@splitsoftware/splitio-commons 2.0.0-rc.0 → 2.0.0-rc.1

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.
Files changed (108) hide show
  1. package/CHANGES.txt +2 -1
  2. package/cjs/evaluator/Engine.js +1 -1
  3. package/cjs/evaluator/index.js +1 -1
  4. package/cjs/readiness/readinessManager.js +13 -2
  5. package/cjs/sdkClient/sdkClientMethodCS.js +0 -1
  6. package/cjs/sdkFactory/index.js +26 -8
  7. package/cjs/storages/{AbstractSegmentsCacheSync.js → AbstractMySegmentsCacheSync.js} +15 -17
  8. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +5 -5
  9. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +3 -2
  10. package/cjs/storages/inLocalStorage/index.js +1 -1
  11. package/cjs/storages/inMemory/InMemoryStorageCS.js +2 -2
  12. package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +5 -5
  13. package/cjs/storages/inMemory/SegmentsCacheInMemory.js +13 -27
  14. package/cjs/storages/inMemory/SplitsCacheInMemory.js +0 -1
  15. package/cjs/storages/inMemory/UniqueKeysCacheInMemory.js +2 -1
  16. package/cjs/storages/inMemory/UniqueKeysCacheInMemoryCS.js +2 -1
  17. package/cjs/storages/inRedis/RedisAdapter.js +2 -1
  18. package/cjs/storages/inRedis/SegmentsCacheInRedis.js +13 -19
  19. package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +2 -1
  20. package/cjs/storages/pluggable/SegmentsCachePluggable.js +11 -32
  21. package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +2 -1
  22. package/cjs/storages/pluggable/inMemoryWrapper.js +2 -1
  23. package/cjs/sync/offline/syncManagerOffline.js +18 -11
  24. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +12 -28
  25. package/cjs/sync/polling/updaters/splitChangesUpdater.js +2 -1
  26. package/cjs/sync/syncManagerOnline.js +20 -21
  27. package/cjs/trackers/eventTracker.js +12 -10
  28. package/cjs/trackers/impressionsTracker.js +16 -14
  29. package/cjs/trackers/uniqueKeysTracker.js +5 -3
  30. package/cjs/utils/lang/sets.js +12 -2
  31. package/esm/evaluator/Engine.js +1 -1
  32. package/esm/evaluator/index.js +2 -2
  33. package/esm/readiness/readinessManager.js +13 -2
  34. package/esm/sdkClient/sdkClientMethodCS.js +0 -1
  35. package/esm/sdkFactory/index.js +26 -8
  36. package/esm/storages/{AbstractSegmentsCacheSync.js → AbstractMySegmentsCacheSync.js} +14 -16
  37. package/esm/storages/inLocalStorage/MySegmentsCacheInLocal.js +5 -5
  38. package/esm/storages/inLocalStorage/SplitsCacheInLocal.js +3 -2
  39. package/esm/storages/inLocalStorage/index.js +1 -1
  40. package/esm/storages/inMemory/InMemoryStorageCS.js +2 -2
  41. package/esm/storages/inMemory/MySegmentsCacheInMemory.js +5 -5
  42. package/esm/storages/inMemory/SegmentsCacheInMemory.js +13 -27
  43. package/esm/storages/inMemory/SplitsCacheInMemory.js +0 -1
  44. package/esm/storages/inMemory/UniqueKeysCacheInMemory.js +2 -1
  45. package/esm/storages/inMemory/UniqueKeysCacheInMemoryCS.js +2 -1
  46. package/esm/storages/inRedis/RedisAdapter.js +2 -1
  47. package/esm/storages/inRedis/SegmentsCacheInRedis.js +13 -19
  48. package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +2 -1
  49. package/esm/storages/pluggable/SegmentsCachePluggable.js +11 -32
  50. package/esm/storages/pluggable/UniqueKeysCachePluggable.js +2 -1
  51. package/esm/storages/pluggable/inMemoryWrapper.js +2 -1
  52. package/esm/sync/offline/syncManagerOffline.js +18 -11
  53. package/esm/sync/polling/updaters/segmentChangesUpdater.js +12 -28
  54. package/esm/sync/polling/updaters/splitChangesUpdater.js +2 -1
  55. package/esm/sync/syncManagerOnline.js +20 -21
  56. package/esm/trackers/eventTracker.js +12 -10
  57. package/esm/trackers/impressionsTracker.js +16 -14
  58. package/esm/trackers/uniqueKeysTracker.js +5 -3
  59. package/esm/utils/lang/sets.js +10 -1
  60. package/package.json +1 -1
  61. package/src/evaluator/Engine.ts +1 -1
  62. package/src/evaluator/index.ts +2 -2
  63. package/src/readiness/readinessManager.ts +12 -3
  64. package/src/readiness/types.ts +3 -0
  65. package/src/sdkClient/sdkClientMethodCS.ts +0 -2
  66. package/src/sdkFactory/index.ts +28 -9
  67. package/src/sdkFactory/types.ts +2 -0
  68. package/src/storages/{AbstractSegmentsCacheSync.ts → AbstractMySegmentsCacheSync.ts} +13 -28
  69. package/src/storages/inLocalStorage/MySegmentsCacheInLocal.ts +5 -5
  70. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +3 -2
  71. package/src/storages/inLocalStorage/index.ts +1 -1
  72. package/src/storages/inMemory/InMemoryStorageCS.ts +2 -2
  73. package/src/storages/inMemory/MySegmentsCacheInMemory.ts +5 -5
  74. package/src/storages/inMemory/SegmentsCacheInMemory.ts +12 -26
  75. package/src/storages/inMemory/SplitsCacheInMemory.ts +0 -1
  76. package/src/storages/inMemory/UniqueKeysCacheInMemory.ts +2 -1
  77. package/src/storages/inMemory/UniqueKeysCacheInMemoryCS.ts +2 -1
  78. package/src/storages/inRedis/RedisAdapter.ts +2 -1
  79. package/src/storages/inRedis/SegmentsCacheInRedis.ts +13 -22
  80. package/src/storages/inRedis/UniqueKeysCacheInRedis.ts +2 -1
  81. package/src/storages/pluggable/SegmentsCachePluggable.ts +11 -35
  82. package/src/storages/pluggable/UniqueKeysCachePluggable.ts +2 -1
  83. package/src/storages/pluggable/inMemoryWrapper.ts +2 -1
  84. package/src/storages/types.ts +3 -9
  85. package/src/sync/offline/syncManagerOffline.ts +21 -13
  86. package/src/sync/polling/updaters/segmentChangesUpdater.ts +13 -29
  87. package/src/sync/polling/updaters/splitChangesUpdater.ts +2 -1
  88. package/src/sync/syncManagerOnline.ts +17 -17
  89. package/src/sync/types.ts +1 -1
  90. package/src/trackers/eventTracker.ts +11 -8
  91. package/src/trackers/impressionsTracker.ts +13 -10
  92. package/src/trackers/types.ts +1 -0
  93. package/src/trackers/uniqueKeysTracker.ts +6 -4
  94. package/src/utils/lang/sets.ts +11 -1
  95. package/types/readiness/types.d.ts +3 -0
  96. package/types/sdkFactory/types.d.ts +1 -0
  97. package/types/storages/inLocalStorage/MySegmentsCacheInLocal.d.ts +5 -5
  98. package/types/storages/inMemory/MySegmentsCacheInMemory.d.ts +5 -5
  99. package/types/storages/inMemory/SegmentsCacheInMemory.d.ts +5 -7
  100. package/types/storages/inMemory/SplitsCacheInMemory.d.ts +0 -1
  101. package/types/storages/inRedis/SegmentsCacheInRedis.d.ts +6 -3
  102. package/types/storages/pluggable/SegmentsCachePluggable.d.ts +4 -16
  103. package/types/storages/types.d.ts +3 -9
  104. package/types/sync/types.d.ts +1 -1
  105. package/types/trackers/eventTracker.d.ts +1 -1
  106. package/types/trackers/impressionsTracker.d.ts +1 -1
  107. package/types/trackers/types.d.ts +1 -0
  108. package/types/utils/lang/sets.d.ts +1 -0
