interceptor-manager.js 3.3 KB

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