Commit 68473d31ef426d44f700e0b079af374482c15230

Authored by Adhidarma Hadiwinoto
1 parent ab524b7ebe
Exists in master

penanganan ETIMEDOUT

Showing 1 changed file with 3 additions and 0 deletions Inline Diff

1 var xmlrpc = require('xmlrpc'); 1 var xmlrpc = require('xmlrpc');
2 var url = require('url'); 2 var url = require('url');
3 var math = require('mathjs'); 3 var math = require('mathjs');
4 var winston = require('winston'); 4 var winston = require('winston');
5 var redis = require('redis'); 5 var redis = require('redis');
6 var resendDelay = require('sate24/resend-delay.js'); 6 var resendDelay = require('sate24/resend-delay.js');
7 var LRU = require('lru-cache'); 7 var LRU = require('lru-cache');
8 8
9 var aaa; 9 var aaa;
10 var logger; 10 var logger;
11 var config; 11 var config;
12 var _callbackReport; 12 var _callbackReport;
13 var redisClient; 13 var redisClient;
14 14
15 var taskHistory = LRU({max: 500, maxAge: 1000 * 3600 * 2}); 15 var taskHistory = LRU({max: 500, maxAge: 1000 * 3600 * 2});
16 16
17 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 17 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
18 18
19 function callbackReport(requestId, responseCode, message, dontResendDelay, raw) { 19 function callbackReport(requestId, responseCode, message, dontResendDelay, raw) {
20 var responseToSave = { 20 var responseToSave = {
21 parsed: { 21 parsed: {
22 MESSAGE: message, 22 MESSAGE: message,
23 } 23 }
24 }; 24 };
25 25
26 if (raw) { 26 if (raw) {
27 responseToSave.raw = raw; 27 responseToSave.raw = raw;
28 } else { 28 } else {
29 responseToSave.raw = message; 29 responseToSave.raw = message;
30 } 30 }
31 31
32 if (responseCode != '68' || dontResendDelay) { 32 if (responseCode != '68' || dontResendDelay) {
33 resendDelay.cancel(requestId); 33 resendDelay.cancel(requestId);
34 } else { 34 } else {
35 getTaskFromHistory(requestId, function(err, archivedTask) { 35 getTaskFromHistory(requestId, function(err, archivedTask) {
36 if (archivedTask) { 36 if (archivedTask) {
37 logger.verbose('DEBUG', {archivedTask: archivedTask}); 37 logger.verbose('DEBUG', {archivedTask: archivedTask});
38 resendDelay.register(archivedTask); 38 resendDelay.register(archivedTask);
39 } 39 }
40 }); 40 });
41 } 41 }
42 42
43 _callbackReport(requestId, responseCode, message, null, responseToSave); 43 _callbackReport(requestId, responseCode, message, null, responseToSave);
44 } 44 }
45 45
46 function createRedisClient(host, port) { 46 function createRedisClient(host, port) {
47 if (!host && !port) { 47 if (!host && !port) {
48 logger.info('Not creating redis client because unspecified host or port'); 48 logger.info('Not creating redis client because unspecified host or port');
49 return; 49 return;
50 } 50 }
51 51
52 try { 52 try {
53 redisClient = redis.createClient(port, host); 53 redisClient = redis.createClient(port, host);
54 } catch(err) { 54 } catch(err) {
55 logger.warn("Error creating redis client to " + host + ':' + port); 55 logger.warn("Error creating redis client to " + host + ':' + port);
56 } 56 }
57 } 57 }
58 58
59 function topupRequest(task) { 59 function topupRequest(task) {
60 aaa.insertTaskToMongoDb(task); 60 aaa.insertTaskToMongoDb(task);
61 61
62 getTaskFromHistory(task, function(err, archivedTask) { 62 getTaskFromHistory(task, function(err, archivedTask) {
63 putTaskToHistory(task); 63 putTaskToHistory(task);
64 64
65 if (archivedTask) { 65 if (archivedTask) {
66 logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask}); 66 logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask});
67 checkStatus(task); 67 checkStatus(task);
68 } else { 68 } else {
69 _topupRequest(task); 69 _topupRequest(task);
70 } 70 }
71 }); 71 });
72 } 72 }
73 73
74 function _topupRequest(task, pendingOnConnectError) { 74 function _topupRequest(task, pendingOnConnectError) {
75 75
76 if (!aaa.isTodayTrx(task)) { 76 if (!aaa.isTodayTrx(task)) {
77 callbackReport(task.requestId, '68', 'Terdeteksi transaksi beda hari, batal kirim ke supplier. Silahkan cek webreport', true); 77 callbackReport(task.requestId, '68', 'Terdeteksi transaksi beda hari, batal kirim ke supplier. Silahkan cek webreport', true);
78 return; 78 return;
79 } 79 }
80 80
81 var partnerUrl = url.parse(config.h2h_out.partner); 81 var partnerUrl = url.parse(config.h2h_out.partner);
82 var clientOptions = { 82 var clientOptions = {
83 host: partnerUrl.hostname, 83 host: partnerUrl.hostname,
84 port: partnerUrl.port, 84 port: partnerUrl.port,
85 path: partnerUrl.pathname 85 path: partnerUrl.pathname
86 }; 86 };
87 87
88 var client; 88 var client;
89 if (partnerUrl.protocol == 'https:') { 89 if (partnerUrl.protocol == 'https:') {
90 client = xmlrpc.createSecureClient(clientOptions); 90 client = xmlrpc.createSecureClient(clientOptions);
91 } else { 91 } else {
92 client = xmlrpc.createClient(clientOptions); 92 client = xmlrpc.createClient(clientOptions);
93 } 93 }
94 94
95 var params = { 95 var params = {
96 MSISDN: config.h2h_out.userid, 96 MSISDN: config.h2h_out.userid,
97 REQUESTID: task['requestId'], 97 REQUESTID: task['requestId'],
98 PIN: config.h2h_out.password, 98 PIN: config.h2h_out.password,
99 NOHP: task['destination'], 99 NOHP: task['destination'],
100 NOM: task['remoteProduct'] 100 NOM: task['remoteProduct']
101 }; 101 };
102 102
103 var methodName = 'topUpRequest'; 103 var methodName = 'topUpRequest';
104 logger.info('Preparing XMLRPC request', {methodname: methodName, params: params, partnerUrl: partnerUrl.href}); 104 logger.info('Preparing XMLRPC request', {methodname: methodName, params: params, partnerUrl: partnerUrl.href});
105 105
106 client.methodCall(methodName, [ params ], function (error, value) { 106 client.methodCall(methodName, [ params ], function (error, value) {
107 107
108 // Results of the method response 108 // Results of the method response
109 109
110 if (error) { 110 if (error) {
111 var rc = '68'; 111 var rc = '68';
112 var msg = 'XMLRPC Client Error: ' + error; 112 var msg = 'XMLRPC Client Error: ' + error;
113 113
114 if (!pendingOnConnectError && (error.code == 'ECONNREFUSED' || error.code == 'EHOSTUNREACH')) { 114 if (!pendingOnConnectError && (error.code == 'ECONNREFUSED' || error.code == 'EHOSTUNREACH')) {
115 rc = '91'; 115 rc = '91';
116 msg = 'XMLRPC Client Error on connecting'; 116 msg = 'XMLRPC Client Error on connecting';
117 } else if (!pendingOnConnectError && error.code == 'ETIMEDOUT' && error.syscall == "connect") {
118 rc = '91';
119 msg = 'XMLRPC Client Error on connecting';
117 } 120 }
118 121
119 callbackReport(task['requestId'], rc, msg, null, JSON.stringify({methodName: methodName, error: error, body: error.body})); 122 callbackReport(task['requestId'], rc, msg, null, JSON.stringify({methodName: methodName, error: error, body: error.body}));
120 return; 123 return;
121 } 124 }
122 125
123 logger.info('Got XMLRPC response from partner for', {methodName: methodName, response_message: value}); 126 logger.info('Got XMLRPC response from partner for', {methodName: methodName, response_message: value});
124 127
125 if (value['RESPONSECODE'] == '94') { 128 if (value['RESPONSECODE'] == '94') {
126 logger.info('Change RC 94 to 68'); 129 logger.info('Change RC 94 to 68');
127 value['RESPONSECODE'] = '68'; 130 value['RESPONSECODE'] = '68';
128 } 131 }
129 132
130 var msg = prefixMessageWithSN(value); 133 var msg = prefixMessageWithSN(value);
131 134
132 callbackReport( 135 callbackReport(
133 task.requestId, value['RESPONSECODE'], msg, null, JSON.stringify({methodName: methodName, response: value}) 136 task.requestId, value['RESPONSECODE'], msg, null, JSON.stringify({methodName: methodName, response: value})
134 ); 137 );
135 }); 138 });
136 } 139 }
137 140
138 function prefixMessageWithSN(data) { 141 function prefixMessageWithSN(data) {
139 142
140 if (data['RESPONSECODE'] != '00') { 143 if (data['RESPONSECODE'] != '00') {
141 return data['MESSAGE']; 144 return data['MESSAGE'];
142 } 145 }
143 146
144 if (data['MESSAGE'].search(/^SN=.+;/) == -1) { 147 if (data['MESSAGE'].search(/^SN=.+;/) == -1) {
145 if (data['SN'] && data['SN'].trim()) { 148 if (data['SN'] && data['SN'].trim()) {
146 return 'SN=' + data['SN'].trim() + '; ' + data['MESSAGE']; 149 return 'SN=' + data['SN'].trim() + '; ' + data['MESSAGE'];
147 } 150 }
148 else if (config.h2h_out.parse_sn == 'YES') { 151 else if (config.h2h_out.parse_sn == 'YES') {
149 return 'SN=' + parseSN(data['MESSAGE']) + '; ' + data['MESSAGE']; 152 return 'SN=' + parseSN(data['MESSAGE']) + '; ' + data['MESSAGE'];
150 } 153 }
151 } 154 }
152 155
153 return data['MESSAGE']; 156 return data['MESSAGE'];
154 } 157 }
155 158
156 function createServer() { 159 function createServer() {
157 160
158 logger.info('Creating XML-RPC server on port ' + config.h2h_out.listen_port); 161 logger.info('Creating XML-RPC server on port ' + config.h2h_out.listen_port);
159 var serverOptions = { 162 var serverOptions = {
160 port: config.h2h_out.listen_port 163 port: config.h2h_out.listen_port
161 }; 164 };
162 165
163 var server = xmlrpc.createServer(serverOptions); 166 var server = xmlrpc.createServer(serverOptions);
164 167
165 server.on('NotFound', function (method, params) { 168 server.on('NotFound', function (method, params) {
166 logger.warn('Unknown method recevied on XMLRPC server', {xmlrpc_method: method, xmlrpc_params: params}); 169 logger.warn('Unknown method recevied on XMLRPC server', {xmlrpc_method: method, xmlrpc_params: params});
167 }); 170 });
168 171
169 server.on('topUpReport', function (err, params, callback) { 172 server.on('topUpReport', function (err, params, callback) {
170 173
171 logger.info('Got XMLRPC topUpReport request from partner', {xmlrpc_method: 'topUpReport', xmlrpc_params: params}); 174 logger.info('Got XMLRPC topUpReport request from partner', {xmlrpc_method: 'topUpReport', xmlrpc_params: params});
172 175
173 var paramscount = params.length; 176 var paramscount = params.length;
174 for (var i = 0; i < paramscount; i++) { 177 for (var i = 0; i < paramscount; i++) {
175 var value = params[i]; 178 var value = params[i];
176 179
177 if (value['RESPONSECODE'] == '94') { 180 if (value['RESPONSECODE'] == '94') {
178 logger.info('Change RC 94 to 68'); 181 logger.info('Change RC 94 to 68');
179 value['RESPONSECODE'] = '68'; 182 value['RESPONSECODE'] = '68';
180 } 183 }
181 184
182 var msg = prefixMessageWithSN(value); 185 var msg = prefixMessageWithSN(value);
183 186
184 callbackReport( 187 callbackReport(
185 value['REQUESTID'], value['RESPONSECODE'], msg, null, JSON.stringify({methodName: 'topUpReport', msg: value}) 188 value['REQUESTID'], value['RESPONSECODE'], msg, null, JSON.stringify({methodName: 'topUpReport', msg: value})
186 ); 189 );
187 } 190 }
188 191
189 callback(null, 'ACK REPORT OK'); 192 callback(null, 'ACK REPORT OK');
190 }) 193 })
191 194
192 } 195 }
193 196
194 function getBalanceFromMessage(message, balance_regex) { 197 function getBalanceFromMessage(message, balance_regex) {
195 if (!balance_regex) { 198 if (!balance_regex) {
196 if (config && config.globals && config.globals.balance_regex) { 199 if (config && config.globals && config.globals.balance_regex) {
197 balance_regex = config.globals.balance_regex; 200 balance_regex = config.globals.balance_regex;
198 } 201 }
199 } 202 }
200 203
201 if (!balance_regex) { 204 if (!balance_regex) {
202 return; 205 return;
203 } 206 }
204 207
205 try { 208 try {
206 var re = new RegExp(balance_regex); 209 var re = new RegExp(balance_regex);
207 var matches = message.match(re); 210 var matches = message.match(re);
208 211
209 var result = matches[1]; 212 var result = matches[1];
210 result = result.replace(/\./g, ''); 213 result = result.replace(/\./g, '');
211 result = result.replace(/,/g, ''); 214 result = result.replace(/,/g, '');
212 215
213 216
214 return Number(result); 217 return Number(result);
215 } 218 }
216 catch(err) { 219 catch(err) {
217 return; 220 return;
218 } 221 }
219 } 222 }
220 223
221 function updateBalance(message) { 224 function updateBalance(message) {
222 var balance = getBalanceFromMessage(message); 225 var balance = getBalanceFromMessage(message);
223 if (balance) { 226 if (balance) {
224 logger.info('Balance: ' + balance); 227 logger.info('Balance: ' + balance);
225 aaa.updateBalance(balance); 228 aaa.updateBalance(balance);
226 } 229 }
227 } 230 }
228 231
229 function checkStatus(task) { 232 function checkStatus(task) {
230 233
231 if (Number(config.globals.topup_request_on_check_status)) { 234 if (Number(config.globals.topup_request_on_check_status)) {
232 _topupRequest(task, true); 235 _topupRequest(task, true);
233 return; 236 return;
234 } 237 }
235 238
236 var partnerUrl = url.parse(config.h2h_out.partner); 239 var partnerUrl = url.parse(config.h2h_out.partner);
237 var clientOptions = { 240 var clientOptions = {
238 host: partnerUrl.hostname 241 host: partnerUrl.hostname
239 , port: partnerUrl.port 242 , port: partnerUrl.port
240 , path: partnerUrl.pathname 243 , path: partnerUrl.pathname
241 }; 244 };
242 logger.info('XMLRPC client options:'); 245 logger.info('XMLRPC client options:');
243 logger.info(clientOptions); 246 logger.info(clientOptions);
244 247
245 var client; 248 var client;
246 if (partnerUrl.protocol == 'https:') { 249 if (partnerUrl.protocol == 'https:') {
247 client = xmlrpc.createSecureClient(clientOptions); 250 client = xmlrpc.createSecureClient(clientOptions);
248 } else { 251 } else {
249 client = xmlrpc.createClient(clientOptions); 252 client = xmlrpc.createClient(clientOptions);
250 } 253 }
251 254
252 var methodName = 'topUpInquiry'; 255 var methodName = 'topUpInquiry';
253 256
254 var params = { 257 var params = {
255 REQUESTID: task['requestId'], 258 REQUESTID: task['requestId'],
256 MSISDN: config.h2h_out.userid, 259 MSISDN: config.h2h_out.userid,
257 PIN: config.h2h_out.password, 260 PIN: config.h2h_out.password,
258 NOHP: task['destination'] 261 NOHP: task['destination']
259 }; 262 };
260 263
261 logger.info('Requesting topUpInquiry', {params: params}); 264 logger.info('Requesting topUpInquiry', {params: params});
262 265
263 client.methodCall(methodName, [ params ], function (error, value) { 266 client.methodCall(methodName, [ params ], function (error, value) {
264 // Results of the method response 267 // Results of the method response
265 if (error) { 268 if (error) {
266 logger.warn('Error requesting topUpInquiry: ', {err: error, params: params}); 269 logger.warn('Error requesting topUpInquiry: ', {err: error, params: params});
267 callbackReport( 270 callbackReport(
268 task.requestId, '68', 'Error requesting topUpInquiry: ' + error, null, JSON.stringify({methodName: methodName, error: error}) 271 task.requestId, '68', 'Error requesting topUpInquiry: ' + error, null, JSON.stringify({methodName: methodName, error: error})
269 ); 272 );
270 return; 273 return;
271 } 274 }
272 logger.info('Method response for \'' + methodName, {response: value}); 275 logger.info('Method response for \'' + methodName, {response: value});
273 276
274 callbackReport(task.requestId, value['RESPONSECODE'], value['MESSAGE'], null, JSON.stringify({methodName: methodName, response: value})); 277 callbackReport(task.requestId, value['RESPONSECODE'], value['MESSAGE'], null, JSON.stringify({methodName: methodName, response: value}));
275 }); 278 });
276 } 279 }
277 280
278 function start(options) { 281 function start(options) {
279 if (!options) { 282 if (!options) {
280 console.log('Undefined options, terminating....'); 283 console.log('Undefined options, terminating....');
281 process.exit(1); 284 process.exit(1);
282 } 285 }
283 286
284 if (options.config) { 287 if (options.config) {
285 config = options.config; 288 config = options.config;
286 } else { 289 } else {
287 console.log('Undefined options.config, terminating....') 290 console.log('Undefined options.config, terminating....')
288 process.exit(1); 291 process.exit(1);
289 } 292 }
290 293
291 if (options.aaa) { 294 if (options.aaa) {
292 aaa = options.aaa; 295 aaa = options.aaa;
293 _callbackReport = options.aaa.callbackReportWithPushToMongoDb; 296 _callbackReport = options.aaa.callbackReportWithPushToMongoDb;
294 } else { 297 } else {
295 console.log('Undefined options.aaa, terminating....') 298 console.log('Undefined options.aaa, terminating....')
296 process.exit(1); 299 process.exit(1);
297 } 300 }
298 301
299 if (options && options.logger) { 302 if (options && options.logger) {
300 logger = options.logger; 303 logger = options.logger;
301 } else { 304 } else {
302 logger = new winston.Logger({ 305 logger = new winston.Logger({
303 transports: [ 306 transports: [
304 new (winston.transports.Console)() 307 new (winston.transports.Console)()
305 ] 308 ]
306 }); 309 });
307 } 310 }
308 311
309 createRedisClient(config.globals.redis_host, config.globals.redis_port); 312 createRedisClient(config.globals.redis_host, config.globals.redis_port);
310 createServer(); 313 createServer();
311 314
312 var resendDelayOptions = { 315 var resendDelayOptions = {
313 config: config, 316 config: config,
314 topupRequest: checkStatus, 317 topupRequest: checkStatus,
315 logger: logger 318 logger: logger
316 }; 319 };
317 320
318 if (Number(config.globals.topup_request_on_resend_delay)) { 321 if (Number(config.globals.topup_request_on_resend_delay)) {
319 resendDelayOptions.topupRequest = topupRequest; 322 resendDelayOptions.topupRequest = topupRequest;
320 } 323 }
321 324
322 resendDelay.init(resendDelayOptions); 325 resendDelay.init(resendDelayOptions);
323 } 326 }
324 327
325 function parseSN(message, _config) { 328 function parseSN(message, _config) {
326 329
327 if (!_config) { 330 if (!_config) {
328 _config = config; 331 _config = config;
329 } 332 }
330 333
331 var sn_regex = new RegExp(_config.h2h_out.sn_pattern); 334 var sn_regex = new RegExp(_config.h2h_out.sn_pattern);
332 var sn_match = message.match(sn_regex); 335 var sn_match = message.match(sn_regex);
333 336
334 if (sn_match <= 0) { 337 if (sn_match <= 0) {
335 logger.info('SN Not found: ' + message); 338 logger.info('SN Not found: ' + message);
336 return ''; 339 return '';
337 } 340 }
338 341
339 var match_index = 0; 342 var match_index = 0;
340 if (_config.h2h_out.sn_match_index) { 343 if (_config.h2h_out.sn_match_index) {
341 match_index = Number(_config.h2h_out.sn_match_index); 344 match_index = Number(_config.h2h_out.sn_match_index);
342 } 345 }
343 346
344 var sn = sn_match[match_index]; 347 var sn = sn_match[match_index];
345 348
346 if (_config.h2h_out.sn_remove_whitespace) { 349 if (_config.h2h_out.sn_remove_whitespace) {
347 sn = sn.replace(/\s/g, ''); 350 sn = sn.replace(/\s/g, '');
348 } 351 }
349 352
350 var sn_remove_patterns = []; 353 var sn_remove_patterns = [];
351 if (_config.h2h_out.sn_remove_patterns && _config.h2h_out.sn_remove_patterns_separator) { 354 if (_config.h2h_out.sn_remove_patterns && _config.h2h_out.sn_remove_patterns_separator) {
352 sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator); 355 sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator);
353 } 356 }
354 var count = sn_remove_patterns.length; 357 var count = sn_remove_patterns.length;
355 358
356 for(var i = 0; i < count; i++) { 359 for(var i = 0; i < count; i++) {
357 360
358 //sn = sn.replace(sn_remove_patterns[i], ''); 361 //sn = sn.replace(sn_remove_patterns[i], '');
359 362
360 var re = new RegExp(sn_remove_patterns[i], 'g'); 363 var re = new RegExp(sn_remove_patterns[i], 'g');
361 sn = sn.replace(re, ''); 364 sn = sn.replace(re, '');
362 } 365 }
363 366
364 //sn = paddingSN(sn, _config); 367 //sn = paddingSN(sn, _config);
365 368
366 return sn.trim(); 369 return sn.trim();
367 } 370 }
368 371
369 function getTaskKey(task, chipInfo) { 372 function getTaskKey(task, chipInfo) {
370 var requestId; 373 var requestId;
371 374
372 if (typeof task === 'string') { 375 if (typeof task === 'string') {
373 requestId = task; 376 requestId = task;
374 } else { 377 } else {
375 try { 378 try {
376 requestId = task.requestId; 379 requestId = task.requestId;
377 } 380 }
378 catch(e) { 381 catch(e) {
379 logger.warn('Something wrong', {task: task}); 382 logger.warn('Something wrong', {task: task});
380 console.trace('Cekidot'); 383 console.trace('Cekidot');
381 process.exit(1); 384 process.exit(1);
382 } 385 }
383 386
384 } 387 }
385 388
386 if (!chipInfo && config && config.globals && config.globals.gateway_name) { 389 if (!chipInfo && config && config.globals && config.globals.gateway_name) {
387 chipInfo = config.globals.gateway_name; 390 chipInfo = config.globals.gateway_name;
388 } 391 }
389 392
390 return chipInfo + '.hitachi.rid:' + requestId; 393 return chipInfo + '.hitachi.rid:' + requestId;
391 } 394 }
392 395
393 396
394 function putTaskToHistory(task, cb) { 397 function putTaskToHistory(task, cb) {
395 if (Number(config.globals.no_dupe_check)) { 398 if (Number(config.globals.no_dupe_check)) {
396 if (cb) { cb(); } 399 if (cb) { cb(); }
397 return; 400 return;
398 } 401 }
399 var key = getTaskKey(task, config.globals.gateway_name); 402 var key = getTaskKey(task, config.globals.gateway_name);
400 logger.verbose('Saving task to history LRU', {key: key, task: task}); 403 logger.verbose('Saving task to history LRU', {key: key, task: task});
401 404
402 try { 405 try {
403 taskHistory.set(key, JSON.parse(JSON.stringify(task))); 406 taskHistory.set(key, JSON.parse(JSON.stringify(task)));
404 } catch (e) { } 407 } catch (e) { }
405 408
406 putTaskToRedis(task, cb); 409 putTaskToRedis(task, cb);
407 } 410 }
408 411
409 function putTaskToRedis(task, cb) { 412 function putTaskToRedis(task, cb) {
410 if (!redisClient) { 413 if (!redisClient) {
411 logger.verbose('Not saving to redis because of undefined redisClient') 414 logger.verbose('Not saving to redis because of undefined redisClient')
412 if (cb) { cb(); } 415 if (cb) { cb(); }
413 return; 416 return;
414 } 417 }
415 418
416 var key = getTaskKey(task, config.globals.gateway_name); 419 var key = getTaskKey(task, config.globals.gateway_name);
417 logger.verbose('Saving task to redis', {key: key, task: task}); 420 logger.verbose('Saving task to redis', {key: key, task: task});
418 421
419 redisClient.set(key, JSON.stringify(task), function() { 422 redisClient.set(key, JSON.stringify(task), function() {
420 redisClient.expire(key, 3600*24*30); 423 redisClient.expire(key, 3600*24*30);
421 if (cb) { 424 if (cb) {
422 cb(); 425 cb();
423 } 426 }
424 }); 427 });
425 } 428 }
426 429
427 function getTaskFromHistory(task, cb) { 430 function getTaskFromHistory(task, cb) {
428 logger.verbose('Getting task from history', {task: task}); 431 logger.verbose('Getting task from history', {task: task});
429 var key = getTaskKey(task, config.globals.gateway_name); 432 var key = getTaskKey(task, config.globals.gateway_name);
430 var archive = taskHistory.get(key); 433 var archive = taskHistory.get(key);
431 434
432 if (archive) { 435 if (archive) {
433 if (cb) { cb(null, archive); } 436 if (cb) { cb(null, archive); }
434 } 437 }
435 else { 438 else {
436 getTaskFromRedis(task, cb); 439 getTaskFromRedis(task, cb);
437 } 440 }
438 } 441 }
439 442
440 function getTaskFromRedis(task, cb) { 443 function getTaskFromRedis(task, cb) {
441 if (!redisClient) { 444 if (!redisClient) {
442 if (cb) { cb(null, null); } 445 if (cb) { cb(null, null); }
443 return; 446 return;
444 } 447 }
445 448
446 var key = getTaskKey(task, config.globals.gateway_name); 449 var key = getTaskKey(task, config.globals.gateway_name);
447 redisClient.get(key, function(err, result) { 450 redisClient.get(key, function(err, result) {
448 if (err) { 451 if (err) {
449 logger.warn('Error retrieving task from redis', {err: err}); 452 logger.warn('Error retrieving task from redis', {err: err});
450 cb(err, null); 453 cb(err, null);
451 return; 454 return;
452 } 455 }
453 456
454 var task; 457 var task;
455 try { 458 try {
456 task = JSON.parse(result); 459 task = JSON.parse(result);
457 } 460 }
458 catch(e) { 461 catch(e) {
459 logger.warn('Exception on parsing redis result as a json', {err: e}); 462 logger.warn('Exception on parsing redis result as a json', {err: e});
460 } 463 }
461 464
462 cb(null, task); 465 cb(null, task);
463 }) 466 })
464 } 467 }
465 468
466 exports.start = start; 469 exports.start = start;
467 exports.topupRequest = topupRequest; 470 exports.topupRequest = topupRequest;
468 exports.getBalanceFromMessage = getBalanceFromMessage; 471 exports.getBalanceFromMessage = getBalanceFromMessage;
469 exports.checkStatus = checkStatus; 472 exports.checkStatus = checkStatus;
470 473