@splitsoftware/splitio-commons 2.12.0 → 3.0.0-rc.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.
Files changed (309) hide show
  1. package/CHANGES.txt +14 -1
  2. package/cjs/evaluator/condition/engineUtils.js +2 -2
  3. package/cjs/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.js +70 -0
  4. package/cjs/evaluator/fallbackConfigsCalculator/index.js +25 -0
  5. package/cjs/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
  6. package/cjs/evaluator/fallbackTreatmentsCalculator/index.js +21 -32
  7. package/cjs/evaluator/index.js +67 -42
  8. package/cjs/evaluator/matchers/whitelist.js +1 -1
  9. package/cjs/integrations/pluggable.js +1 -1
  10. package/cjs/listeners/browser.js +4 -3
  11. package/cjs/listeners/node.js +4 -4
  12. package/cjs/logger/constants.js +14 -20
  13. package/cjs/logger/index.js +1 -1
  14. package/cjs/logger/messages/debug.js +6 -7
  15. package/cjs/logger/messages/error.js +4 -4
  16. package/cjs/logger/messages/info.js +2 -4
  17. package/cjs/logger/messages/warn.js +9 -9
  18. package/cjs/platform/browser.js +15 -0
  19. package/cjs/platform/getEventSource/browser.js +8 -0
  20. package/cjs/platform/getEventSource/eventsource.js +480 -0
  21. package/cjs/platform/getEventSource/node.js +26 -0
  22. package/cjs/platform/getFetch/browser.js +9 -0
  23. package/cjs/platform/getFetch/node.js +27 -0
  24. package/cjs/platform/getOptions/node.js +25 -0
  25. package/cjs/platform/node.js +17 -0
  26. package/cjs/readiness/constants.js +2 -1
  27. package/cjs/sdkClient/client.js +9 -35
  28. package/cjs/sdkClient/clientAttributesDecoration.js +3 -3
  29. package/cjs/sdkClient/clientInputValidation.js +38 -81
  30. package/cjs/sdkClient/identity.js +1 -1
  31. package/cjs/sdkClient/sdkClient.js +4 -49
  32. package/cjs/sdkClient/sdkLifecycle.js +70 -0
  33. package/cjs/sdkClient/trackMethod.js +56 -0
  34. package/cjs/sdkFactory/index.js +8 -45
  35. package/cjs/sdkManager/index.js +3 -3
  36. package/cjs/services/splitApi.js +18 -13
  37. package/cjs/services/splitHttpClient.js +1 -1
  38. package/cjs/storages/AbstractSplitsCacheAsync.js +1 -1
  39. package/cjs/storages/AbstractSplitsCacheSync.js +1 -1
  40. package/cjs/storages/KeyBuilder.js +12 -12
  41. package/cjs/storages/KeyBuilderCS.js +13 -13
  42. package/cjs/storages/KeyBuilderSS.js +15 -15
  43. package/cjs/storages/getRolloutPlan.js +1 -1
  44. package/cjs/storages/inLocalStorage/MySegmentsCacheInLocal.js +1 -1
  45. package/cjs/storages/inLocalStorage/RBSegmentsCacheInLocal.js +1 -1
  46. package/cjs/storages/inLocalStorage/SplitsCacheInLocal.js +1 -1
  47. package/cjs/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
  48. package/cjs/storages/inMemory/MySegmentsCacheInMemory.js +1 -1
  49. package/cjs/storages/inMemory/RBSegmentsCacheInMemory.js +1 -1
  50. package/cjs/storages/inMemory/SplitsCacheInMemory.js +1 -1
  51. package/cjs/storages/inMemory/TelemetryCacheInMemory.js +2 -2
  52. package/cjs/storages/inRedis/EventsCacheInRedis.js +1 -1
  53. package/cjs/storages/inRedis/ImpressionCountsCacheInRedis.js +5 -5
  54. package/cjs/storages/inRedis/ImpressionsCacheInRedis.js +1 -1
  55. package/cjs/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
  56. package/cjs/storages/inRedis/RedisAdapter.js +8 -8
  57. package/cjs/storages/inRedis/SplitsCacheInRedis.js +6 -6
  58. package/cjs/storages/inRedis/TelemetryCacheInRedis.js +7 -7
  59. package/cjs/storages/inRedis/UniqueKeysCacheInRedis.js +3 -3
  60. package/cjs/storages/pluggable/EventsCachePluggable.js +1 -1
  61. package/cjs/storages/pluggable/ImpressionCountsCachePluggable.js +6 -6
  62. package/cjs/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
  63. package/cjs/storages/pluggable/SplitsCachePluggable.js +4 -4
  64. package/cjs/storages/pluggable/TelemetryCachePluggable.js +7 -7
  65. package/cjs/storages/pluggable/UniqueKeysCachePluggable.js +2 -2
  66. package/cjs/storages/pluggable/index.js +3 -3
  67. package/cjs/storages/pluggable/wrapperAdapter.js +1 -1
  68. package/cjs/storages/setRolloutPlan.js +1 -1
  69. package/cjs/storages/utils.js +6 -6
  70. package/cjs/sync/offline/splitsParser/parseCondition.js +1 -1
  71. package/cjs/sync/polling/fetchers/segmentChangesFetcher.js +1 -1
  72. package/cjs/sync/polling/fetchers/splitChangesFetcher.js +23 -14
  73. package/cjs/sync/polling/pollingManagerCS.js +11 -11
  74. package/cjs/sync/polling/pollingManagerSS.js +13 -13
  75. package/cjs/sync/polling/syncTasks/definitionsSyncTask.js +12 -0
  76. package/cjs/sync/polling/updaters/{splitChangesUpdater.js → definitionChangesUpdater.js} +67 -59
  77. package/cjs/sync/polling/updaters/mySegmentsUpdater.js +1 -1
  78. package/cjs/sync/polling/updaters/segmentChangesUpdater.js +6 -6
  79. package/cjs/sync/streaming/SSEClient/index.js +2 -2
  80. package/cjs/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +2 -2
  81. package/cjs/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -2
  82. package/cjs/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +4 -4
  83. package/cjs/sync/streaming/parseUtils.js +12 -12
  84. package/cjs/sync/streaming/pushManager.js +2 -2
  85. package/cjs/sync/submitters/impressionsSubmitter.js +6 -6
  86. package/cjs/sync/submitters/submitter.js +1 -1
  87. package/cjs/sync/syncManagerOnline.js +5 -2
  88. package/cjs/trackers/eventTracker.js +10 -12
  89. package/cjs/trackers/impressionObserver/buildKey.js +1 -1
  90. package/cjs/trackers/impressionsTracker.js +37 -20
  91. package/cjs/trackers/uniqueKeysTracker.js +1 -1
  92. package/cjs/utils/EventEmitter.js +391 -0
  93. package/cjs/utils/filter/bloomFilter.js +37 -0
  94. package/cjs/utils/inputValidation/apiKey.js +1 -1
  95. package/cjs/utils/inputValidation/attribute.js +2 -2
  96. package/cjs/utils/inputValidation/{split.js → definition.js} +10 -10
  97. package/cjs/utils/inputValidation/{splitExistence.js → definitionExistence.js} +6 -6
  98. package/cjs/utils/inputValidation/definitions.js +25 -0
  99. package/cjs/utils/inputValidation/eventProperties.js +1 -1
  100. package/cjs/utils/inputValidation/index.js +7 -7
  101. package/cjs/utils/inputValidation/isOperational.js +4 -4
  102. package/cjs/utils/inputValidation/target.js +22 -0
  103. package/cjs/utils/labels/index.js +3 -3
  104. package/cjs/utils/lang/index.js +1 -1
  105. package/cjs/utils/promise/timeout.js +1 -1
  106. package/cjs/utils/settingsValidation/splitFilters.js +4 -4
  107. package/cjs/utils/settingsValidation/url.js +5 -5
  108. package/esm/evaluator/condition/engineUtils.js +2 -2
  109. package/esm/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.js +64 -0
  110. package/esm/evaluator/fallbackConfigsCalculator/index.js +21 -0
  111. package/esm/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.js +5 -8
  112. package/esm/evaluator/fallbackTreatmentsCalculator/index.js +21 -33
  113. package/esm/evaluator/index.js +66 -42
  114. package/esm/evaluator/matchers/whitelist.js +1 -1
  115. package/esm/integrations/pluggable.js +1 -1
  116. package/esm/listeners/browser.js +4 -3
  117. package/esm/listeners/node.js +4 -4
  118. package/esm/logger/constants.js +11 -17
  119. package/esm/logger/index.js +1 -1
  120. package/esm/logger/messages/debug.js +5 -6
  121. package/esm/logger/messages/error.js +3 -3
  122. package/esm/logger/messages/info.js +1 -3
  123. package/esm/logger/messages/warn.js +8 -8
  124. package/esm/platform/browser.js +12 -0
  125. package/esm/platform/getEventSource/browser.js +4 -0
  126. package/esm/platform/getEventSource/eventsource.js +480 -0
  127. package/esm/platform/getEventSource/node.js +20 -0
  128. package/esm/platform/getFetch/browser.js +5 -0
  129. package/esm/platform/getFetch/node.js +22 -0
  130. package/esm/platform/getOptions/node.js +20 -0
  131. package/esm/platform/node.js +14 -0
  132. package/esm/readiness/constants.js +1 -0
  133. package/esm/sdkClient/client.js +10 -37
  134. package/esm/sdkClient/clientAttributesDecoration.js +3 -3
  135. package/esm/sdkClient/clientInputValidation.js +40 -83
  136. package/esm/sdkClient/identity.js +1 -1
  137. package/esm/sdkClient/sdkClient.js +4 -49
  138. package/esm/sdkClient/sdkLifecycle.js +66 -0
  139. package/esm/sdkClient/trackMethod.js +52 -0
  140. package/esm/sdkFactory/index.js +8 -45
  141. package/esm/sdkManager/index.js +4 -4
  142. package/esm/services/splitApi.js +18 -13
  143. package/esm/services/splitHttpClient.js +1 -1
  144. package/esm/storages/AbstractSplitsCacheAsync.js +1 -1
  145. package/esm/storages/AbstractSplitsCacheSync.js +1 -1
  146. package/esm/storages/KeyBuilder.js +12 -12
  147. package/esm/storages/KeyBuilderCS.js +12 -12
  148. package/esm/storages/KeyBuilderSS.js +14 -14
  149. package/esm/storages/getRolloutPlan.js +1 -1
  150. package/esm/storages/inLocalStorage/RBSegmentsCacheInLocal.js +1 -1
  151. package/esm/storages/inMemory/ImpressionCountsCacheInMemory.js +1 -1
  152. package/esm/storages/inMemory/RBSegmentsCacheInMemory.js +1 -1
  153. package/esm/storages/inMemory/TelemetryCacheInMemory.js +2 -2
  154. package/esm/storages/inRedis/EventsCacheInRedis.js +1 -1
  155. package/esm/storages/inRedis/ImpressionCountsCacheInRedis.js +4 -4
  156. package/esm/storages/inRedis/RBSegmentsCacheInRedis.js +1 -1
  157. package/esm/storages/inRedis/RedisAdapter.js +7 -7
  158. package/esm/storages/inRedis/SplitsCacheInRedis.js +4 -4
  159. package/esm/storages/inRedis/TelemetryCacheInRedis.js +7 -7
  160. package/esm/storages/inRedis/UniqueKeysCacheInRedis.js +1 -1
  161. package/esm/storages/pluggable/EventsCachePluggable.js +1 -1
  162. package/esm/storages/pluggable/ImpressionCountsCachePluggable.js +5 -5
  163. package/esm/storages/pluggable/RBSegmentsCachePluggable.js +1 -1
  164. package/esm/storages/pluggable/SplitsCachePluggable.js +2 -2
  165. package/esm/storages/pluggable/TelemetryCachePluggable.js +7 -7
  166. package/esm/storages/pluggable/UniqueKeysCachePluggable.js +1 -1
  167. package/esm/storages/pluggable/index.js +2 -2
  168. package/esm/storages/pluggable/wrapperAdapter.js +1 -1
  169. package/esm/storages/setRolloutPlan.js +1 -1
  170. package/esm/storages/utils.js +6 -6
  171. package/esm/sync/offline/splitsParser/parseCondition.js +1 -1
  172. package/esm/sync/polling/fetchers/splitChangesFetcher.js +24 -15
  173. package/esm/sync/polling/pollingManagerCS.js +11 -11
  174. package/esm/sync/polling/pollingManagerSS.js +13 -13
  175. package/esm/sync/polling/syncTasks/definitionsSyncTask.js +8 -0
  176. package/esm/sync/polling/updaters/{splitChangesUpdater.js → definitionChangesUpdater.js} +67 -59
  177. package/esm/sync/polling/updaters/mySegmentsUpdater.js +2 -2
  178. package/esm/sync/polling/updaters/segmentChangesUpdater.js +7 -7
  179. package/esm/sync/streaming/SSEClient/index.js +2 -2
  180. package/esm/sync/streaming/UpdateWorkers/MySegmentsUpdateWorker.js +2 -2
  181. package/esm/sync/streaming/UpdateWorkers/SegmentsUpdateWorker.js +2 -2
  182. package/esm/sync/streaming/UpdateWorkers/SplitsUpdateWorker.js +4 -4
  183. package/esm/sync/streaming/parseUtils.js +10 -10
  184. package/esm/sync/streaming/pushManager.js +3 -3
  185. package/esm/sync/submitters/impressionsSubmitter.js +6 -6
  186. package/esm/sync/submitters/submitter.js +1 -1
  187. package/esm/sync/syncManagerOnline.js +5 -2
  188. package/esm/trackers/eventTracker.js +10 -12
  189. package/esm/trackers/impressionObserver/buildKey.js +1 -1
  190. package/esm/trackers/impressionsTracker.js +38 -21
  191. package/esm/trackers/uniqueKeysTracker.js +1 -1
  192. package/esm/utils/EventEmitter.js +387 -0
  193. package/esm/utils/filter/bloomFilter.js +33 -0
  194. package/esm/utils/inputValidation/apiKey.js +1 -1
  195. package/esm/utils/inputValidation/attribute.js +2 -2
  196. package/esm/utils/inputValidation/{split.js → definition.js} +8 -8
  197. package/esm/utils/inputValidation/definitionExistence.js +15 -0
  198. package/esm/utils/inputValidation/definitions.js +21 -0
  199. package/esm/utils/inputValidation/index.js +3 -3
  200. package/esm/utils/inputValidation/isOperational.js +4 -4
  201. package/esm/utils/inputValidation/target.js +18 -0
  202. package/esm/utils/labels/index.js +2 -2
  203. package/esm/utils/promise/timeout.js +1 -1
  204. package/esm/utils/settingsValidation/splitFilters.js +4 -4
  205. package/esm/utils/settingsValidation/url.js +5 -5
  206. package/package.json +15 -6
  207. package/src/dtos/types.ts +65 -70
  208. package/src/evaluator/Engine.ts +4 -4
  209. package/src/evaluator/combiners/and.ts +3 -3
  210. package/src/evaluator/combiners/ifelseif.ts +2 -2
  211. package/src/evaluator/condition/engineUtils.ts +2 -2
  212. package/src/evaluator/condition/index.ts +3 -3
  213. package/src/evaluator/fallbackConfigsCalculator/fallbackSanitizer/index.ts +76 -0
  214. package/src/evaluator/fallbackConfigsCalculator/index.ts +24 -0
  215. package/src/evaluator/fallbackTreatmentsCalculator/fallbackSanitizer/index.ts +5 -7
  216. package/src/evaluator/fallbackTreatmentsCalculator/index.ts +27 -41
  217. package/src/evaluator/index.ts +80 -45
  218. package/src/evaluator/matchers/dependency.ts +2 -2
  219. package/src/evaluator/matchers/matcherTypes.ts +2 -2
  220. package/src/evaluator/matchers/prerequisites.ts +4 -4
  221. package/src/evaluator/matchers/rbsegment.ts +2 -2
  222. package/src/evaluator/matchers/whitelist.ts +2 -2
  223. package/src/evaluator/matchersTransform/index.ts +2 -2
  224. package/src/evaluator/matchersTransform/whitelist.ts +2 -2
  225. package/src/evaluator/parser/index.ts +4 -4
  226. package/src/evaluator/treatments/index.ts +2 -2
  227. package/src/evaluator/types.ts +6 -6
  228. package/src/evaluator/value/index.ts +1 -1
  229. package/src/integrations/pluggable.ts +1 -1
  230. package/src/listeners/browser.ts +11 -8
  231. package/src/listeners/node.ts +2 -5
  232. package/src/logger/constants.ts +11 -17
  233. package/src/logger/messages/debug.ts +5 -6
  234. package/src/logger/messages/error.ts +3 -3
  235. package/src/logger/messages/info.ts +1 -3
  236. package/src/logger/messages/warn.ts +8 -8
  237. package/src/platform/browser.ts +14 -0
  238. package/src/platform/getEventSource/browser.ts +4 -0
  239. package/src/platform/getEventSource/eventsource.js +519 -0
  240. package/src/platform/getEventSource/node.ts +23 -0
  241. package/src/platform/getFetch/browser.ts +5 -0
  242. package/src/platform/getFetch/node.ts +27 -0
  243. package/src/platform/getOptions/node.ts +24 -0
  244. package/src/platform/node.ts +16 -0
  245. package/src/readiness/constants.ts +1 -0
  246. package/src/sdkClient/client.ts +11 -41
  247. package/src/sdkClient/clientInputValidation.ts +44 -84
  248. package/src/sdkClient/sdkClient.ts +5 -54
  249. package/src/sdkClient/sdkLifecycle.ts +78 -0
  250. package/src/sdkClient/trackMethod.ts +59 -0
  251. package/src/sdkFactory/index.ts +10 -54
  252. package/src/sdkFactory/types.ts +19 -16
  253. package/src/sdkManager/index.ts +9 -9
  254. package/src/services/splitApi.ts +6 -0
  255. package/src/services/types.ts +3 -2
  256. package/src/storages/AbstractSplitsCacheAsync.ts +7 -7
  257. package/src/storages/AbstractSplitsCacheSync.ts +10 -10
  258. package/src/storages/inLocalStorage/RBSegmentsCacheInLocal.ts +2 -2
  259. package/src/storages/inLocalStorage/SplitsCacheInLocal.ts +6 -6
  260. package/src/storages/inMemory/RBSegmentsCacheInMemory.ts +2 -2
  261. package/src/storages/inMemory/SplitsCacheInMemory.ts +5 -5
  262. package/src/storages/inMemory/TelemetryCacheInMemory.ts +2 -2
  263. package/src/storages/inRedis/RBSegmentsCacheInRedis.ts +2 -2
  264. package/src/storages/inRedis/SplitsCacheInRedis.ts +9 -9
  265. package/src/storages/pluggable/RBSegmentsCachePluggable.ts +2 -2
  266. package/src/storages/pluggable/SplitsCachePluggable.ts +9 -9
  267. package/src/storages/types.ts +21 -16
  268. package/src/sync/offline/splitsParser/parseCondition.ts +2 -2
  269. package/src/sync/offline/splitsParser/splitsParserFromSettings.ts +3 -3
  270. package/src/sync/offline/splitsParser/types.ts +6 -3
  271. package/src/sync/offline/syncManagerOffline.ts +2 -2
  272. package/src/sync/offline/syncTasks/fromObjectSyncTask.ts +6 -6
  273. package/src/sync/polling/fetchers/splitChangesFetcher.ts +57 -22
  274. package/src/sync/polling/fetchers/types.ts +5 -3
  275. package/src/sync/polling/pollingManagerCS.ts +12 -10
  276. package/src/sync/polling/pollingManagerSS.ts +15 -13
  277. package/src/sync/polling/syncTasks/{splitsSyncTask.ts → definitionsSyncTask.ts} +10 -11
  278. package/src/sync/polling/types.ts +3 -3
  279. package/src/sync/polling/updaters/{splitChangesUpdater.ts → definitionChangesUpdater.ts} +77 -68
  280. package/src/sync/polling/updaters/mySegmentsUpdater.ts +2 -2
  281. package/src/sync/polling/updaters/segmentChangesUpdater.ts +7 -7
  282. package/src/sync/streaming/UpdateWorkers/SplitsUpdateWorker.ts +6 -6
  283. package/src/sync/streaming/parseUtils.ts +12 -12
  284. package/src/sync/streaming/pushManager.ts +3 -3
  285. package/src/sync/submitters/impressionsSubmitter.ts +9 -9
  286. package/src/sync/submitters/types.ts +3 -0
  287. package/src/sync/syncManagerOnline.ts +6 -2
  288. package/src/trackers/eventTracker.ts +7 -10
  289. package/src/trackers/impressionsTracker.ts +42 -26
  290. package/src/trackers/types.ts +3 -1
  291. package/src/utils/EventEmitter.js +444 -0
  292. package/src/utils/filter/bloomFilter.ts +38 -0
  293. package/src/utils/inputValidation/definition.ts +27 -0
  294. package/src/utils/inputValidation/definitionExistence.ts +19 -0
  295. package/src/utils/inputValidation/definitions.ts +21 -0
  296. package/src/utils/inputValidation/index.ts +3 -3
  297. package/src/utils/inputValidation/isOperational.ts +4 -4
  298. package/src/utils/inputValidation/target.ts +21 -0
  299. package/src/utils/labels/index.ts +2 -2
  300. package/src/utils/settingsValidation/splitFilters.ts +3 -3
  301. package/types/splitio.d.ts +202 -9
  302. package/cjs/sync/polling/syncTasks/splitsSyncTask.js +0 -13
  303. package/cjs/utils/inputValidation/splits.js +0 -25
  304. package/esm/sync/polling/syncTasks/splitsSyncTask.js +0 -9
  305. package/esm/utils/inputValidation/splitExistence.js +0 -15
  306. package/esm/utils/inputValidation/splits.js +0 -21
  307. package/src/utils/inputValidation/split.ts +0 -27
  308. package/src/utils/inputValidation/splitExistence.ts +0 -19
  309. package/src/utils/inputValidation/splits.ts +0 -21
