comprodls-sdk 2.82.0-alpha → 2.83.0-alpha

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.
package/lib/comprodls.js CHANGED
@@ -46,7 +46,6 @@ var drive = require('./services/drive');
46
46
  var taxonomy = require('./services/taxonomy');
47
47
  var rules = require('./services/rules');
48
48
  var datasyncmanager = require('./services/datasyncmanager');
49
- var helloWorld = require('./services/helloworld');
50
49
 
51
50
 
52
51
  /*********************************
@@ -146,7 +145,6 @@ comproDLS.prototype.Invitations = invitations;
146
145
  comproDLS.prototype.Workflows = workflows;
147
146
  comproDLS.prototype.Integrations = integrations;
148
147
  comproDLS.prototype.Drive = drive;
149
- comproDLS.prototype.HelloWorld = helloWorld;
150
148
  comproDLS.prototype.Taxonomy = taxonomy;
151
149
  comproDLS.prototype.Rules = rules;
152
150
  comproDLS.prototype.Datasyncmanager = datasyncmanager;
@@ -53,8 +53,7 @@ exports.REALM_HOSTS = {
53
53
  PRODUCT: 'http://dls-asgard-thor-1453383019.us-west-2.elb.amazonaws.com/lb-product',
54
54
  ANALYTICS: 'http://dls-asgard-thor-1453383019.us-west-2.elb.amazonaws.com/lb-analytics',
55
55
  INTEGRATION: 'http://dls-asgard-thor-1453383019.us-west-2.elb.amazonaws.com/lb-integrations',
56
- DRIVE: 'http://dls-asgard-thor-1453383019.us-west-2.elb.amazonaws.com/lb-drive',
57
- HELLOWORLD: 'http://dls-asgard-thor-1453383019.us-west-2.elb.amazonaws.com/lb-helloworld'
56
+ DRIVE: 'http://dls-asgard-thor-1453383019.us-west-2.elb.amazonaws.com/lb-drive'
58
57
  }
59
58
  },
60
59
  CUP: {
@@ -371,10 +370,6 @@ exports.DRIVE_API_URLS = {
371
370
  documents: '/accounts/{accountid}/users/{userid}/documents/multi'
372
371
  };
373
372
 
374
- exports.HELLO_WORLD_API_URLS = {
375
- sayHello: '/org/{orgid}/hello?name=map-team'
376
- };
377
-
378
373
  exports.TAXONOMY_API_URLS = {
379
374
  associateTagsWithEntity: '/org/{orgId}/taxonomy/associate-tags-with-entity',
380
375
  tags: '/org/{orgId}/context/{context}/taxonomy/{taxonomyId}/tags'
@@ -26,9 +26,7 @@
26
26
  var ERROR_TYPES = {
27
27
  "API_ERROR": "API_ERROR",
28
28
  "SDK_ERROR": "SDK_ERROR",
29
- "CHANNEL_SUBSCRIPTION": "CHANNEL_SUBSCRIPTION",
30
- "UNEXPECTED_ERROR": "UNEXPECTED_ERROR",
31
- "POLLING_INITIATION": "POLLING_INITIATION"
29
+ "CHANNEL_SUBSCRIPTION": "CHANNEL_SUBSCRIPTION"
32
30
  };
33
31
 
34
32
  var ERROR_CATEGORY = {
@@ -2369,12 +2369,7 @@ function deleteAssignedPath(options) {
2369
2369
  item_type: 'string', //mandatory, ['dls-internal','external']
2370
2370
  dls_product_code: 'string' //mandatory only if item_type is 'dls-internal'
2371
2371
  }
2372
- ],
2373
- "rules": {}, // Optional
2374
- "context": { // Optional (Needed for system event only)
2375
- "bundle-code": "string",
2376
- "space_key": "string"
2377
- }
2372
+ ]
2378
2373
  }
2379
2374
  }
2380
2375
  */
