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