@@ -1,19 +1,20 @@
1
1
  import { ISegmentsCacheBase, IStorageBase } from '../../../storages/types';
2
- import { ISplitChangesFetcher } from '../fetchers/types';
3
- import { IRBSegment, ISplit, ISplitChangesResponse, ISplitFiltersValidation, MaybeThenable } from '../../../dtos/types';
2
+ import { IDefinitionChangesFetcher } from '../fetchers/types';
3
+ import { IRBSegment, IDefinition, IDefinitionChangesResponse, ISplitFiltersValidation, MaybeThenable } from '../../../dtos/types';
4
4
  import { ISplitsEventEmitter } from '../../../readiness/types';
5
5
  import { timeout } from '../../../utils/promise/timeout';
6
- import { SDK_SPLITS_ARRIVED, FLAGS_UPDATE, SEGMENTS_UPDATE } from '../../../readiness/constants';
6
+ import { SDK_SPLITS_ARRIVED, FLAGS_UPDATE, SEGMENTS_UPDATE, CONFIGS_UPDATE } from '../../../readiness/constants';
7
7
  import { ILogger } from '../../../logger/types';
8
- import { SYNC_SPLITS_FETCH, SYNC_SPLITS_UPDATE, SYNC_RBS_UPDATE, SYNC_SPLITS_FETCH_FAILS, SYNC_SPLITS_FETCH_RETRY } from '../../../logger/constants';
8
+ import { SYNC_FETCH, SYNC_UPDATE, SYNC_FETCH_FAILS, SYNC_FETCH_RETRY } from '../../../logger/constants';
9
9
  import { startsWith } from '../../../utils/lang';
