Commit fdb2abd41e9dafca6fb0a059b8f4c1ff34e762f1

Authored by Adhidarma Hadiwinoto
1 parent b450476d61
Exists in master

registerResendDelay

Showing 4 changed files with 313 additions and 3 deletions Side-by-side Diff

... ... @@ -0,0 +1,301 @@
  1 +var redis = require('redis');
  2 +var moment = require('moment');
  3 +var LRU = require('lru-cache');
  4 +
  5 +var config;
  6 +var logger;
  7 +var partner;
  8 +var imConfig;
  9 +var redisClient;
  10 +
  11 +var resendHandlers = LRU({max: 2000, maxAge: 1000 * 3600 * 36});
  12 +
  13 +function init(options) {
  14 + if (options && options.config) {
  15 + config = options.config;
  16 + }
  17 +
  18 + if (options && options.logger) {
  19 + logger = options.logger;
  20 + }
  21 +
  22 + createRedisClient(config.globals.redis_host, config.globals.redis_port);
  23 + readImConfig();
  24 +}
  25 +
  26 +function createRedisClient(host, port) {
  27 + try {
  28 + redisClient = redis.createClient(port, host);
  29 + } catch(err) {
  30 + logger.warn("Error creating redis client to " + host + ':' + port);
  31 + }
  32 +}
  33 +
  34 +function readImConfig(filename) {
  35 +
  36 + if (!filename) {
  37 + filename = process.cwd() + '/config.im.json';
  38 + }
  39 +
  40 + try {
  41 + imConfig = require(filename);
  42 + }
  43 + catch(e) {
  44 + imConfig = {};
  45 + }
  46 +
  47 + logger.verbose('IM Config', {imConfig: imConfig});
  48 + return imConfig;
  49 +}
  50 +
  51 +function getPatternFromMessage(message, pattern, patternMatchIndex) {
  52 + var re = new RegExp(pattern);
  53 + var matches = message.match(re);
  54 +
  55 + if (!matches) {
  56 + return null;
  57 + }
  58 +
  59 + if (patternMatchIndex < matches.length) {
  60 + return matches[patternMatchIndex];
  61 + } else {
  62 + return null;
  63 + }
  64 +}
  65 +
  66 +function getPatternsFromMessage(message, patterns) {
  67 + var patternCount = patterns.length;
  68 + for (var i = 0; i < patternCount; i++) {
  69 +
  70 + var pattern = patterns[i];
  71 +
  72 + var result = getPatternFromMessage(message, pattern.pattern, pattern.matchIndex);
  73 + if (result) {
  74 + return result;
  75 + }
  76 + }
  77 +}
  78 +
  79 +function getTaskKey(task, chipInfo, today) {
  80 + if (!chipInfo && config && config.globals && config.globals.gateway_name) {
  81 + chipInfo = config.globals.gateway_name;
  82 + }
  83 +
  84 + if (task.timestamp && !today) {
  85 + today = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYYMMDD');
  86 + }
  87 +
  88 + return chipInfo + '.trx.date:' + today + '.rProduct:' + task.remoteProduct.toUpperCase() + '.dest:' + task.destination ;
  89 +}
  90 +
  91 +function saveTask(task, cb) {
  92 + var key = getTaskKey(task, config.globals.gateway_name);
  93 + logger.verbose('Saving task', {key: key, task: task});
  94 +
  95 + redisClient.set(key, JSON.stringify(task), function() {
  96 + redisClient.expire(key, 3600*24);
  97 + if (cb) {
  98 + cb();
  99 + }
  100 + });
  101 +}
  102 +
  103 +function getTask(remoteProduct, destination, cb) {
  104 + var dummyTask = {
  105 + remoteProduct: remoteProduct,
  106 + destination: destination,
  107 + }
  108 +
  109 + var key = getTaskKey(dummyTask, config.globals.gateway_name, moment().format('YYYYMMDD'));
  110 + redisClient.get(key, function(err, result) {
  111 + if (err) {
  112 + logger.verbose('getTask: task not found', {key: key, params: dummyTask});
  113 +
  114 + cb(err, null);
  115 + return;
  116 + }
  117 +
  118 + var task = {};
  119 +
  120 + try {
  121 + task = JSON.parse(result);
  122 + }
  123 + catch(e) {
  124 + logger.warn('getTask: Can not parse result', {key: key, params: dummyTask, data: result});
  125 + err = "Can not parse result"
  126 + }
  127 + cb(err, task);
  128 + });
  129 +}
  130 +
  131 +function deleteTask(remoteProduct, destination) {
  132 + var dummyTask = {
  133 + remoteProduct: remoteProduct,
  134 + destination: destination,
  135 + }
  136 +
  137 + var key = getTaskKey(dummyTask, config.globals.gateway_name, moment().format('YYYYMMDD'));
  138 +
  139 + try {
  140 + redisClient.del(key);
  141 + }
  142 + catch(e) {};
  143 +}
  144 +
  145 +function createMessage(pattern, keywords) {
  146 + var msg = pattern;
  147 +
  148 + for (var key in keywords) {
  149 + msg = msg.replace('[' + key + ']', keywords[key]);
  150 + }
  151 + return msg;
  152 +}
  153 +
  154 +function getRemoteProductFromMessage(msg) {
  155 + return getPatternsFromMessage(msg, imConfig.product_patterns);
  156 +}
  157 +
  158 +function getDestinationFromMessage(msg) {
  159 + return getPatternsFromMessage(msg, imConfig.destination_patterns);
  160 +}
  161 +
  162 +function getSnFromMessage(msg) {
  163 + return getPatternsFromMessage(msg, imConfig.sn_patterns);
  164 +}
  165 +
  166 +function getRcFromMessage(msg) {
  167 + var rcs = imConfig.response_codes;
  168 + var rcsCount = rcs.length;
  169 +
  170 + for (var i = 0; i < rcsCount; i++) {
  171 +
  172 + var item = rcs[i];
  173 + var re = new RegExp(item.pattern);
  174 + if (msg.search(re) != -1) {
  175 + return item.rc;
  176 + }
  177 +
  178 + }
  179 + return '68';
  180 +}
  181 +
  182 +function isAllowedFrom(sender) {
  183 + if (!config || !config.h2h_out || !config.h2h_out.allowed_response_from) {
  184 + return true;
  185 + }
  186 +
  187 + whitelist = config.h2h_out.allowed_response_from.split(',');
  188 + whitelistCount = whitelist.length;
  189 +
  190 + for(var i=0; i<whitelistCount; i++) {
  191 + if (sender == whitelist[i]) {
  192 + return true;
  193 + }
  194 + }
  195 +
  196 + return false;
  197 +}
  198 +
  199 +function checkForSameDayDuplicate(task, cbNoDupe, cbDupe, cbDupeWithSameReqId) {
  200 + getTask(task.remoteProduct, task.destination, function(err, archivedTask) {
  201 + if (err) {
  202 + logger.warn('Error on checking same day duplicate', {task: task});
  203 + cbNoDupe(task);
  204 + return;
  205 + }
  206 +
  207 + if (archivedTask && archivedTask.requestId) {
  208 + if (cbDupeWithSameReqId && task.requestId == archivedTask.requestId) {
  209 + logger.verbose('Duplicate trx on same day with same requestId', {task: task});
  210 + cbDupeWithSameReqId(task, archivedTask);
  211 + return;
  212 + }
  213 +
  214 + logger.verbose('Duplicate trx on same day', {task: task, archivedTask: archivedTask});
  215 + cbDupe(task, archivedTask);
  216 + return;
  217 + }
  218 +
  219 + cbNoDupe(task);
  220 + });
  221 +}
  222 +
  223 +function registerResendDelay(task) {
  224 + if (!task.requestId) {
  225 + logger.warn('Invalid task on resendDelay')
  226 + return;
  227 + }
  228 +
  229 + if (!config || !config.globals || !config.globals.auto_resend_on_delay_secs) {
  230 + return;
  231 + }
  232 +
  233 + if (!partner || !partner.topupRequest) {
  234 + logger.warn('Skip request resend delay because partner.topupRequest is not exists');
  235 + return;
  236 + }
  237 +
  238 + var retry = 10;
  239 + var oldHandler = resendHandlers.get(task.requestId);
  240 + if (oldHandler) {
  241 + retry = oldHandler.retry - 1;
  242 + }
  243 +
  244 + if (retry <= 0) {
  245 + logger.verbose('Resend delay retry exceeded', {task: task});
  246 + cancelResendDelay(task);
  247 + return;
  248 + }
  249 +
  250 + logger.info('Resending task request', {task});
  251 + var handlerData = {
  252 + handler: setTimeout(partner.topupRequest, config.globals.auto_resend_on_delay_secs, task),
  253 + task: task,
  254 + retry: retry
  255 + }
  256 +
  257 + resendHandlers.set(task.requestId, handlerData);
  258 +}
  259 +
  260 +function cancelResendDelay(task) {
  261 + if (!task || !task.requestId) {
  262 + logger.warn('Invalid task on cancelResendDelay');
  263 + return;
  264 + }
  265 +
  266 + var oldHandler = resendHandlers.get(task.requestId);
  267 + if (!oldHandler) {
  268 + return;
  269 + }
  270 +
  271 + logger.verbose('Canceling resend delay', {task: task});
  272 +
  273 + try {
  274 + if (oldHandler.handler) {
  275 + clearTimeout(oldHandler.handler);
  276 + }
  277 + }
  278 + catch(e) {};
  279 +
  280 + try {
  281 + resendHandlers.del(task.requestId);
  282 + }
  283 + catch(e) {};
  284 +}
  285 +
  286 +exports.init = init;
  287 +exports.start = init;
  288 +exports.getPatternFromMessage = getPatternFromMessage;
  289 +exports.getPatternsFromMessage = getPatternsFromMessage;
  290 +exports.saveTask = saveTask;
  291 +exports.getTask = getTask;
  292 +exports.readImConfig = readImConfig;
  293 +exports.createMessage = createMessage;
  294 +exports.getRemoteProductFromMessage = getRemoteProductFromMessage;
  295 +exports.getDestinationFromMessage = getDestinationFromMessage;
  296 +exports.getRcFromMessage = getRcFromMessage;
  297 +exports.getSnFromMessage = getSnFromMessage;
  298 +exports.isAllowedFrom = isAllowedFrom;
  299 +exports.checkForSameDayDuplicate = checkForSameDayDuplicate;
  300 +exports.deleteTask = deleteTask;
  301 +exports.registerResendDelay = registerResendDelay;
