apiServerEntry = (storage, {name, apiServerUrl, apiPath, imagePreviewSuffixes, entrySuffix, concurrent, timeout}) => {
  let currentErrors = 0;

  const test = entry => {
    if (currentErrors > ERROR_THRESHOLD) {
      return false;
    } else if (!getEntryFileBySuffixes(storage, entry, imagePreviewSuffixes) || storage.hasFile(entry, entrySuffix)) {
      return false;
    } else if (entry.type === 'image' || entry.type === 'rawImage') {
      return true;
    } else {
      return false;
    }
  }

  const task = async (entry) =>{
    const t0 = Date.now();
    const imagePreviewSuffix = getEntryFileBySuffixes(storage, entry, imagePreviewSuffixes);
    const buffer = await storage.readFile(entry, imagePreviewSuffix)

    const options = {
      url: `${apiServerUrl}${apiPath}`,
      method: 'POST',
      headers: { 'Content-Type': 'image/jpeg' },
      body: buffer,
      encoding: null,
      timeout: timeout * 1000,
    }
    const data = await simpleFetch(options)
    await storage.writeFile(entry, entrySuffix, data)
    log.debug(t0, `Fetched ${name} for ${entry}`);
  }

  const taskFacade = async (entry) => {
    return task(entry)
      .then(() => {
        if (currentErrors > 0) {
          currentErrors--
        }
      })
      .catch(err => {
        log.warn(err, `Failed to fetch ${name} for ${entry}: ${err}`)
        currentErrors++;
        if (currentErrors > ERROR_THRESHOLD) {
          log.warn(`Too many errors. Skip processing of ${name}`);
        }
      })
  }

  return parallel({task: conditionalAsyncTask(test, taskFacade), concurrent});
}
@param {import('@home-gallery/types').TStorage} storage