Source: service/transaction-service.js

const Service = require('./service');
const HttpRequestBuilder = require('../http/http-request-builder');
const PATH_TRANSACTIONS = require('./service-paths').PATH_TRANSACTIONS;

const LoggingUtils = require('../logging/logging-utils');
const StringUtils = require('../util/string-utils');

const RepositoryClientConfig =
  require('../repository/repository-client-config');
const TransactionalRepositoryClient =
  require('../transaction/transactional-repository-client');

/**
 * Service for working with the transactions endpoint.
 *
 * @author Mihail Radkov
 * @author Svilen Velikov
 * @author Teodossi Dossev
 */
class TransactionService extends Service {
  /**
   * Instantiates the transaction service with the supplied executor and
   * repository client config.
   *
   * @param {Function} httpRequestExecutor used to execute HTTP requests
   * @param {RepositoryClientConfig} repositoryClientConfig used to create
   * transaction client configurations
   */
  constructor(httpRequestExecutor, repositoryClientConfig) {
    super(httpRequestExecutor);
    this.repositoryClientConfig = repositoryClientConfig;
  }

  /**
   * Starts a transaction and produces a {@link TransactionalRepositoryClient}.
   *
   * The transactions ID is extracted from the <code>location</code> header and
   * is used as  endpoint for the produced TransactionalRepositoryClient.
   *
   * If no transaction isolation level is provided, the server will use its
   * default isolation level.
   *
   * @param {string} [isolationLevel] an optional parameter to specify the
   * transaction's level of isolation; for possible values see
   * {@link TransactionIsolationLevel}
   *
   * @return {Promise<TransactionalRepositoryClient>} transactional client
   */
  beginTransaction(isolationLevel) {
    const requestBuilder = HttpRequestBuilder.httpPost(PATH_TRANSACTIONS)
      .addParam('isolation-level', isolationLevel);

    return this.httpRequestExecutor(requestBuilder).then((response) => {
      const locationUrl = response.getHeaders()['location'];
      if (StringUtils.isBlank(locationUrl)) {
        this.logger.error(LoggingUtils.getLogPayload(response,
          {isolationLevel}), 'Cannot obtain transaction ID');
        return Promise.reject(new Error('Couldn\'t obtain transaction ID'));
      }

      const config = this.getTransactionalClientConfig(locationUrl);
      const transactionClient = new TransactionalRepositoryClient(config);

      this.logger.debug(LoggingUtils.getLogPayload(response, {isolationLevel}),
        'Started transaction');
      return transactionClient;
    });
  }

  /**
   * Builds client configuration for transactional repository out of the
   * provided repository client config and the supplied location URL.
   *
   * @private
   *
   * @param {string} locationUrl the url for the transactional repo endpoint
   *
   * @return {RepositoryClientConfig} the built transaction client config
   */
  getTransactionalClientConfig(locationUrl) {
    const config = this.repositoryClientConfig;
    const transactionConfig = new RepositoryClientConfig(config.getEndpoint())
      .setEndpoints([locationUrl])
      .setHeaders(config.getHeaders())
      .setDefaultRDFMimeType(config.getDefaultRDFMimeType())
      .setReadTimeout(config.getReadTimeout())
      .setWriteTimeout(config.getWriteTimeout());

    if (config.shouldAuthenticate()) {
      const userName = config.getUsername();
      const password = config.getPass();
      if (config.getBasicAuthentication()) {
        transactionConfig.useBasicAuthentication(userName, password);
      } else if (config.getGdbTokenAuthentication()) {
        transactionConfig.useGdbTokenAuthentication(userName, password);
      }
    }

    return transactionConfig;
  }

  /**
   * @inheritDoc
   */
  getServiceName() {
    return 'TransactionService';
  }
}

module.exports = TransactionService;