@@ -80,8 +80,11 @@ function _connect(pubnubCW, options) {
80
80
  'publishKey': options.publishKey,
81
81
  'subscribeKey': options.subscribeKey,
82
82
  'ssl': true
83
- }
84
- });
83
+ },
84
+ 'pollingEndpoint': options.pollingEndpoint,
85
+ 'pollingIterations': options.pollingIterations || 10, // Default polling iterations is 10
86
+ 'pollingInterval': options.pollingInterval, // Default polling interval is exponential backoff
87
+ });
85
88
  }
86
89
 
87
90
  function _cleanup(pubnubCW) { pubnubCW.cleanup(); }
@@ -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,13 @@ 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;
31
+ var bPollingInitiated = false;
24
32
 
25
33
  /** ###### END OF MODULE GLOBALS */
26
34
 
@@ -36,6 +44,9 @@ module.exports = function () {
36
44
  //Returning the adaptor (Plain Javascript object)
37
45
  return {
38
46
  "on": function (channelObj, handler) {
47
+ // If PubNub fails, we will fetch the events from this timestamp
48
+ _startTimestampForPolling = Date.now();
49
+
39
50
  var pubNubChannel;
40
51
  var channelContext = [];
41
52
 
@@ -64,6 +75,9 @@ module.exports = function () {
64
75
  _eventEmitter.on(channelObj.channel, handler);
65
76
  bStatusSubscribed = true;
66
77
  }
78
+
79
+ // Clean up the old events
80
+ _checkOldBubbledEvents();
67
81
  },
68
82
  "getMySubscriptionStatus": __getMySubscriptionStatus
69
83
  };
@@ -77,6 +91,10 @@ module.exports = function () {
77
91
 
78
92
  var _translatePubnubStatus = function(status, options) {
79
93
  var channels = [], error, successObj;
94
+
95
+ // If polling has been initiated, ignore all punnub status
96
+ if (bPollingInitiated) return;
97
+
80
98
  switch (status.category) {
81
99
  case "PNConnectedCategory":
82
100
  if(status.operation === "PNSubscribeOperation") {
@@ -138,11 +156,10 @@ module.exports = function () {
138
156
  break;
139
157
  case "PNNetworkIssuesCategory":
140
158
  if(status.operation === 'PNSubscribeOperation') {
141
- if(!options.accountId) {
159
+ if(!options.accountId || !_userOptions.pollingEndpoint) {
142
160
  error = {
143
- message: "Missing mandatory parameters to initiate polling operation - accountId",
144
- status: status.statusCode,
145
- type: helpers.errors.ERROR_TYPES.POLLING_INITIATION,
161
+ message: "Polling initiation error: Missing mandatory parameters to initiate polling operation - [accountId, pollingEndpoint]",
162
+ status: status.statusCode
146
163
  };
147
164
  error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
148
165
  _eventEmitter.emit('pushx_status', error);
@@ -156,6 +173,9 @@ module.exports = function () {
156
173
  * The wrapper supports multiple channels, but the APP currently uses a single channel only.
157
174
  * Polling will also limited to a single channel.
158
175
  */
176
+ _pollingCounter = 0;
177
+ _pollForEvents();
178
+ bPollingInitiated = true;
159
179
  }
160
180
  }
161
181
  else {
@@ -168,9 +188,8 @@ module.exports = function () {
168
188
  default:
169
189
  // Emit error for other status-category received from pubnub
170
190
  error = {
171
- message: "PushX Error",
191
+ message: "PushX Error: unexpected error",
172
192
  status: status.statusCode,
173
- type: helpers.errors.ERROR_TYPES.UNEXPECTED_ERROR,
174
193
  pushXError: status
175
194
  };
176
195
  error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
@@ -207,6 +226,7 @@ module.exports = function () {
207
226
  * @returns PROMISE.
208
227
  */
209
228
  var __setup = function (userOptions) {
229
+
210
230
  var pubnubConfig = userOptions.pubnub;
211
231
  pubnubConfig.uuid = userOptions.userid;
212
232
  var accountId = userOptions.accountid;
@@ -245,8 +265,169 @@ module.exports = function () {
245
265
  _globalSubscription = [];
246
266
  bStatusSubscribed = false;
247
267
  _globalSubscriptionStatus = {};
268
+ bPollingInitiated = false;
248
269
  }
249
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
+
296
+ // Safe check to avoid poll for events if the channel name or start time is not set
297
+ // This handles an edge condition where the clearTimeout doesn't work as expected
298
+ if (!params.channelname || !params.starttime) {
299
+ return;
300
+ }
301
+
302
+ var requestAPI = request.get(_userOptions.pollingEndpoint).query(params);
303
+
304
+ requestAPI
305
+ .end(function(error, response) {
306
+
307
+ if (!error) {
308
+ // Bubble the connected status
309
+ if (_pollingCounter === 0) {
310
+ // Set the status of the channel to subscribed
311
+ if(_globalSubscriptionStatus[_globalSubscription[0]]) {
312
+ _globalSubscriptionStatus[_globalSubscription[0]].status = 'subscribed';
313
+ }
314
+
315
+ var successObj = {
316
+ category: 'PUSHX',
317
+ type: 'CHANNEL_SUBSCRIPTION',
318
+ status: 'SUCCESS',
319
+ message: 'Success: Subscribed successfully.',
320
+ httpcode: 200,
321
+ data: {
322
+ payload: {
323
+ channels: _globalSubscription
324
+ },
325
+ message: 'Success: Subscribed successfully.'
326
+ }
327
+ };
328
+ _eventEmitter.emit('pushx_status', successObj);
329
+ }
330
+
331
+ // Bubble the received events
332
+ _bubblePolledEvents(response.body);
333
+
334
+ // Increase the counter
335
+ _pollingCounter++;
336
+ }
337
+
338
+ // Polling will be done only for specific number of times
339
+ if (_pollingCounter > _userOptions.pollingIterations) {
340
+ var error = {
341
+ message: "Polling error: Polling limit exceeded",
342
+ status: 429
343
+ };
344
+ error = new PUSHXError(helpers.errors.ERROR_CATEGORY.PUSHX, error);
345
+ _eventEmitter.emit('pushx_status', error);
346
+ } else {
347
+ var timeoutDelay;
348
+
349
+ // If the polling interval is provided, use that
350
+ if (_userOptions.pollingInterval) {
351
+ timeoutDelay = _userOptions.pollingInterval * 60 * 1000;
352
+ } else {
353
+ // Else, use exponential backoff
354
+ timeoutDelay = parseInt(Math.pow(1.3, _pollingCounter) * 10 * 1000, 10);
355
+ }
356
+
357
+ // Set timeout for next poll
358
+ if (timeoutDelay) {
359
+ _setTimeoutIDForPolling = setTimeout(_pollForEvents, timeoutDelay);
360
+ }
361
+ }
362
+ });
363
+ };
364
+
365
+ /**
366
+ * Bubble the polled events to the FE APP
367
+ * @param {*} events - Events recieved from the polling endpoint
368
+ */
369
+ var _bubblePolledEvents = function (events) {
370
+ // Load the old events from the session storage
371
+ var oldEventData = _checkOldBubbledEvents();
372
+
373
+ var oldEvents = oldEventData.events;
374
+ var sessionStorageKey = oldEventData.key;
375
+
376
+ for (var i = 0; i < events.entities.length; i++) {
377
+ var event = events.entities[i];
378
+ var eventId = event.pk + '_' + event.sk;
379
+
380
+ // Check if the event is already emitted
381
+ if (!oldEvents[eventId]) {
382
+ oldEvents[eventId] = event.context.start_time;
383
+
384
+ // Emit the event
385
+ _eventEmitter.emit(_globalSubscription[0], event);
386
+ }
387
+ }
388
+
389
+ // Save the bubbled events to session storage
390
+ sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
391
+ };
392
+
393
+ /**
394
+ * Check the old bubbled events and remove the events that are older than the start timestamp
395
+ * @returns {object} - Object containing the key and the events
396
+ */
397
+ var _checkOldBubbledEvents = function () {
398
+ var sessionStorageKey = 'comprodls.old_pushx_events.' + _userOptions.userid + '.' + _globalSubscription[0];
399
+ var oldEvents = sessionStorage.getItem(sessionStorageKey);
400
+
401
+ if (oldEvents) {
402
+ try {
403
+ oldEvents = JSON.parse(oldEvents);
404
+ } catch (e) {
405
+ oldEvents = {};
406
+ }
407
+
408
+ var oldEventIds = Object.keys(oldEvents);
409
+
410
+ // Remove the events that are older than the start timestamp
411
+ for (var i = 0; i < oldEventIds.length; i++) {
412
+ var oldEventId = oldEventIds[i];
413
+
414
+ if (oldEvents[oldEventId] < _startTimestampForPolling) {
415
+ delete oldEvents[oldEventId];
416
+ }
417
+ }
418
+
419
+ // If the number of events has changed, save the events
420
+ if (oldEventIds.length !== Object.keys(oldEvents).length) {
421
+ sessionStorage.setItem(sessionStorageKey, JSON.stringify(oldEvents));
422
+ }
423
+ } else {
424
+ oldEvents = {};
425
+ }
426
+
427
+ return {
428
+ key: sessionStorageKey,
429
+ events: oldEvents
430
+ };
250
431
  };
251
432
 
252
433
  return { // Return public methods for the wrapper
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "comprodls-sdk",
3
3
  "description": "comproDLS SDK for JavaScript",
4
- "version": "2.82.0-alpha",
4
+ "version": "2.83.0-alpha",
5
5
  "author": {
6
6
  "name": "Compro Technologies Private Limited",
7
7
  "url": "http://www.comprotechnologies.com/"
@@ -1,81 +0,0 @@
1
- /*************************************************************************
2
- *
3
- * COMPRO CONFIDENTIAL
4
- * __________________
5
- *
6
- * [2015] - [2020] Compro Technologies Private Limited
7
- * All Rights Reserved.
8
- *
9
- * NOTICE: All information contained herein is, and remains
10
- * the property of Compro Technologies Private Limited. The
11
- * intellectual and technical concepts contained herein are
12
- * proprietary to Compro Technologies Private Limited and may
13
- * be covered by U.S. and Foreign Patents, patents in process,
14
- * and are protected by trade secret or copyright law.
15
- *
16
- * Dissemination of this information or reproduction of this material
17
- * is strictly forbidden unless prior written permission is obtained
18
- * from Compro Technologies Pvt. Ltd..
19
- ***************************************************************************/
20
-
21
- /***********************************************************
22
- * comproDLS SDK Hello World Service
23
- * Function for calling Hello World API.
24
- ************************************************************/
25
-
26
- var q = require('q');
27
- var request = require('superagent');
28
- var Agent = require('agentkeepalive');
29
-
30
- var helpers = require('../../helpers');
31
- var DLSError = helpers.errors.DLSError;
32
-
33
- module.exports = helloWorld;
34
-
35
- var keepaliveAgent = new Agent({
36
- timeout: 60000,
37
- freeSocketTimeout: 30000
38
- });
39
-
40
- /*********************************
41
- * Public Function definitions
42
- **********************************/
43
- function helloWorld() {
44
- return {
45
- sayHello: sayHello.bind(this)
46
- };
47
- }
48
-
49
- /*
50
- options = {
51
- accountid : 'string', //mandatory
52
- extuserid : 'string', //mandatory
53
- }
54
- */
55
- function sayHello() {
56
- var self = this;
57
- var dfd = q.defer();
58
-
59
- // Passed all validations, Construct API url
60
- var url = self.config.DEFAULT_HOSTS.HELLOWORLD + self.config.HELLO_WORLD_API_URLS.sayHello;
61
- var urlOptions = {
62
- orgid: self.orgId,
63
- };
64
- url = helpers.api.constructAPIUrl(url, urlOptions);
65
-
66
- // Setup request with URL
67
- var requestAPI = request.get(url);
68
-
69
- if (self.traceid) { requestAPI.set('X-Amzn-Trace-Id', self.traceid); }
70
-
71
- requestAPI.end(function (err, response) {
72
- if (err) {
73
- err = new DLSError(helpers.errors.ERROR_TYPES.API_ERROR, err);
74
- dfd.reject(err);
75
- } else {
76
- dfd.resolve(response.body);
77
- }
78
- });
79
-
80
- return dfd.promise;
81
- }