/** {@inheritDoc} */
  public String doExport(final String descriptorGroup, final String fileName, final boolean async) {

    final AsyncContext ctx = getAsyncContext();

    final String imgVault = systemService.getImageRepositoryDirectory();

    // Max char of report to UI since it will get huge and simply will crash the UI, not to mention
    // traffic cost.
    final int logSize =
        NumberUtils.toInt(
            nodeService.getConfiguration().get(AttributeNamesKeys.System.IMPORT_JOB_LOG_SIZE), 100);
    // Timeout - just in case runnable crashes and we need to unlock through timeout.
    final int timeout =
        NumberUtils.toInt(
            nodeService.getConfiguration().get(AttributeNamesKeys.System.IMPORT_JOB_TIMEOUT_MS),
            100);

    final String rootPath = resolveExportDirectory();
    final String absFile = resolveExportFile(fileName);

    return doJob(
        new JobContextImpl(
            async,
            new JobStatusListenerImpl(logSize, timeout),
            new HashMap<String, Object>() {
              {
                put(JobContextKeys.EXPORT_DESCRIPTOR_GROUP, descriptorGroup);
                put(JobContextKeys.EXPORT_FILE, absFile);
                put(JobContextKeys.IMAGE_VAULT_PATH, imgVault);
                put(JobContextKeys.EXPORT_DIRECTORY_ROOT, rootPath);
                putAll(ctx.getAttributes());
              }
            }));
  }
  private long determineExpiryInMs() {

    final String av =
        systemService.getAttributeValue(AttributeNamesKeys.System.CART_ABANDONED_TIMEOUT_SECONDS);

    if (av != null && StringUtils.isNotBlank(av)) {
      long expiry = NumberUtils.toInt(av) * 1000L;
      if (expiry > 0) {
        return expiry;
      }
    }
    return this.abandonedTimeoutMs;
  }