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