@@ -1,5 +1,5 @@
1
1
  import { __extends } from "tslib";
2
- import { AbstractSegmentsCacheSync } from '../AbstractSegmentsCacheSync';
2
+ import { AbstractMySegmentsCacheSync } from '../AbstractMySegmentsCacheSync';
3
3
  /**
4
4
  * Default MySegmentsCacheInMemory implementation that stores MySegments in memory.
5
5
  * Supported by all JS runtimes.
@@ -11,13 +11,13 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
11
11
  _this.segmentCache = {};
12
12
  return _this;
13
13
  }
14
- MySegmentsCacheInMemory.prototype.addToSegment = function (name) {
14
+ MySegmentsCacheInMemory.prototype.addSegment = function (name) {
15
15
  if (this.segmentCache[name])
16
16
  return false;
17
17
  this.segmentCache[name] = true;
18
18
  return true;
19
19
  };
20
- MySegmentsCacheInMemory.prototype.removeFromSegment = function (name) {
20
+ MySegmentsCacheInMemory.prototype.removeSegment = function (name) {
21
21
  if (!this.segmentCache[name])
22
22
  return false;
23
23
  delete this.segmentCache[name];
@@ -26,7 +26,7 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
26
26
  MySegmentsCacheInMemory.prototype.isInSegment = function (name) {
27
27
  return this.segmentCache[name] === true;
28
28
  };
29
- MySegmentsCacheInMemory.prototype.setChangeNumber = function (name, changeNumber) {
29
+ MySegmentsCacheInMemory.prototype.setChangeNumber = function (changeNumber) {
30
30
  this.cn = changeNumber;
31
31
  };
32
32
  MySegmentsCacheInMemory.prototype.getChangeNumber = function () {
@@ -39,5 +39,5 @@ var MySegmentsCacheInMemory = /** @class */ (function (_super) {
39
39
  return 1;
40
40
  };
41
41
  return MySegmentsCacheInMemory;
42
- }(AbstractSegmentsCacheSync));
42
+ }(AbstractMySegmentsCacheSync));
43
43
  export { MySegmentsCacheInMemory };
@@ -1,31 +1,19 @@
1
- import { __extends } from "tslib";
2
- import { AbstractSegmentsCacheSync } from '../AbstractSegmentsCacheSync';
3
1
  import { isIntegerNumber } from '../../utils/lang';
