appManager.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. var async = require('async');
  2. var utils = require('../../util/utils');
  3. var logger = require('pomelo-logger').getLogger('pomelo', __filename);
  4. var transactionLogger = require('pomelo-logger').getLogger('transaction-log', __filename);
  5. var transactionErrorLogger = require('pomelo-logger').getLogger('transaction-error-log', __filename);
  6. var manager = module.exports;
  7. manager.transaction = function(name, conditions, handlers, retry) {
  8. if(!retry) {
  9. retry = 1;
  10. }
  11. if(typeof name !== 'string') {
  12. logger.error('transaction name is error format, name: %s.', name);
  13. return;
  14. }
  15. if(typeof conditions !== 'object' || typeof handlers !== 'object') {
  16. logger.error('transaction conditions parameter is error format, conditions: %j, handlers: %j.', conditions, handlers);
  17. return;
  18. }
  19. var cmethods=[] ,dmethods=[], cnames=[], dnames=[];
  20. for(var key in conditions) {
  21. if(typeof key !== 'string' || typeof conditions[key] !== 'function') {
  22. logger.error('transaction conditions parameter is error format, condition name: %s, condition function: %j.', key, conditions[key]);
  23. return;
  24. }
  25. cnames.push(key);
  26. cmethods.push(conditions[key]);
  27. }
  28. var i = 0;
  29. // execute conditions
  30. async.forEachSeries(cmethods, function(method, cb) {
  31. method(cb);
  32. transactionLogger.info('[%s]:[%s] condition is executed.', name, cnames[i]);
  33. i++;
  34. }, function(err) {
  35. if(err) {
  36. process.nextTick(function() {
  37. transactionLogger.error('[%s]:[%s] condition is executed with err: %j.', name, cnames[--i], err.stack);
  38. var log = {
  39. name: name,
  40. method: cnames[i],
  41. time: Date.now(),
  42. type: 'condition',
  43. description: err.stack
  44. };
  45. transactionErrorLogger.error(JSON.stringify(log));
  46. });
  47. return;
  48. } else {
  49. // execute handlers
  50. process.nextTick(function() {
  51. for(var key in handlers) {
  52. if(typeof key !== 'string' || typeof handlers[key] !== 'function') {
  53. logger.error('transcation handlers parameter is error format, handler name: %s, handler function: %j.', key, handlers[key]);
  54. return;
  55. }
  56. dnames.push(key);
  57. dmethods.push(handlers[key]);
  58. }
  59. var flag = true;
  60. var times = retry;
  61. // do retry if failed util retry times
  62. async.whilst(
  63. function() {
  64. return retry > 0 && flag;
  65. },
  66. function(callback) {
  67. var j = 0;
  68. retry--;
  69. async.forEachSeries(dmethods, function(method, cb) {
  70. method(cb);
  71. transactionLogger.info('[%s]:[%s] handler is executed.', name, dnames[j]);
  72. j++;
  73. }, function(err) {
  74. if(err) {
  75. process.nextTick(function() {
  76. transactionLogger.error('[%s]:[%s]:[%s] handler is executed with err: %j.', name, dnames[--j], times-retry, err.stack);
  77. var log = {
  78. name: name,
  79. method: dnames[j],
  80. retry: times-retry,
  81. time: Date.now(),
  82. type: 'handler',
  83. description: err.stack
  84. };
  85. transactionErrorLogger.error(JSON.stringify(log));
  86. utils.invokeCallback(callback);
  87. });
  88. return;
  89. }
  90. flag = false;
  91. utils.invokeCallback(callback);
  92. process.nextTick(function() {
  93. transactionLogger.info('[%s] all conditions and handlers are executed successfully.', name);
  94. });
  95. });
  96. },
  97. function(err) {
  98. if(err) {
  99. logger.error('transaction process is executed with error: %j', err);
  100. }
  101. // callback will not pass error
  102. }
  103. );
  104. });
  105. }
  106. });
  107. };