interceptor-manager.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import loggerFactory from '~/utils/logger';
  2. const logger = loggerFactory('growi:InterceptorManager');
  3. /**
  4. * the manager class of Interceptor
  5. */
  6. class InterceptorManager {
  7. constructor() {
  8. this.interceptorAndOrders = []; /* [
  9. {interceptor: instanceA, order: 200 },
  10. {interceptor: instanceB, order: 100 },
  11. ...
  12. ] */
  13. this.interceptors = [];
  14. }
  15. /**
  16. * add an Interceptor
  17. * @param {BasicInterceptor} interceptor
  18. * @param {number} order
  19. */
  20. addInterceptor(interceptor, order) {
  21. this.addInterceptors([interceptor], order);
  22. }
  23. /**
  24. * add Interceptors
  25. * @param {BasicInterceptor[]} interceptors
  26. * @param {number} order
  27. */
  28. addInterceptors(interceptors, order) {
  29. let isDefaultOrder = false;
  30. if (order == null) {
  31. order = 100; // eslint-disable-line
  32. isDefaultOrder = true;
  33. }
  34. const interceptorIds = interceptors.map((i) => { return i.getId() });
  35. logger.info(`'addInterceptors' invoked. adding interceptors '${interceptorIds}' at order=${order}${isDefaultOrder ? '(default)' : ''}`);
  36. this.interceptorAndOrders = this.interceptorAndOrders.concat(
  37. interceptors.map((interceptor) => {
  38. return { interceptor, order };
  39. }),
  40. );
  41. // sort asc
  42. this.interceptorAndOrders.sort((a, b) => { return a.order - b.order });
  43. // store sorted list
  44. this.interceptors = this.interceptorAndOrders.map((obj) => { return obj.interceptor });
  45. const thisInterceptorIds = this.interceptors.map((i) => { return i.getId() });
  46. logger.info(`interceptors list has initialized: ${thisInterceptorIds}`);
  47. }
  48. /**
  49. * process Interceptors
  50. *
  51. * @param {string} contextName
  52. * @param {any} args
  53. */
  54. process(contextName, ...args) {
  55. logger.debug(`processing the context '${contextName}'`);
  56. // filter only contexts matches to specified 'contextName'
  57. const matchInterceptors = this.interceptors.filter((i) => { return i.isInterceptWhen(contextName) });
  58. const parallels = matchInterceptors.filter((i) => { return i.isProcessableParallel() });
  59. const sequentials = matchInterceptors.filter((i) => { return !i.isProcessableParallel() });
  60. logger.debug(`${parallels.length} parallel interceptors found.`);
  61. logger.debug(`${sequentials.length} sequencial interceptors found.`);
  62. return Promise.all(
  63. // parallel
  64. parallels.map((interceptor) => {
  65. return this.doProcess(interceptor, contextName, ...args);
  66. })
  67. // sequential
  68. .concat([
  69. sequentials.reduce((prevPromise, nextInterceptor) => {
  70. return prevPromise.then((...results) => { return this.doProcess(nextInterceptor, contextName, ...results) });
  71. }, Promise.resolve(...args)/* initial Promise */),
  72. ]),
  73. ).then(() => {
  74. logger.debug(`end processing the context '${contextName}'`);
  75. });
  76. }
  77. doProcess(interceptor, contextName, ...args) {
  78. return interceptor.process(contextName, ...args)
  79. .then((...results) => {
  80. logger.debug(`processing '${interceptor.getId()}' in the context '${contextName}'`);
  81. return Promise.resolve(...results);
  82. })
  83. .catch((reason) => {
  84. logger.debug(`failed when processing '${interceptor.getId()}' in the context '${contextName}'`);
  85. logger.debug(reason);
  86. return Promise.resolve(...args);
  87. });
  88. }
  89. }
  90. export default InterceptorManager;