middleware/transaction.js

/**
 * @module middleware/transaction
 * @exports trasnactionMiddleware
 */
import domain from 'domain';
import uuidv4 from 'uuid/v4';

/**
 * Adds a transaction identifier to every request to track a request's control
 * flow through the entire lifetime of the request, including across
 * asynchronous calls. We use a transactoin ID instead of the session ID or
 * user since both are persistent(ish) identification.
 *
 * @see {@link https://nodejs.org/api/domain.html}
 *
 * @param  {Object}   ctx  The Koa context
 * @param  {Function} next The next middleware or handler in the connect chain
 * @return {void}
 */
export default (ctx: Object, next: Function): void => {
  const transactionId: string = uuidv4();
  const transaction: Object = domain.create();

  // eslint-disable-next-line no-param-reassign
  ctx.transactionId = transactionId;

  transaction.add(ctx);
  transaction.data = {
    id: transactionId,
    ctx,
  };

  return new Promise((resolve, reject) => {
    transaction.run(async () => {
      try {
        await next();
        return resolve();
      } catch (e) {
        return reject(e);
      }
    });
  });
};