... ... @@ -18,6 +18,7 @@ var options = {
18 18 'logger': logger,
19 19 'config': config,
20 20 'matrix': matrix,
  21 + 'partner': partner,
21 22 }
22 23  
23 24 var httpServer = HttpServer.start(config, options);
... ... @@ -22,6 +22,7 @@
22 22 "author": "Adhidarma Hadiwinoto <me@adhisimon.org>",
23 23 "license": "ISC",
24 24 "dependencies": {
  25 + "lru-cache": "^4.0.1",
25 26 "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git",
26 27 "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git",
27 28 "yahoomessenger": "^0.1.3-Beta"
1   -var im = require('sate24/im.js')
  1 +var im = require('./im.js')
2 2 var YM = require('yahoomessenger');
3 3 var imAdaptor = require('./adaptor-ym');
4 4  
... ... @@ -52,7 +52,11 @@ function onPM(from, msg) {
52 52 im.deleteTask(remoteProduct, destination);
53 53 }
54 54  
55   - callbackReport(task.requestId, rc, msg);
  55 + if (rc != '68') {
  56 + im.cancelResendDelay(task);
  57 + }
  58 +
  59 + callbackReportWrapper(task.requestId, rc, msg);
56 60 });
57 61 }
58 62  
... ... @@ -114,6 +118,8 @@ function _topupRequest(task) {
114 118 }
115 119  
116 120 im.saveTask(task, function() {
  121 + im.registerResendDelay(task);
  122 +
117 123 var msg = im.createMessage(pattern, keywords);
118 124 imAdaptor.sendMessage(config.h2h_out.partner, msg);
119 125 });
... ... @@ -124,9 +130,10 @@ function topupRequest(task) {
124 130 if (!aaa.isTodayTrx(task)) {
125 131 logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan');
126 132 callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan');
  133 + im.cancelResendDelay(task);
127 134 return;
128 135 }
129   -
  136 +
130 137 im.checkForSameDayDuplicate(task, _topupRequest, onSameDayDupe, _topupRequest);
131 138 }
132 139