<commit_before>'use strict';

/**
 * super-microservices
 *
 * @author <NAME> <<EMAIL>>
 */

const assert = require('assert');
const utils = require('./utils');
const error = require('./error');
const Service = require('./service');
const ServiceNotFoundError = error.ServiceNotFoundError;

function formatErrorObject(err) {
  if (err instanceof Error) {
    const ret = {};
    for (const i in err) {
      ret[i] = err[i];
    }
    ret.message = err.message;
    return ret;
  }
  return err;
}

class Context {

  /**
   * Context
   *
   * @param {Object} options
   *   - {Object} manager
   *   - {Object} service
   *   - {String} requestId
   *   - {Object} params
   *   - {Function} callback
   *   - {Object} logRecorder
   */
  constructor(options) {

    const opts = Object.assign({}, options || {});

    // 严格要求输入的params必须是一个对象
    if (opts.params) {
      const paramsType = typeof opts.params;
      assert(paramsType === 'object', `new Context({params}): params只能为一个对象，不能为${ paramsType }类型`);
    }

    // manager对象
    this._manager = opts.manager || null;
    // service对象
    this._service = opts.service || null;
    // 拼接requestId
    this.requestId = opts.requestId || utils.newRequestId(Context.REQUEST_ID_MIN_SIZE);
    // 复制并冻结参数对象
    this.params = Object.freeze(Object.assign({}, opts.params || {}));
    // 回调函数
    this._callback = opts.callback || null;
    // 打印日志函数
    this._logRecorder = opts.logRecorder || null;

    // 检查manager参数
    assert(!!this._manager, `new Context({ manager }): manager不能为空`);
    assert(typeof this._manager.getService === 'function', `new Context({ manager }): manager.getService()未定义`);
    assert(typeof this._manager.newContext === 'function', `new Context({ manager }): manager.newContext()未定义`);

    // 检查其他参数
    if (this._callback) assert(typeof this._callback === 'function', `new Context({ callback }): callback必须为一个函数`);
    if (this._logRecorder) assert(utils.isValidLogRecorder(this._logRecorder), `new Context({ logRecorder }): logRecorder必须是一个有效的LogRecorder`);
    if (this._service) assert(this._service instanceof Service, `new Context(service): service必须为Service的实例`);

    // 执行结束相关的信息
    this.startTime = new Date();
    this.stopTime = null;
    this.spent = 0;
    this._isCallbacked = false;

    this._counter = 0;

    this.writeJSON('call', this.params);
  }

  /**
   * 返回结果
   *
   * @param {Object} ret
   */
  result(ret) {
    this.callback(null, ret);
  }

  /**
   * 返回错误
   *
   * @param {Error} err
   */
  error(err) {
    this.callback(err);
  }

  /**
   * 执行回调
   *
   * @param {Error} err
   * @param {Object} ret
   */
  callback(err, ret) {
    setImmediate(() => {

      // 不允许重复执行回调
      if (this._isCallbacked) {
        return this.debug('context.callback(): callback many times, ignore');
      }

      this.stopTime = new Date();
      this.spent = this.stopTime - this.startTime;

      if (!this._callback) {
        return this.debug('context.callback(): has no callback handler');
      }

      this._isCallbacked = true;
      if (err) {
        this.writeJSON('error', formatErrorObject(err));
      } else {
        this.writeJSON('result', ret);<commit_msg>feat: ctx.error() 时 err 对象会自动带上 $requestId<commit_after>'use strict';

/**
 * super-microservices
 *
 * @author <NAME> <<EMAIL>>
 */

const assert = require('assert');
const utils = require('./utils');
const error = require('./error');
const Service = require('./service');
const ServiceNotFoundError = error.ServiceNotFoundError;

function formatErrorObject(err) {
  if (err instanceof Error) {
    const ret = {};
    for (const i in err) {
      ret[i] = err[i];
    }
    ret.message = err.message;
    return ret;
  }
  return err;
}

class Context {

  /**
   * Context
   *
   * @param {Object} options
   *   - {Object} manager
   *   - {Object} service
   *   - {String} requestId
   *   - {Object} params
   *   - {Function} callback
   *   - {Object} logRecorder
   */
  constructor(options) {

    const opts = Object.assign({}, options || {});

    // 严格要求输入的params必须是一个对象
    if (opts.params) {
      const paramsType = typeof opts.params;
      assert(paramsType === 'object', `new Context({params}): params只能为一个对象，不能为${ paramsType }类型`);
    }

    // manager对象
    this._manager = opts.manager || null;
    // service对象
    this._service = opts.service || null;
    // 拼接requestId
    this.requestId = opts.requestId || utils.newRequestId(Context.REQUEST_ID_MIN_SIZE);
    // 复制并冻结参数对象
    this.params = Object.freeze(Object.assign({}, opts.params || {}));
    // 回调函数
    this._callback = opts.callback || null;
    // 打印日志函数
    this._logRecorder = opts.logRecorder || null;

    // 检查manager参数
    assert(!!this._manager, `new Context({ manager }): manager不能为空`);
    assert(typeof this._manager.getService === 'function', `new Context({ manager }): manager.getService()未定义`);
    assert(typeof this._manager.newContext === 'function', `new Context({ manager }): manager.newContext()未定义`);

    // 检查其他参数
    if (this._callback) assert(typeof this._callback === 'function', `new Context({ callback }): callback必须为一个函数`);
    if (this._logRecorder) assert(utils.isValidLogRecorder(this._logRecorder), `new Context({ logRecorder }): logRecorder必须是一个有效的LogRecorder`);
    if (this._service) assert(this._service instanceof Service, `new Context(service): service必须为Service的实例`);

    // 执行结束相关的信息
    this.startTime = new Date();
    this.stopTime = null;
    this.spent = 0;
    this._isCallbacked = false;

    this._counter = 0;

    this.writeJSON('call', this.params);
  }

  /**
   * 返回结果
   *
   * @param {Object} ret
   */
  result(ret) {
    this.callback(null, ret);
  }

  /**
   * 返回错误
   *
   * @param {Error} err
   */
  error(err) {
    this.callback(err);
  }

  /**
   * 执行回调
   *
   * @param {Error} err
   * @param {Object} ret
   */
  callback(err, ret) {
    setImmediate(() => {

      // 不允许重复执行回调
      if (this._isCallbacked) {
        return this.debug('context.callback(): callback many times, ignore');
      }

      this.stopTime = new Date();
      this.spent = this.stopTime - this.startTime;

      if (!this._callback) {
        return this.debug('context.callback(): has no callback handler');
      }

      // 如果出错，自动加上 requestId 信息
      if (err) {
        // eslint-disable-next-line
        err.$requestId = this.requestId;
      }

      this._isCallbacked = true;
      if (err) {
        this.writeJSON('error', formatErrorObject(err));
      } else {
        this.writeJSON('result', ret);
{'fraction_non_alphanumeric': 0.15605875152998777, 'fraction_numerical': 0.0006119951040391676, 'mean_word_length': 2.7612197928653623, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1402787', 'n_tokens_mistral': 2248, 'n_tokens_neox': 2295, 'n_words': 446}