comprodls-sdk 2.77.1 → 2.79.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -80,7 +80,10 @@ function _connect(pubnubCW, options) {
|
|
|
80
80
|
'publishKey': options.publishKey,
|
|
81
81
|
'subscribeKey': options.subscribeKey,
|
|
82
82
|
'ssl': true
|
|
83
|
-
}
|
|
83
|
+
},
|
|
84
|
+
'pollingEndpoint': options.pollingEndpoint,
|
|
85
|
+
'pollingIterations': options.pollingIterations || 10, // Default polling iterations is 10
|
|
86
|
+
'pollingInterval': options.pollingInterval || 1, // Default polling interval is 1 minute
|
|
84
87
|
});
|
|
85
88
|
}
|
|
86
89
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
var pubNub = require("pubnub");
|
|
2
|
+
var request = require('superagent');
|
|
2
3
|
var EventEmitter = require("events").EventEmitter;
|
|
3
4
|
var helpers = require('../../helpers');
|
|
4
5
|
|
|
@@ -21,6 +22,12 @@ module.exports = function () {
|
|
|
21
22
|
var _globalSubscription = [];
|
|
22
23
|
var _globalSubscriptionStatus = {};
|
|
23
24
|
var bStatusSubscribed = false;
|
|
25
|
+
/** ID of the setTimeout - used for Polling events when PubNub fails */
|
|
26
|
+
var _setTimeoutIDForPolling;
|
|
27
|
+
/** Timestamp from when the events need to be fetched */
|
|
28
|
+
var _startTimestampForPolling;
|
|
29
|
+
/** Counter for polling */
|
|
30
|
+
var _pollingCounter;
|
|
24
31
|
var bPollingInitiated = false;
|
|
25
32
|
|
|
26
33
|
/** ###### END OF MODULE GLOBALS */
|
|
@@ -37,6 +44,9 @@ module.exports = function () {
|
|
|
37
44
|
//Returning the adaptor (Plain Javascript object)
|
|
38
45
|
return {
|
|
39
46
|
"on": function (channelObj, handler) {
|
|
47
|
+
// If PubNub fails, we will fetch the events from this timestamp
|
|
48
|
+
_startTimestampForPolling = Date.now();
|
|
49
|
+
|
|
40
50
|
var pubNubChannel;
|
|
41
51
|
var channelContext = [];
|
|
42
52
|
|
|
@@ -65,6 +75,9 @@ module.exports = function () {
|
|
|
65
75
|
_eventEmitter.on(channelObj.channel, handler);
|
|
66
76
|
bStatusSubscribed = true;
|
|
67
77
|
}
|
|
78
|
+
|
|
79
|
+
// Clean up the old events
|
|
80
|
+
_checkOldBubbledEvents();
|
|
68
81
|
},
|
|
69
82
|
"getMySubscriptionStatus": __getMySubscriptionStatus
|
|
70
83
|
};
|
|
@@ -143,9 +156,9 @@ module.exports = function () {
|
|
|
143
156
|
break;
|
|
144
157
|
case "PNNetworkIssuesCategory":
|
|
145
158
|
if(status.operation === 'PNSubscribeOperation') {
|
|
146
|
-
if(!options.accountId) {
|
|
159
|
+
if(!options.accountId || !_userOptions.pollingEndpoint) {
|
|
147
160
|
error = {
|
|
148
|
-
message: "Polling initiation error: Missing mandatory parameters to initiate polling operation - accountId",
|
|
161
|
+
message: "Polling initiation error: Missing mandatory parameters to initiate polling operation - [accountId, pollingEndpoint]",
|
|
149
162
|
status: status.statusCode
|
|
150
163
|
};
|
|
151
164
|
error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
|
|
@@ -160,6 +173,8 @@ module.exports = function () {
|
|
|
160
173
|
* The wrapper supports multiple channels, but the APP currently uses a single channel only.
|
|
161
174
|
* Polling will also limited to a single channel.
|
|
162
175
|
*/
|
|
176
|
+
_pollingCounter = 0;
|
|
177
|
+
_pollForEvents();
|
|
163
178
|
bPollingInitiated = true;
|
|
164
179
|
}
|
|
165
180
|
}
|
|
@@ -211,6 +226,7 @@ module.exports = function () {
|
|
|
211
226
|
* @returns PROMISE.
|
|
212
227
|
*/
|
|
213
228
|
var __setup = function (userOptions) {
|
|
229
|
+
|
|
214
230
|
var pubnubConfig = userOptions.pubnub;
|
|
215
231
|
pubnubConfig.uuid = userOptions.userid;
|
|
216
232
|
var accountId = userOptions.accountid;
|
|
@@ -252,6 +268,147 @@ module.exports = function () {
|
|
|
252
268
|
bPollingInitiated = false;
|
|
253
269
|
}
|
|
254
270
|
_pubnubClient = undefined;
|
|
271
|
+
|
|
272
|
+
// Clear the Polling
|
|
273
|
+
if (_setTimeoutIDForPolling) {
|
|
274
|
+
clearTimeout(_setTimeoutIDForPolling);
|
|
275
|
+
// Setting the start time to now to clear the old events
|
|
276
|
+
_startTimestampForPolling = Date.now();
|
|
277
|
+
_checkOldBubbledEvents();
|
|
278
|
+
_setTimeoutIDForPolling = undefined;
|
|
279
|
+
_pollingCounter = undefined;
|
|
280
|
+
_startTimestampForPolling = undefined;
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Polling function
|
|
286
|
+
*/
|
|
287
|
+
var _pollForEvents = function () {
|
|
288
|
+
// Setup request params
|
|
289
|
+
var params = {
|
|
290
|
+
accountid: _userOptions.accountid,
|
|
291
|
+
channelname: _globalSubscription[0],
|
|
292
|
+
starttime: _startTimestampForPolling,
|
|
293
|
+
endtime: Date.now()
|
|
294
|
+
};
|
|
295
|
+
var requestAPI = request.get(_userOptions.pollingEndpoint).query(params);
|
|
296
|
+
|
|
297
|
+
requestAPI
|
|
298
|
+
.end(function(error, response) {
|
|
299
|
+
|
|
300
|
+
if (!error) {
|
|
301
|
+
// Bubble the connected status
|
|
302
|
+
if (_pollingCounter === 0) {
|
|
303
|
+
// Set the status of the channel to subscribed
|
|
304
|
+
if(_globalSubscriptionStatus[_globalSubscription[0]]) {
|
|
305
|
+
_globalSubscriptionStatus[_globalSubscription[0]].status = 'subscribed';
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
var successObj = {
|
|
309
|
+
category: 'PUSHX',
|
|
310
|
+
type: 'CHANNEL_SUBSCRIPTION',
|
|
311
|
+
status: 'SUCCESS',
|
|
312
|
+
message: 'Success: Subscribed successfully.',
|
|
313
|
+
httpcode: 200,
|
|
314
|
+
data: {
|
|
315
|
+
payload: {
|
|
316
|
+
channels: _globalSubscription
|
|
317
|
+
},
|
|
318
|
+
message: 'Success: Subscribed successfully.'
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
_eventEmitter.emit('pushx_status', successObj);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Bubble the received events
|
|
325
|
+
_bubblePolledEvents(response.body);
|
|
326
|
+
|
|
327
|
+
// Increase the counter
|
|
328
|
+
_pollingCounter++;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Polling will be done only for specific number of times
|
|
332
|
+
if (_pollingCounter > _userOptions.pollingIterations) {
|
|
333
|
+
var error = {
|
|
334
|
+
message: "Polling error: Polling limit exceeded",
|
|
335
|
+
status: 429
|
|
336
|
+
};
|
|
337
|
+
error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
|
|
338
|
+
_eventEmitter.emit('pushx_status', error);
|
|
339
|
+
} else {
|
|
340
|
+
// Set timeout for next poll
|
|
341
|
+
_setTimeoutIDForPolling = setTimeout(_pollForEvents, _userOptions.pollingInterval * 60 * 1000);
|
|
342
|
+
}
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Bubble the polled events to the FE APP
|
|
348
|
+
* @param {*} events - Events recieved from the polling endpoint
|
|
349
|
+
*/
|
|
350
|
+
var _bubblePolledEvents = function (events) {
|
|
351
|
+
// Load the old events from the session storage
|
|
352
|
+
var oldEventData = _checkOldBubbledEvents();
|
|
353
|
+
|
|
354
|
+
var oldEvents = oldEventData.events;
|
|
355
|
+
var sessionStorageKey = oldEventData.key;
|
|
356
|
+
|
|
357
|
+
for (var i = 0; i < events.entities.length; i++) {
|
|
358
|
+
var event = events.entities[i];
|
|
359
|
+
var eventId = event.pk + '_' + event.sk;
|
|
360
|
+
|
|
361
|
+
// Check if the event is already emitted
|
|
362
|
+
if (!oldEvents[eventId]) {
|
|
363
|
+
oldEvents[eventId] = event.context.start_time;
|
|
364
|
+
|
|
365
|
+
// Emit the event
|
|
366
|
+
_eventEmitter.emit(_globalSubscription[0], event);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Save the bubbled events to session storage
|
|
371
|
+
sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Check the old bubbled events and remove the events that are older than the start timestamp
|
|
376
|
+
* @returns {object} - Object containing the key and the events
|
|
377
|
+
*/
|
|
378
|
+
var _checkOldBubbledEvents = function () {
|
|
379
|
+
var sessionStorageKey = 'comprodls.old_pushx_events.' + _userOptions.userid + '.' + _globalSubscription[0];
|
|
380
|
+
var oldEvents = sessionStorage.getItem(sessionStorageKey);
|
|
381
|
+
|
|
382
|
+
if (oldEvents) {
|
|
383
|
+
try {
|
|
384
|
+
oldEvents = JSON.parse(oldEvents);
|
|
385
|
+
} catch (e) {
|
|
386
|
+
oldEvents = {};
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
var oldEventIds = Object.keys(oldEvents);
|
|
390
|
+
|
|
391
|
+
// Remove the events that are older than the start timestamp
|
|
392
|
+
for (var i = 0; i < oldEventIds.length; i++) {
|
|
393
|
+
var oldEventId = oldEventIds[i];
|
|
394
|
+
|
|
395
|
+
if (oldEvents[oldEventId] < _startTimestampForPolling) {
|
|
396
|
+
delete oldEvents[oldEventId];
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// If the number of events has changed, save the events
|
|
401
|
+
if (oldEventIds.length !== Object.keys(oldEvents).length) {
|
|
402
|
+
sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
|
|
403
|
+
}
|
|
404
|
+
} else {
|
|
405
|
+
oldEvents = {};
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
return {
|
|
409
|
+
key: sessionStorageKey,
|
|
410
|
+
events: oldEvents
|
|
411
|
+
};
|
|
255
412
|
};
|
|
256
413
|
|
|
257
414
|
return { // Return public methods for the wrapper
|