4
2
  /**
5
- * Default ISplitsCacheSync implementation that stores split definitions in memory.
6
- * Supported by all JS runtimes.
3
+ * Default ISplitsCacheSync implementation for server-side that stores segments definitions in memory.
7
4
  */
8
- var SegmentsCacheInMemory = /** @class */ (function (_super) {
9
- __extends(SegmentsCacheInMemory, _super);
5
+ var SegmentsCacheInMemory = /** @class */ (function () {
10
6
  function SegmentsCacheInMemory() {
11
- var _this = _super !== null && _super.apply(this, arguments) || this;
12
- _this.segmentCache = {};
13
- _this.segmentChangeNumber = {};
14
- return _this;
7
+ this.segmentCache = {};
8
+ this.segmentChangeNumber = {};
15
9
  }
16
- SegmentsCacheInMemory.prototype.addToSegment = function (name, segmentKeys) {
17
- var values = this.segmentCache[name];
18
- var keySet = values ? values : new Set();
19
- segmentKeys.forEach(function (k) { return keySet.add(k); });
20
- this.segmentCache[name] = keySet;
21
- return true;
22
- };
23
- SegmentsCacheInMemory.prototype.removeFromSegment = function (name, segmentKeys) {
24
- var values = this.segmentCache[name];
25
- var keySet = values ? values : new Set();
26
- segmentKeys.forEach(function (k) { return keySet.delete(k); });
10
+ SegmentsCacheInMemory.prototype.update = function (name, addedKeys, removedKeys, changeNumber) {
11
+ var keySet = this.segmentCache[name] || new Set();
12
+ addedKeys.forEach(function (k) { return keySet.add(k); });
13
+ removedKeys.forEach(function (k) { return keySet.delete(k); });
27
14
  this.segmentCache[name] = keySet;
28
- return true;
15
+ this.segmentChangeNumber[name] = changeNumber;
16
+ return addedKeys.length > 0 || removedKeys.length > 0;
29
17
  };
30
18
  SegmentsCacheInMemory.prototype.isInSegment = function (name, key) {
31
19
  var segmentValues = this.segmentCache[name];
@@ -59,14 +47,12 @@ var SegmentsCacheInMemory = /** @class */ (function (_super) {
59
47
  return acum + _this.segmentCache[segmentName].size;
60
48
  }, 0);
61
49
  };
62
- SegmentsCacheInMemory.prototype.setChangeNumber = function (name, changeNumber) {
63
- this.segmentChangeNumber[name] = changeNumber;
64
- return true;
65
- };
66
50
  SegmentsCacheInMemory.prototype.getChangeNumber = function (name) {
67
51
  var value = this.segmentChangeNumber[name];
68
52
  return isIntegerNumber(value) ? value : -1;
69
53
  };
54
+ // No-op. Not used in server-side
55
+ SegmentsCacheInMemory.prototype.resetSegments = function () { return false; };
70
56
  return SegmentsCacheInMemory;
71
- }(AbstractSegmentsCacheSync));
57
+ }());
72
58
  export { SegmentsCacheInMemory };
@@ -3,7 +3,6 @@ import { AbstractSplitsCacheSync, usesSegments } from '../AbstractSplitsCacheSyn
3
3
  import { isFiniteNumber } from '../../utils/lang';
4
4
  /**
5
5
  * Default ISplitsCacheSync implementation that stores split definitions in memory.
6
- * Supported by all JS runtimes.
7
6
  */
8
7
  var SplitsCacheInMemory = /** @class */ (function (_super) {
9
8
  __extends(SplitsCacheInMemory, _super);
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
2
+ import { setToArray } from '../../utils/lang/sets';
2
3
  /**
3
4
  * Converts `uniqueKeys` data from cache into request payload for SS.
4
5
  */
@@ -7,7 +8,7 @@ export function fromUniqueKeysCollector(uniqueKeys) {
7
8
  var featureNames = Object.keys(uniqueKeys);
8
9
  for (var i = 0; i < featureNames.length; i++) {
9
10
  var featureName = featureNames[i];
10
- var userKeys = Array.from(uniqueKeys[featureName]);
11
+ var userKeys = setToArray(uniqueKeys[featureName]);
11
12
  var uniqueKeysPayload = {
12
13
  f: featureName,
13
14
  ks: userKeys
@@ -1,4 +1,5 @@
1
1
  import { DEFAULT_CACHE_SIZE } from '../inRedis/constants';
2
+ import { setToArray } from '../../utils/lang/sets';
2
3
  var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
3
4
  /**
4
5
  *
@@ -58,7 +59,7 @@ var UniqueKeysCacheInMemoryCS = /** @class */ (function () {
58
59
  var userKeys = Object.keys(uniqueKeys);
59
60
  for (var k = 0; k < userKeys.length; k++) {
60
61
  var userKey = userKeys[k];
61
- var featureNames = Array.from(uniqueKeys[userKey]);
62
+ var featureNames = setToArray(uniqueKeys[userKey]);
62
63
  var uniqueKeysPayload = {
63
64
  k: userKey,
64
65
  fs: featureNames
@@ -3,6 +3,7 @@ import ioredis from 'ioredis';
3
3
  import { merge, isString } from '../../utils/lang';
4
4
  import { thenable } from '../../utils/promise/thenable';
5
5
  import { timeout } from '../../utils/promise/timeout';
6
+ import { setToArray } from '../../utils/lang/sets';
6
7
  var LOG_PREFIX = 'storage:redis-adapter: ';
7
8
  // If we ever decide to fully wrap every method, there's a Commander.getBuiltinCommands from ioredis.
8
9
  var METHODS_TO_PROMISE_WRAP = ['set', 'exec', 'del', 'get', 'keys', 'sadd', 'srem', 'sismember', 'smembers', 'incr', 'rpush', 'expire', 'mget', 'lrange', 'ltrim', 'hset', 'hincrby', 'popNRaw'];
@@ -125,7 +126,7 @@ var RedisAdapter = /** @class */ (function (_super) {
125
126
  setTimeout(function deferredDisconnect() {
126
127
  if (instance._runningCommands.size > 0) {
127
128
  instance.log.info(LOG_PREFIX + ("Attempting to disconnect but there are " + instance._runningCommands.size + " commands still waiting for resolution. Defering disconnection until those finish."));
128
- Promise.all(Array.from(instance._runningCommands))
129
+ Promise.all(setToArray(instance._runningCommands))
129
130
  .then(function () {
130
131
  instance.log.debug(LOG_PREFIX + 'Pending commands finished successfully, disconnecting.');
131
132
  originalMethod.apply(instance, params);
@@ -6,30 +6,24 @@ var SegmentsCacheInRedis = /** @class */ (function () {
6
6
  this.redis = redis;
7
7
  this.keys = keys;
8
8
  }
9
- SegmentsCacheInRedis.prototype.addToSegment = function (name, segmentKeys) {
9
+ /**
10
+ * Update the given segment `name` with the lists of `addedKeys`, `removedKeys` and `changeNumber`.
11
+ * The returned promise is resolved if the operation success, with `true` if the segment was updated (i.e., some key was added or removed),
12
+ * or rejected if it fails (e.g., Redis operation fails).
13
+ */
14
+ SegmentsCacheInRedis.prototype.update = function (name, addedKeys, removedKeys, changeNumber) {
10
15
  var segmentKey = this.keys.buildSegmentNameKey(name);
11
- if (segmentKeys.length) {
12
- return this.redis.sadd(segmentKey, segmentKeys).then(function () { return true; });
13
- }
14
- else {
15
- return Promise.resolve(true);
16
- }
17
- };
18
- SegmentsCacheInRedis.prototype.removeFromSegment = function (name, segmentKeys) {
19
- var segmentKey = this.keys.buildSegmentNameKey(name);
20
- if (segmentKeys.length) {
21
- return this.redis.srem(segmentKey, segmentKeys).then(function () { return true; });
22
- }
23
- else {
24
- return Promise.resolve(true);
25
- }
16
+ return Promise.all([
17
+ addedKeys.length && this.redis.sadd(segmentKey, addedKeys),
18
+ removedKeys.length && this.redis.srem(segmentKey, removedKeys),
19
+ this.redis.set(this.keys.buildSegmentTillKey(name), changeNumber + '')
20
+ ]).then(function () {
21
+ return addedKeys.length > 0 || removedKeys.length > 0;
22
+ });
26
23
  };
27
24
  SegmentsCacheInRedis.prototype.isInSegment = function (name, key) {
28
25
  return this.redis.sismember(this.keys.buildSegmentNameKey(name), key).then(function (matches) { return matches !== 0; });
29
26
  };
30
- SegmentsCacheInRedis.prototype.setChangeNumber = function (name, changeNumber) {
31
- return this.redis.set(this.keys.buildSegmentTillKey(name), changeNumber + '').then(function (status) { return status === 'OK'; });
32
- };
33
27
  SegmentsCacheInRedis.prototype.getChangeNumber = function (name) {
34
28
  var _this = this;
35
29
  return this.redis.get(this.keys.buildSegmentTillKey(name)).then(function (value) {
@@ -2,6 +2,7 @@ import { __extends } from "tslib";
2
2
  import { UniqueKeysCacheInMemory } from '../inMemory/UniqueKeysCacheInMemory';
3
3
  import { DEFAULT_CACHE_SIZE, REFRESH_RATE, TTL_REFRESH } from './constants';
4
4
  import { LOG_PREFIX } from './constants';
5
+ import { setToArray } from '../../utils/lang/sets';
5
6
  var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
6
7
  __extends(UniqueKeysCacheInRedis, _super);
7
8
  function UniqueKeysCacheInRedis(log, key, redis, uniqueKeysQueueSize, refreshRate) {
@@ -21,7 +22,7 @@ var UniqueKeysCacheInRedis = /** @class */ (function (_super) {
21
22
  if (!featureNames.length)
22
23
  return Promise.resolve(false);
23
24
  var uniqueKeysArray = featureNames.map(function (featureName) {
24
- var featureKeys = Array.from(_this.uniqueKeysTracker[featureName]);
25
+ var featureKeys = setToArray(_this.uniqueKeysTracker[featureName]);
25
26
  var uniqueKeysPayload = {
26
27
  f: featureName,
27
28
  ks: featureKeys
@@ -12,32 +12,19 @@ var SegmentsCachePluggable = /** @class */ (function () {
12
12
  this.wrapper = wrapper;
13
13
  }
14
14
  /**
15
- * Add a list of `segmentKeys` to the given segment `name`.
16
- * The returned promise is resolved when the operation success
17
- * or rejected if wrapper operation fails.
18
- */
19
- SegmentsCachePluggable.prototype.addToSegment = function (name, segmentKeys) {
20
- var segmentKey = this.keys.buildSegmentNameKey(name);
21
- if (segmentKeys.length) {
22
- return this.wrapper.addItems(segmentKey, segmentKeys);
23
- }
24
- else {
25
- return Promise.resolve();
26
- }
27
- };
28
- /**
29
- * Remove a list of `segmentKeys` from the given segment `name`.
30
- * The returned promise is resolved when the operation success
31
- * or rejected if wrapper operation fails.
15
+ * Update the given segment `name` with the lists of `addedKeys`, `removedKeys` and `changeNumber`.
16
+ * The returned promise is resolved if the operation success, with `true` if the segment was updated (i.e., some key was added or removed),
17
+ * or rejected if it fails (e.g., wrapper operation fails).
32
18
  */
33
- SegmentsCachePluggable.prototype.removeFromSegment = function (name, segmentKeys) {
19
+ SegmentsCachePluggable.prototype.update = function (name, addedKeys, removedKeys, changeNumber) {
34
20
  var segmentKey = this.keys.buildSegmentNameKey(name);
35
- if (segmentKeys.length) {
36
- return this.wrapper.removeItems(segmentKey, segmentKeys);
37
- }
38
- else {
39
- return Promise.resolve();
40
- }
21
+ return Promise.all([
22
+ addedKeys.length && this.wrapper.addItems(segmentKey, addedKeys),
23
+ removedKeys.length && this.wrapper.removeItems(segmentKey, removedKeys),
24
+ this.wrapper.set(this.keys.buildSegmentTillKey(name), changeNumber + '')
25
+ ]).then(function () {
26
+ return addedKeys.length > 0 || removedKeys.length > 0;
27
+ });
41
28
  };
42
29
  /**
43
30
  * Returns a promise that resolves with a boolean value indicating if `key` is part of `name` segment.
@@ -46,14 +33,6 @@ var SegmentsCachePluggable = /** @class */ (function () {
46
33
  SegmentsCachePluggable.prototype.isInSegment = function (name, key) {
47
34
  return this.wrapper.itemContains(this.keys.buildSegmentNameKey(name), key);
48
35
  };
49
- /**
50
- * Set till number for the given segment `name`.
51
- * The returned promise is resolved when the operation success,
52
- * or rejected if it fails (e.g., wrapper operation fails).
53
- */
54
- SegmentsCachePluggable.prototype.setChangeNumber = function (name, changeNumber) {
55
- return this.wrapper.set(this.keys.buildSegmentTillKey(name), changeNumber + '');
56
- };
57
36
  /**
58
37
  * Get till number or -1 if it's not defined.
59
38
  * The returned promise is resolved with the changeNumber or -1 if it doesn't exist or a wrapper operation fails.
@@ -2,6 +2,7 @@ import { __extends } from "tslib";
2
2
  import { UniqueKeysCacheInMemory } from '../inMemory/UniqueKeysCacheInMemory';
3
3
  import { DEFAULT_CACHE_SIZE, REFRESH_RATE } from '../inRedis/constants';
4
4
  import { LOG_PREFIX } from './constants';
5
+ import { setToArray } from '../../utils/lang/sets';
5
6
  var UniqueKeysCachePluggable = /** @class */ (function (_super) {
6
7
  __extends(UniqueKeysCachePluggable, _super);
7
8
  function UniqueKeysCachePluggable(log, key, wrapper, uniqueKeysQueueSize, refreshRate) {
@@ -21,7 +22,7 @@ var UniqueKeysCachePluggable = /** @class */ (function (_super) {
21
22
  if (!featureNames.length)
22
23
  return Promise.resolve(false);
23
24
  var uniqueKeysArray = featureNames.map(function (featureName) {
24
- var featureKeys = Array.from(_this.uniqueKeysTracker[featureName]);
25
+ var featureKeys = setToArray(_this.uniqueKeysTracker[featureName]);
25
26
  var uniqueKeysPayload = {
26
27
  f: featureName,
27
28
  ks: featureKeys
@@ -1,4 +1,5 @@
1
1
  import { startsWith, toNumber } from '../../utils/lang';
2
+ import { setToArray } from '../../utils/lang/sets';
2
3
  /**
3
4
  * Creates a IPluggableStorageWrapper implementation that stores items in memory.
4
5
  * The `_cache` property is the object were items are stored.
@@ -115,7 +116,7 @@ export function inMemoryWrapperFactory(connDelay) {
115
116
  if (!set)
116
117
  return Promise.resolve([]);
117
118
  if (set instanceof Set)
118
- return Promise.resolve(Array.from(set));
119
+ return Promise.resolve(setToArray(set));
119
120
  return Promise.reject('key is not a set');
120
121
  },
121
122
  // always connects and disconnects
@@ -16,23 +16,30 @@ export function syncManagerOfflineFactory(splitsParserFactory) {
16
16
  */
17
17
  return function (_a) {
18
18
  var settings = _a.settings, readiness = _a.readiness, storage = _a.storage;
19
- return objectAssign(fromObjectSyncTaskFactory(splitsParserFactory(), storage, readiness, settings), {
19
+ var mainSyncManager = fromObjectSyncTaskFactory(splitsParserFactory(), storage, readiness, settings);
20
+ var mainStart = mainSyncManager.start;
21
+ var sharedStarts = [];
22
+ return objectAssign(mainSyncManager, {
23
+ start: function () {
24
+ mainStart();
25
+ sharedStarts.forEach(function (cb) { return cb(); });
26
+ sharedStarts.length = 0;
27
+ },
20
28
  // fake flush, that resolves immediately
21
29
  flush: flush,
22
30
  // [Only used for client-side]
23
31
  shared: function (matchingKey, readinessManager) {
32
+ // In LOCALHOST mode, shared clients are ready in the next event-loop cycle than created
33
+ // SDK_READY cannot be emitted directly because this will not update the readiness status
34
+ function emitSdkReady() {
35
+ readinessManager.segments.emit(SDK_SEGMENTS_ARRIVED); // SDK_SPLITS_ARRIVED emitted by main SyncManager
36
+ }
37
+ if (mainSyncManager.isRunning())
38
+ setTimeout(emitSdkReady);
39
+ else
40
+ sharedStarts.push(emitSdkReady);
24
41
  return {
25
- start: function () {
26
- // In LOCALHOST mode, shared clients are ready in the next event-loop cycle than created
27
- // SDK_READY cannot be emitted directly because this will not update the readiness status
28
- setTimeout(function () {
29
- readinessManager.segments.emit(SDK_SEGMENTS_ARRIVED); // SDK_SPLITS_ARRIVED emitted by main SyncManager
30
- }, 0);
31
- },
32
42
  stop: function () { },
33
- isRunning: function () {
34
- return true;
35
- },
36
43
  flush: flush,
37
44
  };
38
45
  }
@@ -1,7 +1,5 @@
1
- import { findIndex } from '../../../utils/lang';
2
1
  import { SDK_SEGMENTS_ARRIVED } from '../../../readiness/constants';
3
2
  import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants';
4
- import { thenable } from '../../../utils/promise/thenable';
5
3
  /**
6
4
  * Factory of SegmentChanges updater, a task that:
7
5
  * - fetches segment changes using `segmentChangesFetcher`
@@ -20,27 +18,16 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
20
18
  var sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
21
19
  return sincePromise.then(function (since) {
22
20
  // if fetchOnlyNew flag, avoid processing already fetched segments
23
- if (fetchOnlyNew && since !== -1)
24
- return -1;
25
- return segmentChangesFetcher(since, segmentName, noCache, till).then(function (changes) {
26
- var changeNumber = -1;
27
- var results = [];
28
- changes.forEach(function (x) {
29
- if (x.added.length > 0)
30
- results.push(segments.addToSegment(segmentName, x.added));
31
- if (x.removed.length > 0)
32
- results.push(segments.removeFromSegment(segmentName, x.removed));
33
- if (x.added.length > 0 || x.removed.length > 0) {
34
- results.push(segments.setChangeNumber(segmentName, x.till));
35
- changeNumber = x.till;
36
- }
37
- log.debug(LOG_PREFIX_SYNC_SEGMENTS + "Processed " + segmentName + " with till = " + x.till + ". Added: " + x.added.length + ". Removed: " + x.removed.length);
21
+ return fetchOnlyNew && since !== -1 ?
22
+ false :
23
+ segmentChangesFetcher(since, segmentName, noCache, till).then(function (changes) {
24
+ return Promise.all(changes.map(function (x) {
25
+ log.debug(LOG_PREFIX_SYNC_SEGMENTS + "Processing " + segmentName + " with till = " + x.till + ". Added: " + x.added.length + ". Removed: " + x.removed.length);
26
+ return segments.update(x.name, x.added, x.removed, x.till);
27
+ })).then(function (updates) {
28
+ return updates.some(function (update) { return update; });
29
+ });
38
30
  });
39
- // If at least one storage operation result is a promise, join all in a single promise.
40
- if (results.some(function (result) { return thenable(result); }))
41
- return Promise.all(results).then(function () { return changeNumber; });
42
- return changeNumber;
43
- });
44
31
  });
45
32
  }
46
33
  /**
@@ -59,14 +46,11 @@ export function segmentChangesUpdaterFactory(log, segmentChangesFetcher, segment
59
46
  // If not a segment name provided, read list of available segments names to be updated.
60
47
  var segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
61
48
  return segmentsPromise.then(function (segmentNames) {
62
- // Async fetchers are collected here.
63
- var updaters = [];
64
- for (var index = 0; index < segmentNames.length; index++) {
65
- updaters.push(updateSegment(segmentNames[index], noCache, till, fetchOnlyNew));
66
- }
49
+ // Async fetchers
50
+ var updaters = segmentNames.map(function (segmentName) { return updateSegment(segmentName, noCache, till, fetchOnlyNew); });
67
51
  return Promise.all(updaters).then(function (shouldUpdateFlags) {
68
52
  // if at least one segment fetch succeeded, mark segments ready
69
- if (findIndex(shouldUpdateFlags, function (v) { return v !== -1; }) !== -1 || readyOnAlreadyExistentState) {
53
+ if (shouldUpdateFlags.some(function (update) { return update; }) || readyOnAlreadyExistentState) {
70
54
  readyOnAlreadyExistentState = false;
71
55
  if (readiness)
72
56
  readiness.segments.emit(SDK_SEGMENTS_ARRIVED);
@@ -3,6 +3,7 @@ import { SDK_SPLITS_ARRIVED, SDK_SPLITS_CACHE_LOADED } from '../../../readiness/
3
3
  import { SYNC_SPLITS_FETCH, SYNC_SPLITS_NEW, SYNC_SPLITS_REMOVED, SYNC_SPLITS_SEGMENTS, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
4
4
  import { startsWith } from '../../../utils/lang';
5
5
  import { IN_SEGMENT } from '../../../utils/constants';
6
+ import { setToArray } from '../../../utils/lang/sets';
6
7
  // Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
7
8
  // Returns a promise that could be rejected.
8
9
  // @TODO review together with Segments and MySegments storage APIs
@@ -67,7 +68,7 @@ export function computeSplitsMutation(entries, filters) {
67
68
  }
68
69
  return accum;
69
70
  }, { added: [], removed: [], segments: [] });
70
- computed.segments = Array.from(segments);
71
+ computed.segments = setToArray(segments);
71
72
  return computed;
72
73
  }
73
74
  /**
@@ -115,33 +115,32 @@ export function syncManagerOnlineFactory(pollingManagerFactory, pushManagerFacto
115
115
  if (!pollingManager)
116
116
  return;
117
117
  var mySegmentsSyncTask = pollingManager.add(matchingKey, readinessManager, storage);
118
- return {
119
- isRunning: mySegmentsSyncTask.isRunning,
120
- start: function () {
121
- if (syncEnabled) {
122
- if (pushManager) {
123
- if (pollingManager.isRunning()) {
124
- // if doing polling, we must start the periodic fetch of data
125
- if (storage.splits.usesSegments())
126
- mySegmentsSyncTask.start();
127
- }
128
- else {
129
- // if not polling, we must execute the sync task for the initial fetch
130
- // of segments since `syncAll` was already executed when starting the main client
131
- mySegmentsSyncTask.execute();
132
- }
133
- pushManager.add(matchingKey, mySegmentsSyncTask);
134
- }
135
- else {
118
+ if (running) {
119
+ if (syncEnabled) {
120
+ if (pushManager) {
121
+ if (pollingManager.isRunning()) {
122
+ // if doing polling, we must start the periodic fetch of data
136
123
  if (storage.splits.usesSegments())
137
124
  mySegmentsSyncTask.start();
138
125
  }
126
+ else {
127
+ // if not polling, we must execute the sync task for the initial fetch
128
+ // of segments since `syncAll` was already executed when starting the main client
129
+ mySegmentsSyncTask.execute();
130
+ }
131
+ pushManager.add(matchingKey, mySegmentsSyncTask);
139
132
  }
140
133
  else {
141
- if (!readinessManager.isReady())
142
- mySegmentsSyncTask.execute();
134
+ if (storage.splits.usesSegments())
135
+ mySegmentsSyncTask.start();
143
136
  }
144
- },
137
+ }
138
+ else {
139
+ if (!readinessManager.isReady())
140
+ mySegmentsSyncTask.execute();
141
+ }
142
+ }
143
+ return {
145
144
  stop: function () {
146
145
  // check in case `client.destroy()` has been invoked more than once for the same client
147
146
  var mySegmentsSyncTask = pollingManager.get(matchingKey);
@@ -9,7 +9,7 @@ import { isConsumerMode } from '../utils/settingsValidation/mode';
9
9
  * @param eventsCache cache to save events
10
10
  * @param integrationsManager optional event handler used for integrations
11
11
  */
12
- export function eventTrackerFactory(settings, eventsCache, integrationsManager, telemetryCache) {
12
+ export function eventTrackerFactory(settings, eventsCache, whenInit, integrationsManager, telemetryCache) {
13
13
  var log = settings.log, mode = settings.mode;
14
14
  var isAsync = isConsumerMode(mode);
15
15
  function queueEventsCallback(eventData, tracked) {
@@ -19,15 +19,17 @@ export function eventTrackerFactory(settings, eventsCache, integrationsManager,
19
19
  if (tracked) {
20
20
  log.info(EVENTS_TRACKER_SUCCESS, [msg]);
21
21
  if (integrationsManager) {
22
- // Wrap in a timeout because we don't want it to be blocking.
23
- setTimeout(function () {
24
- // copy of event, to avoid unexpected behaviour if modified by integrations
25
- var eventDataCopy = objectAssign({}, eventData);
26
- if (properties)
27
- eventDataCopy.properties = objectAssign({}, properties);
28
- // integrationsManager does not throw errors (they are internally handled by each integration module)
29
- integrationsManager.handleEvent(eventDataCopy);
30
- }, 0);
22
+ whenInit(function () {
23
+ // Wrap in a timeout because we don't want it to be blocking.
24
+ setTimeout(function () {
25
+ // copy of event, to avoid unexpected behaviour if modified by integrations
26
+ var eventDataCopy = objectAssign({}, eventData);
27
+ if (properties)
28
+ eventDataCopy.properties = objectAssign({}, properties);
29
+ // integrationsManager does not throw errors (they are internally handled by each integration module)
30
+ integrationsManager.handleEvent(eventDataCopy);
31
+ });
32
+ });
31
33
  }
32
34
  }
33
35
  else {
@@ -11,7 +11,7 @@ import { CONSENT_DECLINED, DEDUPED, QUEUED } from '../utils/constants';
11
11
  * @param integrationsManager optional integrations manager
12
12
  * @param strategy strategy for impressions tracking.
13
13
  */
14
- export function impressionsTrackerFactory(settings, impressionsCache, strategy, integrationsManager, telemetryCache) {
14
+ export function impressionsTrackerFactory(settings, impressionsCache, strategy, whenInit, integrationsManager, telemetryCache) {
15
15
  var log = settings.log, impressionListener = settings.impressionListener, _a = settings.runtime, ip = _a.ip, hostname = _a.hostname, version = settings.version;
16
16
  return {
17
17
  track: function (impressions, attributes) {
@@ -50,19 +50,21 @@ export function impressionsTrackerFactory(settings, impressionsCache, strategy,
50
50
  hostname: hostname,
51
51
  sdkLanguageVersion: version
52
52
  };
53
- // Wrap in a timeout because we don't want it to be blocking.
54
- setTimeout(function () {
55
- // integrationsManager.handleImpression does not throw errors
56
- if (integrationsManager)
57
- integrationsManager.handleImpression(impressionData);
58
- try { // @ts-ignore. An exception on the listeners should not break the SDK.
59
- if (impressionListener)
60
- impressionListener.logImpression(impressionData);
61
- }
62
- catch (err) {
63
- log.error(ERROR_IMPRESSIONS_LISTENER, [err]);
64
- }
65
- }, 0);
53
+ whenInit(function () {
54
+ // Wrap in a timeout because we don't want it to be blocking.
55
+ setTimeout(function () {
56
+ // integrationsManager.handleImpression does not throw errors
57
+ if (integrationsManager)
58
+ integrationsManager.handleImpression(impressionData);
59
+ try { // @ts-ignore. An exception on the listeners should not break the SDK.
60
+ if (impressionListener)
61
+ impressionListener.logImpression(impressionData);
62
+ }
63
+ catch (err) {
64
+ log.error(ERROR_IMPRESSIONS_LISTENER, [err]);
65
+ }
66
+ });
67
+ });
66
68
  };
67
69
  for (var i = 0; i < impressionsToListenerCount; i++) {
68
70
  _loop_1(i);
@@ -16,9 +16,6 @@ var noopFilterAdapter = {
16
16
  export function uniqueKeysTrackerFactory(log, uniqueKeysCache, filterAdapter) {
17
17
  if (filterAdapter === void 0) { filterAdapter = noopFilterAdapter; }
18
18
  var intervalId;
19
- if (filterAdapter.refreshRate) {
20
- intervalId = setInterval(filterAdapter.clear, filterAdapter.refreshRate);
21
- }
22
19
  return {
23
20
  track: function (key, featureName) {
24
21
  if (!filterAdapter.add(key, featureName)) {
@@ -27,6 +24,11 @@ export function uniqueKeysTrackerFactory(log, uniqueKeysCache, filterAdapter) {
27
24
  }
28
25
  uniqueKeysCache.track(key, featureName);
29
26
  },
27
+ start: function () {
28
+ if (filterAdapter.refreshRate) {
29
+ intervalId = setInterval(filterAdapter.clear, filterAdapter.refreshRate);
30
+ }
31
+ },
30
32
  stop: function () {
31
33
  clearInterval(intervalId);
32
34
  }
@@ -1,5 +1,14 @@
1
+ export function setToArray(set) {
2
+ if (Array.from)
3
+ return Array.from(set);
4
+ var array = [];
5
+ set.forEach(function (value) {
6
+ array.push(value);
7
+ });
8
+ return array;
9
+ }
1
10
  export function returnSetsUnion(set, set2) {
2
- return new Set(Array.from(set).concat(Array.from(set2)));
11
+ return new Set(setToArray(set).concat(setToArray(set2)));
3
12
  }
4
13
  export function returnDifference(list, list2) {
5
14
  if (list === void 0) { list = []; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@splitsoftware/splitio-commons",
3
- "version": "2.0.0-rc.0",
3
+ "version": "2.0.0-rc.1",
4
4
  "description": "Split JavaScript SDK common components",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",
@@ -21,7 +21,7 @@ export class Engine {
21
21
 
22
22
  constructor(private baseInfo: ISplit, private evaluator: IEvaluator) {
23
23
 
24
- // in case we don't have a default treatment in the instanciation, use 'control'
24
+ // in case we don't have a default treatment in the instantiation, use 'control'
25
25
  if (typeof this.baseInfo.defaultTreatment !== 'string') {
26
26
  this.baseInfo.defaultTreatment = CONTROL;
27
27
  }