10
10
  import { IN_RULE_BASED_SEGMENT, IN_SEGMENT, RULE_BASED_SEGMENT, STANDARD_SEGMENT } from '../../../utils/constants';
11
11
  import { setToArray } from '../../../utils/lang/sets';
12
12
  import { SPLIT_UPDATE } from '../../streaming/constants';
13
13
  import { SdkUpdateMetadata } from '../../../../types/splitio';
14
+ import { ISplit } from '../fetchers/splitChangesFetcher';
14
15
 
15
16
  export type InstantUpdate = { payload: ISplit | IRBSegment, changeNumber: number, type: string };
16
- type SplitChangesUpdater = (noCache?: boolean, till?: number, instantUpdate?: InstantUpdate) => Promise<boolean>
17
+ type DefinitionChangesUpdater = (noCache?: boolean, till?: number, instantUpdate?: InstantUpdate) => Promise<boolean>
17
18
 
18
19
  // Checks that all registered segments have been fetched (changeNumber !== -1 for every segment).
19
20
  // Returns a promise that could be rejected.
@@ -30,8 +31,8 @@ function checkAllSegmentsExist(segments: ISegmentsCacheBase): Promise<boolean> {
30
31
  * Collect segments from a raw FF or RBS definition.
31
32
  * Exported for testing purposes.
32
33
  */
33
- export function parseSegments(ruleEntity: ISplit | IRBSegment, matcherType: typeof IN_SEGMENT | typeof IN_RULE_BASED_SEGMENT = IN_SEGMENT): Set<string> {
34
- const { conditions = [], excluded } = ruleEntity as IRBSegment;
34
+ export function parseSegments(ruleEntity: IDefinition | IRBSegment, matcherType: typeof IN_SEGMENT | typeof IN_RULE_BASED_SEGMENT = IN_SEGMENT): Set<string> {
35
+ const { conditions, excluded } = ruleEntity as IRBSegment;
35
36
 
36
37
  const segments = new Set<string>();
37
38
  if (excluded && excluded.segments) {
@@ -42,146 +43,154 @@ export function parseSegments(ruleEntity: ISplit | IRBSegment, matcherType: type
42
43
  });
43
44
  }
44
45
 
45
- for (let i = 0; i < conditions.length; i++) {
46
- const matchers = conditions[i].matcherGroup.matchers;
46
+ if (conditions) {
47
+ for (let i = 0; i < conditions.length; i++) {
48
+ const matchers = conditions[i].matcherGroup.matchers;
47
49
 
48
- matchers.forEach(matcher => {
49
- if (matcher.matcherType === matcherType) segments.add(matcher.userDefinedSegmentMatcherData.segmentName);
50
- });
50
+ matchers.forEach(matcher => {
51
+ if (matcher.matcherType === matcherType) segments.add(matcher.userDefinedSegmentMatcherData.segmentName);
52
+ });
53
+ }
51
54
  }
52
55
 
53
56
  return segments;
54
57
  }
55
58
 
56
- interface ISplitMutations<T extends ISplit | IRBSegment> {
59
+ interface IDefinitionMutations<T extends IDefinition | IRBSegment> {
57
60
  added: T[],
58
- removed: T[],
61
+ removed: string[],
59
62
  names: string[]
60
63
  }
61
64
 
62
65
  /**
63
- * If there are defined filters and one feature flag doesn't match with them, its status is changed to 'ARCHIVE' to avoid storing it
66
+ * If there are defined filters and one definition doesn't match with them, its status is changed to 'ARCHIVE' to avoid storing it
64
67
  * If there is `bySet` filter, `byName` and `byPrefix` filters are ignored
65
68
  *
66
- * @param featureFlag - feature flag to be evaluated
69
+ * @param definition - definition to be evaluated
67
70
  * @param filters - splitFiltersValidation bySet | byName
68
71
  */
69
- function matchFilters(featureFlag: ISplit, filters: ISplitFiltersValidation) {
72
+ function matchFilters(definition: IDefinition, filters: ISplitFiltersValidation) {
70
73
  const { bySet: setsFilter, byName: namesFilter, byPrefix: prefixFilter } = filters.groupedFilters;
71
- if (setsFilter.length > 0) return featureFlag.sets && featureFlag.sets.some((featureFlagSet: string) => setsFilter.indexOf(featureFlagSet) > -1);
74
+ if (setsFilter.length > 0) return definition.sets && definition.sets.some((definitionSet: string) => setsFilter.indexOf(definitionSet) > -1);
72
75
 
73
76
  const namesFilterConfigured = namesFilter.length > 0;
74
77
  const prefixFilterConfigured = prefixFilter.length > 0;
75
78
 
76
79
  if (!namesFilterConfigured && !prefixFilterConfigured) return true;
77
80
 
78
- const matchNames = namesFilterConfigured && namesFilter.indexOf(featureFlag.name) > -1;
79
- const matchPrefix = prefixFilterConfigured && prefixFilter.some(prefix => startsWith(featureFlag.name, prefix));
81
+ const matchNames = namesFilterConfigured && namesFilter.indexOf(definition.name) > -1;
82
+ const matchPrefix = prefixFilterConfigured && prefixFilter.some(prefix => startsWith(definition.name, prefix));
80
83
  return matchNames || matchPrefix;
81
84
  }
82
85
 
83
86
  /**
84
- * Given the list of splits from /splitChanges endpoint, it returns the mutations,
85
- * i.e., an object with added splits, removed splits and used segments.
87
+ * Given the list of definitions from /splitChanges or /configs endpoint, it returns the mutations,
88
+ * i.e., an object with added definitions, removed definitions, and used segments.
86
89
  * Exported for testing purposes.
87
90
  */
88
- export function computeMutation<T extends ISplit | IRBSegment>(rules: Array<T>, segments: Set<string>, filters?: ISplitFiltersValidation): ISplitMutations<T> {
89
-
90
- return rules.reduce((accum, ruleEntity) => {
91
- if (ruleEntity.status === 'ACTIVE' && (!filters || matchFilters(ruleEntity as ISplit, filters))) {
91
+ export function computeMutation<T extends IDefinition | IRBSegment>(update: { updated: T[], removed: string[] }, segments: Set<string>, filters?: ISplitFiltersValidation): IDefinitionMutations<T> {
92
+ return update.updated.reduce((accum, ruleEntity) => {
93
+ if (!filters || matchFilters(ruleEntity as IDefinition, filters)) {
92
94
  accum.added.push(ruleEntity);
93
95
 
94
96
  parseSegments(ruleEntity).forEach((segmentName: string) => {
95
97
  segments.add(segmentName);
96
98
  });
97
99
  } else {
98
- accum.removed.push(ruleEntity);
100
+ accum.removed.push(ruleEntity.name);
99
101
  }
100
102
  accum.names.push(ruleEntity.name);
101
-
102
103
  return accum;
103
- }, { added: [], removed: [], names: [] } as ISplitMutations<T>);
104
+ }, { added: [], removed: update.removed, names: update.removed.slice() } as IDefinitionMutations<T>);
105
+ }
106
+
107
+ function convertInstantUpdateToDefinitionChanges(instantUpdate: InstantUpdate) {
108
+ const { payload, changeNumber } = instantUpdate;
109
+ return payload.status === 'ARCHIVED' ?
110
+ { till: changeNumber, updated: [], removed: [payload.name] } :
111
+ { till: changeNumber, updated: [payload], removed: [] };
104
112
  }
105
113
 
106
114
  /**
107
- * factory of SplitChanges updater, a task that:
108
- * - fetches split changes using `splitChangesFetcher`
109
- * - updates `splitsCache`
110
- * - uses `splitsEventEmitter` to emit events related to split data updates
115
+ * Factory of DefinitionChanges updater, a task that:
116
+ * - fetches definition changes using `definitionChangesFetcher`
117
+ * - updates definitions storage
118
+ * - uses `definitionsEventEmitter` to emit events related to definition data updates
111
119
  *
112
120
  * @param log - Logger instance
113
- * @param splitChangesFetcher - Fetcher of `/splitChanges`
114
- * @param splits - Splits storage, with sync or async methods
121
+ * @param definitionChangesFetcher - Fetcher of `/splitChanges` or `/configs`
122
+ * @param definitions - Definitions storage, with sync or async methods
115
123
  * @param segments - Segments storage, with sync or async methods
116
- * @param splitsEventEmitter - Optional readiness manager. Not required for synchronizer or producer mode.
124
+ * @param definitionsEventEmitter - Optional readiness manager. Not required for synchronizer or producer mode.
117
125
  * @param requestTimeoutBeforeReady - How long the updater will wait for the request to timeout. Default 0, i.e., never timeout.
118
- * @param retriesOnFailureBeforeReady - How many retries on `/splitChanges` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
126
+ * @param retriesOnFailureBeforeReady - How many retries on `/splitChanges` or `/configs` we the updater do in case of failure or timeout. Default 0, i.e., no retries.
119
127
  */
120
- export function splitChangesUpdaterFactory(
128
+ export function definitionChangesUpdaterFactory(
121
129
  log: ILogger,
122
- splitChangesFetcher: ISplitChangesFetcher,
130
+ definitionChangesFetcher: IDefinitionChangesFetcher,
123
131
  storage: Pick<IStorageBase, 'splits' | 'rbSegments' | 'segments' | 'save'>,
124
132
  splitFiltersValidation: ISplitFiltersValidation,
125
133
  splitsEventEmitter?: ISplitsEventEmitter,
126
134
  requestTimeoutBeforeReady = 0,
127
135
  retriesOnFailureBeforeReady = 0,
128
136
  isClientSide?: boolean
129
- ): SplitChangesUpdater {
137
+ ): DefinitionChangesUpdater {
130
138
  const { splits, rbSegments, segments } = storage;
131
139
 
132
140
  let startingUp = true;
133
141
 
134
- /** timeout decorator for `splitChangesFetcher` promise */
142
+ /** timeout decorator for `definitionChangesFetcher` promise */
135
143
  function _promiseDecorator<T>(promise: Promise<T>) {
136
144
  if (startingUp && requestTimeoutBeforeReady) promise = timeout(requestTimeoutBeforeReady, promise);
137
145
  return promise;
138
146
  }
139
147
 
140
148
  /**
141
- * SplitChanges updater returns a promise that resolves with a `false` boolean value if it fails to fetch splits or synchronize them with the storage.
149
+ * DefinitionChanges updater returns a promise that resolves with a `false` boolean value if it fails to fetch definitions or synchronize them with the storage.
142
150
  * Returned promise will not be rejected.
143
151
  *
144
152
  * @param noCache - true to revalidate data to fetch
145
153
  * @param till - query param to bypass CDN requests
146
154
  */
147
- return function splitChangesUpdater(noCache?: boolean, till?: number, instantUpdate?: InstantUpdate) {
155
+ return function definitionChangesUpdater(noCache?: boolean, till?: number, instantUpdate?: InstantUpdate) {
148
156
 
149
157
  /**
150
- * @param since - current changeNumber at splitsCache
158
+ * @param since - current changeNumber at definitionsCache
151
159
  * @param retry - current number of retry attempts
152
160
  */
153
- function _splitChangesUpdater(sinces: [number, number], retry = 0): Promise<boolean> {
161
+ function _definitionChangesUpdater(sinces: [number, number], retry = 0): Promise<boolean> {
154
162
  const [since, rbSince] = sinces;
155
- log.debug(SYNC_SPLITS_FETCH, sinces);
163
+ log.debug(SYNC_FETCH, [definitionChangesFetcher.type, since, rbSince]);
164
+
156
165
  return Promise.resolve(
157
166
  instantUpdate ?
158
167
  instantUpdate.type === SPLIT_UPDATE ?
159
- // IFFU edge case: a change to a flag that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
168
+ // IFFU edge case: a change to definition that adds an IN_RULE_BASED_SEGMENT matcher that is not present yet
160
169
  Promise.resolve(rbSegments.contains(parseSegments(instantUpdate.payload, IN_RULE_BASED_SEGMENT))).then((contains) => {
161
170
  return contains ?
162
- { ff: { d: [instantUpdate.payload as ISplit], t: instantUpdate.changeNumber } } :
163
- splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
171
+ { d: convertInstantUpdateToDefinitionChanges(instantUpdate) as IDefinitionChangesResponse['d'] } :
172
+ definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator);
164
173
  }) :
165
- { rbs: { d: [instantUpdate.payload as IRBSegment], t: instantUpdate.changeNumber } } :
166
- splitChangesFetcher(since, noCache, till, rbSince, _promiseDecorator)
174
+ { rbs: convertInstantUpdateToDefinitionChanges(instantUpdate) as IDefinitionChangesResponse['rbs'] } :
175
+ definitionChangesFetcher(since, noCache, till, rbSince, _promiseDecorator)
167
176
  )
168
- .then((splitChanges: ISplitChangesResponse) => {
177
+ .then((definitionChanges: IDefinitionChangesResponse) => {
169
178
  const usedSegments = new Set<string>();
170
179
 
171
- let updatedFlags: string[] = [];
180
+ let updatedDefinitions: string[] = [];
172
181
  let ffUpdate: MaybeThenable<boolean> = false;
173
- if (splitChanges.ff) {
174
- const { added, removed, names } = computeMutation(splitChanges.ff.d, usedSegments, splitFiltersValidation);
175
- updatedFlags = names;
176
- log.debug(SYNC_SPLITS_UPDATE, [added.length, removed.length]);
177
- ffUpdate = splits.update(added, removed, splitChanges.ff.t);
182
+ if (definitionChanges.d) {
183
+ const { added, removed, names } = computeMutation(definitionChanges.d, usedSegments, splitFiltersValidation);
184
+ updatedDefinitions = names;
185
+ log.debug(SYNC_UPDATE, [definitionChangesFetcher.type, added.length, removed.length]);
186
+ ffUpdate = splits.update(added, removed, definitionChanges.d.till);
178
187
  }
179
188
 
180
189
  let rbsUpdate: MaybeThenable<boolean> = false;
181
- if (splitChanges.rbs) {
182
- const { added, removed } = computeMutation(splitChanges.rbs.d, usedSegments);
183
- log.debug(SYNC_RBS_UPDATE, [added.length, removed.length]);
184
- rbsUpdate = rbSegments.update(added, removed, splitChanges.rbs.t);
190
+ if (definitionChanges.rbs) {
191
+ const { added, removed } = computeMutation(definitionChanges.rbs, usedSegments);
192
+ log.debug(SYNC_UPDATE, ['rule-based segments', added.length, removed.length]);
193
+ rbsUpdate = rbSegments.update(added, removed, definitionChanges.rbs.till);
185
194
  }
186
195
 
187
196
  return Promise.all([ffUpdate, rbsUpdate,
@@ -200,8 +209,8 @@ export function splitChangesUpdaterFactory(
200
209
  // emit SDK events
201
210
  if (emitSplitsArrivedEvent) {
202
211
  const metadata: SdkUpdateMetadata = {
203
- type: updatedFlags.length > 0 ? FLAGS_UPDATE : SEGMENTS_UPDATE,
204
- names: updatedFlags.length > 0 ? updatedFlags : []
212
+ type: updatedDefinitions.length > 0 ? definitionChangesFetcher.type === 'configs' ? CONFIGS_UPDATE : FLAGS_UPDATE : SEGMENTS_UPDATE,
213
+ names: updatedDefinitions.length > 0 ? updatedDefinitions : []
205
214
  };
206
215
  splitsEventEmitter.emit(SDK_SPLITS_ARRIVED, metadata);
207
216
  }
@@ -214,17 +223,17 @@ export function splitChangesUpdaterFactory(
214
223
  .catch(error => {
215
224
  if (startingUp && retriesOnFailureBeforeReady > retry) {
216
225
  retry += 1;
217
- log.warn(SYNC_SPLITS_FETCH_RETRY, [retry, error]);
218
- return _splitChangesUpdater(sinces, retry);
226
+ log.warn(SYNC_FETCH_RETRY, [definitionChangesFetcher.type, retry, error]);
227
+ return _definitionChangesUpdater(sinces, retry);
219
228
  } else {
220
229
  startingUp = false;
221
- log.warn(SYNC_SPLITS_FETCH_FAILS, [error]);
230
+ log.warn(SYNC_FETCH_FAILS, [definitionChangesFetcher.type, error]);
222
231
  }
223
232
  return false;
224
233
  });
225
234
  }
226
235
 
227
236
  // `getChangeNumber` never rejects or throws error
228
- return Promise.all([splits.getChangeNumber(), rbSegments.getChangeNumber()]).then(_splitChangesUpdater);
237
+ return Promise.all([splits.getChangeNumber(), rbSegments.getChangeNumber()]).then(_definitionChangesUpdater);
229
238
  };
230
239
  }
@@ -4,7 +4,7 @@ import { ISegmentsEventEmitter } from '../../../readiness/types';
4
4
  import { timeout } from '../../../utils/promise/timeout';
5
5
  import { SDK_SEGMENTS_ARRIVED, SEGMENTS_UPDATE } from '../../../readiness/constants';
6
6
  import { ILogger } from '../../../logger/types';
7
- import { SYNC_MYSEGMENTS_FETCH_RETRY } from '../../../logger/constants';
7
+ import { SYNC_FETCH_RETRY } from '../../../logger/constants';
8
8
  import { MySegmentsData } from '../types';
9
9
  import { IMembershipsResponse } from '../../../dtos/types';
10
10
  import { MEMBERSHIPS_LS_UPDATE } from '../../streaming/constants';
@@ -76,7 +76,7 @@ export function mySegmentsUpdaterFactory(
76
76
  return updaterPromise.catch(error => {
77
77
  if (startingUp && retriesOnFailureBeforeReady > retry) {
78
78
  retry += 1;
79
- log.warn(SYNC_MYSEGMENTS_FETCH_RETRY, [retry, error]);
79
+ log.warn(SYNC_FETCH_RETRY, ['memberships', retry, error]);
80
80
  return _mySegmentsUpdater(retry); // no need to forward `segmentList` and `noCache` params
81
81
  } else {
82
82
  startingUp = false;
@@ -3,7 +3,7 @@ import { ISegmentsCacheBase } from '../../../storages/types';
3
3
  import { IReadinessManager } from '../../../readiness/types';
4
4
  import { SDK_SEGMENTS_ARRIVED, SEGMENTS_UPDATE } from '../../../readiness/constants';
5
5
  import { ILogger } from '../../../logger/types';
6
- import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC_SEGMENTS } from '../../../logger/constants';
6
+ import { LOG_PREFIX_INSTANTIATION, LOG_PREFIX_SYNC } from '../../../logger/constants';
7
7
  import { timeout } from '../../../utils/promise/timeout';
8
8
  import { SdkUpdateMetadata } from '../../../../types/splitio';
9
9
 
@@ -38,7 +38,7 @@ export function segmentChangesUpdaterFactory(
38
38
  }
39
39
 
40
40
  function updateSegment(segmentName: string, noCache?: boolean, till?: number, fetchOnlyNew?: boolean, retries?: number): Promise<boolean> {
41
- log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processing segment ${segmentName}`);
41
+ log.debug(`${LOG_PREFIX_SYNC}Processing segment ${segmentName}`);
42
42
  const sincePromise = Promise.resolve(segments.getChangeNumber(segmentName));
43
43
 
44
44
  return sincePromise.then(since => {
@@ -47,14 +47,14 @@ export function segmentChangesUpdaterFactory(
47
47
  false :
48
48
  segmentChangesFetcher(since || -1, segmentName, noCache, till, _promiseDecorator).then((changes) => {
49
49
  return Promise.all(changes.map(x => {
50
- log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
50
+ log.debug(`${LOG_PREFIX_SYNC}Processing ${segmentName} with till = ${x.till}. Added: ${x.added.length}. Removed: ${x.removed.length}`);
51
51
  return segments.update(segmentName, x.added, x.removed, x.till);
52
52
  })).then((updates) => {
53
53
  return updates.some(update => update);
54
54
  });
55
55
  }).catch(error => {
56
56
  if (retries) {
57
- log.warn(`${LOG_PREFIX_SYNC_SEGMENTS}Retrying fetch of segment ${segmentName} (attempt #${retries}). Reason: ${error}`);
57
+ log.warn(`${LOG_PREFIX_SYNC}Retrying fetch of segment ${segmentName} (attempt #${retries}). Reason: ${error}`);
58
58
  return updateSegment(segmentName, noCache, till, fetchOnlyNew, retries - 1);
59
59
  }
60
60
  throw error;
@@ -73,7 +73,7 @@ export function segmentChangesUpdaterFactory(
73
73
  * @param till - till target for the provided segmentName, for CDN bypass.
74
74
  */
75
75
  return function segmentChangesUpdater(fetchOnlyNew?: boolean, segmentName?: string, noCache?: boolean, till?: number) {
76
- log.debug(`${LOG_PREFIX_SYNC_SEGMENTS}Started segments update`);
76
+ log.debug(`${LOG_PREFIX_SYNC}Started segments update`);
77
77
 
78
78
  // If not a segment name provided, read list of available segments names to be updated.
79
79
  let segmentsPromise = Promise.resolve(segmentName ? [segmentName] : segments.getRegisteredSegments());
@@ -102,9 +102,9 @@ export function segmentChangesUpdaterFactory(
102
102
  // If the operation is forbidden, it may be due to permissions. Destroy the SDK instance.
103
103
  // @TODO although factory status is destroyed, synchronization is not stopped
104
104
  if (readiness) readiness.setDestroyed();
105
- log.error(`${LOG_PREFIX_INSTANTIATION}: you passed a client-side type authorizationKey, please grab an SDK Key from the Split user interface that is of type server-side.`);
105
+ log.error(`${LOG_PREFIX_INSTANTIATION}: you passed a client-side type authorizationKey, please grab an SDK Key from Harness UI that is of type server-side.`);
106
106
  } else {
107
- log.warn(`${LOG_PREFIX_SYNC_SEGMENTS}Error while doing fetch of segments. ${error}`);
107
+ log.warn(`${LOG_PREFIX_SYNC}Error while doing fetch of segments. ${error}`);
108
108
  }
109
109
 
110
110
  return false;
@@ -1,4 +1,4 @@
1
- import { IRBSegment, ISplit } from '../../../dtos/types';
1
+ import { IRBSegment, IDefinition } from '../../../dtos/types';
2
2
  import { STREAMING_PARSING_SPLIT_UPDATE } from '../../../logger/constants';
3
3
  import { ILogger } from '../../../logger/types';
4
4
  import { SDK_SPLITS_ARRIVED } from '../../../readiness/constants';
@@ -7,8 +7,8 @@ import { IRBSegmentsCacheSync, ISplitsCacheSync, IStorageSync } from '../../../s
7
7
  import { ITelemetryTracker } from '../../../trackers/types';
8
8
  import { Backoff } from '../../../utils/Backoff';
9
9
  import { SPLITS } from '../../../utils/constants';
10
- import { ISegmentsSyncTask, ISplitsSyncTask } from '../../polling/types';
11
- import { InstantUpdate } from '../../polling/updaters/splitChangesUpdater';
10
+ import { ISegmentsSyncTask, IDefinitionsSyncTask } from '../../polling/types';
11
+ import { InstantUpdate } from '../../polling/updaters/definitionChangesUpdater';
12
12
  import { RB_SEGMENT_UPDATE } from '../constants';
13
13
  import { parseFFUpdatePayload } from '../parseUtils';
14
14
  import { ISplitKillData, ISplitUpdateData } from '../SSEHandler/types';
@@ -18,7 +18,7 @@ import { IUpdateWorker } from './types';
18
18
  /**
19
19
  * SplitsUpdateWorker factory
20
20
  */
21
- export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSyncTask: ISplitsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker<[updateData: ISplitUpdateData]> & { killSplit(event: ISplitKillData): void } {
21
+ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, definitionsSyncTask: IDefinitionsSyncTask, splitsEventEmitter: ISplitsEventEmitter, telemetryTracker: ITelemetryTracker, segmentsSyncTask?: ISegmentsSyncTask): IUpdateWorker<[updateData: ISplitUpdateData]> & { killSplit(event: ISplitKillData): void } {
22
22
 
23
23
  const ff = SplitsUpdateWorker(storage.splits);
24
24
  const rbs = SplitsUpdateWorker(storage.rbSegments);
@@ -36,7 +36,7 @@ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSy
36
36
  if (maxChangeNumber > cache.getChangeNumber()) {
37
37
  handleNewEvent = false;
38
38
  // fetch splits revalidating data if cached
39
- splitsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, instantUpdate).then(() => {
39
+ definitionsSyncTask.execute(true, cdnBypass ? maxChangeNumber : undefined, instantUpdate).then(() => {
40
40
  if (!isHandlingEvent) return; // halt if `stop` has been called
41
41
  if (handleNewEvent) {
42
42
  __handleSplitUpdateCall();
@@ -79,7 +79,7 @@ export function SplitsUpdateWorker(log: ILogger, storage: IStorageSync, splitsSy
79
79
  *
80
80
  * @param changeNumber - change number of the notification
81
81
  */
82
- put({ changeNumber, pcn, type }: ISplitUpdateData, payload?: ISplit | IRBSegment) {
82
+ put({ changeNumber, pcn, type }: ISplitUpdateData, payload?: IDefinition | IRBSegment) {
83
83
  const currentChangeNumber = cache.getChangeNumber();
84
84
 
85
85
  if (changeNumber <= currentChangeNumber || changeNumber <= maxChangeNumber) return;
@@ -1,8 +1,8 @@
1
1
  import { algorithms } from '../../utils/decompress';
2
2
  import { decodeFromBase64 } from '../../utils/base64';
3
3
  import { hash } from '../../utils/murmur3/murmur3';
4
- import { Compression, IMembershipMSUpdateData, KeyList } from './SSEHandler/types';
5
- import { IRBSegment, ISplit } from '../../dtos/types';
4
+ import { Compression, IMembershipMSUpdateData } from './SSEHandler/types';
5
+ import { IRBSegment, IDefinition } from '../../dtos/types';
6
6
 
7
7
  const GZIP = 1;
8
8
  const ZLIB = 2;
@@ -35,20 +35,20 @@ function decompress(data: string, compression: Compression) {
35
35
  }
36
36
 
37
37
  /**
38
- * Decode, decompress and parse the provided 'data' into a KeyList object
38
+ * Decode, decompress and parse the provided 'data' into an object of type T
39
39
  *
40
40
  * @param data - base64 encoded string
41
41
  * @param compression - 1 GZIP, 2 ZLIB
42
42
  * @param avoidPrecisionLoss - true as default, set it as false if dont need to avoid precission loss
43
- * @returns keyList
43
+ * @returns parsed object
44
44
  * @throws if data string cannot be decoded, decompressed or parsed
45
45
  */
46
- export function parseKeyList(data: string, compression: Compression, avoidPrecisionLoss = true): KeyList {
47
- const binKeyList = decompress(data, compression);
48
- let strKeyList = Uint8ArrayToString(binKeyList);
49
- // replace numbers to strings, to avoid losing precision
50
- if (avoidPrecisionLoss) strKeyList = strKeyList.replace(/\d+/g, '"$&"');
51
- return JSON.parse(strKeyList);
46
+ export function parseCompressedData<T>(data: string, compression: Compression, avoidPrecisionLoss = true): T {
47
+ const binData = decompress(data, compression);
48
+ let str = Uint8ArrayToString(binData);
49
+ // replace numbers to strings, to avoid losing precision (e.g., 64-bit IDs in KeyList)
50
+ if (avoidPrecisionLoss) str = str.replace(/\d+/g, '"$&"');
51
+ return JSON.parse(str) as T;
52
52
  }
53
53
 
54
54
  /**
@@ -82,9 +82,9 @@ export function isInBitmap(bitmap: Uint8Array, hash64hex: string) {
82
82
  /**
83
83
  * Parse feature flags notifications for instant feature flag updates
84
84
  */
85
- export function parseFFUpdatePayload(compression: Compression, data: string): ISplit | IRBSegment | undefined {
85
+ export function parseFFUpdatePayload(compression: Compression, data: string): IDefinition | IRBSegment | undefined {
86
86
  return compression > 0 ?
87
- parseKeyList(data, compression, false) :
87
+ parseCompressedData<IDefinition | IRBSegment>(data, compression, false) :
88
88
  JSON.parse(decodeFromBase64(data));
89
89
  }
90
90
 
@@ -14,7 +14,7 @@ import { checkIfServerSide, getMatching } from '../../utils/key';
14
14
  import { MEMBERSHIPS_MS_UPDATE, MEMBERSHIPS_LS_UPDATE, PUSH_NONRETRYABLE_ERROR, PUSH_SUBSYSTEM_DOWN, SECONDS_BEFORE_EXPIRATION, SEGMENT_UPDATE, SPLIT_KILL, SPLIT_UPDATE, RB_SEGMENT_UPDATE, PUSH_RETRYABLE_ERROR, PUSH_SUBSYSTEM_UP, ControlType } from './constants';
15
15
  import { STREAMING_FALLBACK, STREAMING_REFRESH_TOKEN, STREAMING_CONNECTING, STREAMING_DISABLED, ERROR_STREAMING_AUTH, STREAMING_DISCONNECTING, STREAMING_RECONNECT, STREAMING_PARSING_MEMBERSHIPS_UPDATE } from '../../logger/constants';
16
16
  import { IMembershipMSUpdateData, IMembershipLSUpdateData, KeyList, UpdateStrategy } from './SSEHandler/types';
17
- import { getDelay, isInBitmap, parseBitmap, parseKeyList } from './parseUtils';
17
+ import { getDelay, isInBitmap, parseBitmap, parseCompressedData } from './parseUtils';
18
18
  import { Hash64, hash64 } from '../../utils/murmur3/murmur3_64';
19
19
  import { IAuthTokenPushEnabled } from './AuthClient/types';
20
20
  import { TOKEN_REFRESH, AUTH_REJECTION } from '../../utils/constants';
@@ -56,7 +56,7 @@ export function pushManagerFactory(
56
56
  // MySegmentsUpdateWorker (client-side) are initiated in `add` method
57
57
  const segmentsUpdateWorker = userKey ? undefined : SegmentsUpdateWorker(log, pollingManager.segmentsSyncTask as ISegmentsSyncTask, storage.segments);
58
58
  // For server-side we pass the segmentsSyncTask, used by SplitsUpdateWorker to fetch new segments
59
- const splitsUpdateWorker = SplitsUpdateWorker(log, storage, pollingManager.splitsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
59
+ const splitsUpdateWorker = SplitsUpdateWorker(log, storage, pollingManager.definitionsSyncTask, readiness.splits, telemetryTracker, userKey ? undefined : pollingManager.segmentsSyncTask as ISegmentsSyncTask);
60
60
 
61
61
  // [Only for client-side] map of hashes to user keys, to dispatch membership update events to the corresponding MySegmentsUpdateWorker
62
62
  const userKeyHashes: Record<string, string> = {};
@@ -243,7 +243,7 @@ export function pushManagerFactory(
243
243
  case UpdateStrategy.KeyList: {
244
244
  let keyList: KeyList, added: Set<string>, removed: Set<string>;
245
245
  try {
246
- keyList = parseKeyList(parsedData.d!, parsedData.c!);
246
+ keyList = parseCompressedData<KeyList>(parsedData.d!, parsedData.c!);
247
247
  added = new Set(keyList.a);
248
248
  removed = new Set(keyList.r);
249
249
  } catch (e) {
@@ -3,20 +3,20 @@ import SplitIO from '../../../types/splitio';
3
3
  import { submitterFactory } from './submitter';
4
4
  import { ImpressionsPayload } from './types';
5
5
  import { SUBMITTERS_PUSH_FULL_QUEUE } from '../../logger/constants';
6
- import { ISdkFactoryContextSync } from '../../sdkFactory/types';
6
+ import { EntityType, ISdkFactoryContextSync } from '../../sdkFactory/types';
7
7
 
8
8
  /**
9
9
  * Converts `impressions` data from cache into request payload.
10
10
  */
11
- export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.ImpressionDTO[]): ImpressionsPayload {
11
+ export function fromImpressionsCollector(sendLabels: boolean, entityType: EntityType | undefined, data: SplitIO.ImpressionDTO[]): ImpressionsPayload {
12
12
  let groupedByFeature = groupBy(data, 'feature');
13
13
  let dto: ImpressionsPayload = [];
14
14
 
15
15
  forOwn(groupedByFeature, (value, name) => {
16
16
  dto.push({
17
- f: name, // Test Name
17
+ f: name, // Definition type
18
18
  i: value.map(entry => { // Key Impressions
19
- const keyImpression = {
19
+ return {
20
20
  k: entry.keyName, // Key
21
21
  t: entry.treatment, // Treatment
22
22
  m: entry.time, // Timestamp
@@ -24,10 +24,9 @@ export function fromImpressionsCollector(sendLabels: boolean, data: SplitIO.Impr
24
24
  r: sendLabels ? entry.label : undefined, // Rule
25
25
  b: entry.bucketingKey, // Bucketing Key
26
26
  pt: entry.pt, // Previous time
27
- properties: entry.properties // Properties
27
+ properties: entry.properties, // Properties
28
+ et: entityType, // Definition type
28
29
  };
29
-
30
- return keyImpression;
31
30
  })
32
31
  });
33
32
  });
@@ -43,11 +42,12 @@ export function impressionsSubmitterFactory(params: ISdkFactoryContextSync) {
43
42
  const {
44
43
  settings: { log, scheduler: { impressionsRefreshRate }, core: { labelsEnabled } },
45
44
  splitApi: { postTestImpressionsBulk },
46
- storage: { impressions }
45
+ storage: { impressions },
46
+ entityType
47
47
  } = params;
48
48
 
49
49
  // retry impressions only once.
50
- const syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, fromImpressionsCollector.bind(undefined, labelsEnabled), 1);
50
+ const syncTask = submitterFactory(log, postTestImpressionsBulk, impressions, impressionsRefreshRate, fromImpressionsCollector.bind(undefined, labelsEnabled, entityType), 1);
51
51
 
52
52
  // register impressions submitter to be executed when impressions cache is full
53
53
  impressions.setOnFullQueueCb(() => {
@@ -2,6 +2,7 @@
2
2
  import { IMetadata } from '../../dtos/types';
3
3
  import SplitIO from '../../../types/splitio';
4
4
  import { ISyncTask } from '../types';
5
+ import { EntityType } from '../../sdkFactory/types';
5
6
 
6
7
  type ImpressionPayload = {
7
8
  /** Matching Key */
@@ -20,6 +21,8 @@ type ImpressionPayload = {
20
21
  pt?: number;
21
22
  /** Stringified JSON object with properties */
22
23
  properties?: string;
24
+ /** Definition type */
25
+ et?: EntityType,
23
26
  };
24
27
 
25
28
  export type ImpressionsPayload = {
@@ -11,6 +11,8 @@ import { POLLING, STREAMING, SYNC_MODE_UPDATE } from '../utils/constants';
11
11
  import { ISdkFactoryContextSync } from '../sdkFactory/types';
12
12
  import { SDK_SPLITS_CACHE_LOADED } from '../readiness/constants';
13
13
  import { usesSegmentsSync } from '../storages/AbstractSplitsCacheSync';
14
+ import { splitChangesFetcherFactory } from './polling/fetchers/splitChangesFetcher';
15
+ import { IDefinitionChangesFetcher } from './polling/fetchers/types';
14
16
 
15
17
  /**
16
18
  * Online SyncManager factory.
@@ -19,10 +21,12 @@ import { usesSegmentsSync } from '../storages/AbstractSplitsCacheSync';
19
21
  * @param pollingManagerFactory - allows to specialize the SyncManager for server-side or client-side API by passing
20
22
  * `pollingManagerSSFactory` or `pollingManagerCSFactory` respectively.
21
23
  * @param pushManagerFactory - optional to build a SyncManager with or without streaming support
24
+ * @param definitionChangesFetcherFactory - optional to replace the default split changes fetcher
22
25
  */
23
26
  export function syncManagerOnlineFactory(
24
- pollingManagerFactory?: (params: ISdkFactoryContextSync) => IPollingManager,
27
+ pollingManagerFactory?: (params: ISdkFactoryContextSync, definitionChangesFetcher: IDefinitionChangesFetcher) => IPollingManager,
25
28
  pushManagerFactory?: (params: ISdkFactoryContextSync, pollingManager: IPollingManager) => IPushManager | undefined,
29
+ definitionChangesFetcherFactory = splitChangesFetcherFactory
26
30
  ): (params: ISdkFactoryContextSync) => ISyncManagerCS {
27
31
 
28
32
  /**
@@ -33,7 +37,7 @@ export function syncManagerOnlineFactory(
33
37
  const { settings, settings: { log, streamingEnabled, sync: { enabled: syncEnabled } }, telemetryTracker, storage, readiness } = params;
34
38
 
35
39
  /** Polling Manager */
36
- const pollingManager = pollingManagerFactory && pollingManagerFactory(params);
40
+ const pollingManager = pollingManagerFactory && pollingManagerFactory(params, definitionChangesFetcherFactory(params));
37
41
 
38
42
  /** Push Manager */
39
43
  const pushManager = syncEnabled && streamingEnabled && pollingManager && pushManagerFactory ?
@@ -17,7 +17,6 @@ import { isConsumerMode } from '../utils/settingsValidation/mode';
17
17
  export function eventTrackerFactory(
18
18
  settings: ISettings,
19
19
  eventsCache: IEventsCacheBase,
20
- whenInit: (cb: () => void) => void,
21
20
  integrationsManager?: IEventsHandler,
22
21
  telemetryCache?: ITelemetryCacheSync | ITelemetryCacheAsync
23
22
  ): IEventTracker {
@@ -33,15 +32,13 @@ export function eventTrackerFactory(
33
32
  if (tracked) {
34
33
  log.info(EVENTS_TRACKER_SUCCESS, [msg]);
35
34
  if (integrationsManager) {
36
- whenInit(() => {
37
- // Wrap in a timeout because we don't want it to be blocking.
38
- setTimeout(() => {
39
- // copy of event, to avoid unexpected behavior if modified by integrations
40
- const eventDataCopy = objectAssign({}, eventData);
41
- if (properties) eventDataCopy.properties = objectAssign({}, properties);
42
- // integrationsManager does not throw errors (they are internally handled by each integration module)
43
- integrationsManager.handleEvent(eventDataCopy);
44
- });
35
+ // Wrap in a timeout because we don't want it to be blocking.
36
+ setTimeout(() => {
37
+ // copy of event, to avoid unexpected behavior if modified by integrations
38
+ const eventDataCopy = objectAssign({}, eventData);
39
+ if (properties) eventDataCopy.properties = objectAssign({}, properties);
40
+ // integrationsManager does not throw errors (they are internally handled by each integration module)
41
+ integrationsManager.handleEvent(eventDataCopy);
45
42
  });
46
43
  }
47
44
  } else {