@@ -13,12 +13,13 @@ import unboundedMessage from '../mocks/message.MEMBERSHIPS_MS_UPDATE.UNBOUNDED.1
1313import boundedZlibMessage from '../mocks/message.MEMBERSHIPS_MS_UPDATE.BOUNDED.ZLIB.1457552651000.json' ;
1414import keylistGzipMessage from '../mocks/message.MEMBERSHIPS_MS_UPDATE.KEYLIST.GZIP.1457552652000.json' ;
1515import segmentRemovalMessage from '../mocks/message.MEMBERSHIPS_MS_UPDATE.SEGMENT_REMOVAL.1457552653000.json' ;
16- import unboundedMyLargeSegmentsMessage from '../mocks/message.MEMBERSHIPS_LS_UPDATE.UNBOUNDED.DELAY.1457552650000.json' ;
17- import myLargeSegmentRemovalMessage from '../mocks/message.MEMBERSHIPS_LS_UPDATE.SEGMENT_REMOVAL.1457552653000.json' ;
16+ import unboundedLSMessage from '../mocks/message.MEMBERSHIPS_LS_UPDATE.UNBOUNDED.DELAY.1457552650000.json' ;
17+ import segmentRemovalLSMessage from '../mocks/message.MEMBERSHIPS_LS_UPDATE.SEGMENT_REMOVAL.1457552653000.json' ;
1818
1919import authPushEnabledNicolas from '../mocks/auth.pushEnabled.nicolas@split.io.json' ;
2020import authPushEnabledNicolasAndMarcio from '../mocks/auth.pushEnabled.nicolas@split.io.marcio@split.io.json' ;
2121
22+ import { Backoff } from '@splitsoftware/splitio-commons/src/utils/Backoff' ;
2223import { nearlyEqual , url , hasNoCacheHeader } from '../testUtils' ;
2324
2425// Replace original EventSource with mock
@@ -64,7 +65,8 @@ const MILLIS_MEMBERSHIPS_MS_UPDATE_BOUNDED = 1100;
6465const MILLIS_MEMBERSHIPS_MS_UPDATE_KEYLIST = 1200 ;
6566const MILLIS_MEMBERSHIPS_MS_UPDATE_SEGMENT_REMOVAL = 1300 ;
6667const MILLIS_MEMBERSHIPS_LS_UPDATE_UNBOUNDED_FETCH = 1400 ;
67- const MILLIS_MEMBERSHIPS_LS_UPDATE_SEGMENT_REMOVAL = 1800 ;
68+ const MILLIS_MEMBERSHIPS_LS_UPDATE_SEGMENT_REMOVAL = 1900 ;
69+ const EXPECTED_DELAY_AND_BACKOFF = 241 + 100 ;
6870
6971/**
7072 * Sequence of calls:
@@ -82,12 +84,14 @@ const MILLIS_MEMBERSHIPS_LS_UPDATE_SEGMENT_REMOVAL = 1800;
8284 * 1.1 secs: MEMBERSHIPS_MS_UPDATE BoundedFetchRequest event.
8385 * 1.2 secs: MEMBERSHIPS_MS_UPDATE KeyList event.
8486 * 1.3 secs: MEMBERSHIPS_MS_UPDATE SegmentRemoval event.
85- // WITH CN IN THE RESPONSE
8687 * 1.4 secs: MEMBERSHIPS_LS_UPDATE UnboundedFetchRequest event, with 241 ms delay for 'nicolas@split.io' (hash('nicolas@split.io') % 300)
87- * 1.641 secs: /memberships/* fetch due to unbounded MEMBERSHIPS_LS_UPDATE event -> SDK_UPDATE event
88- * 1.8 secs: MEMBERSHIPS_LS_UPDATE SegmentRemoval event -> SPLIT_UPDATE event
88+ * 1.641 secs: /memberships/* fetch due to unbounded MEMBERSHIPS_LS_UPDATE event, with an old changeNumber
89+ * 1.741 secs: /memberships/* fetch due to unbounded MEMBERSHIPS_LS_UPDATE event, with the target changeNumber -> SDK_UPDATE event
90+ * 1.9 secs: MEMBERSHIPS_LS_UPDATE SegmentRemoval event -> SPLIT_UPDATE event
8991 */
9092export function testSynchronization ( fetchMock , assert ) {
93+ // Force the backoff base of UpdateWorkers to reduce test time
94+ Backoff . __TEST__BASE_MILLIS = 100 ;
9195 assert . plan ( 34 ) ;
9296 fetchMock . reset ( ) ;
9397
@@ -198,14 +202,13 @@ export function testSynchronization(fetchMock, assert) {
198202 assert . equal ( client . getTreatment ( 'in_large_segment' ) , 'no' , 'evaluation before myLargeSegment fetch' ) ;
199203
200204 const timestampUnboundEvent = Date . now ( ) ;
201- const EXPECTED_DELAY = 241 ;
202205
203206 client . once ( client . Event . SDK_UPDATE , ( ) => {
204- assert . true ( nearlyEqual ( Date . now ( ) - timestampUnboundEvent , EXPECTED_DELAY ) , 'SDK_UPDATE after fetching memberships with a delay' ) ;
207+ assert . true ( nearlyEqual ( Date . now ( ) - timestampUnboundEvent , EXPECTED_DELAY_AND_BACKOFF ) , 'SDK_UPDATE after fetching memberships with a delay' ) ;
205208 assert . equal ( client . getTreatment ( 'in_large_segment' ) , 'yes' , 'evaluation after myLargeSegment fetch' ) ;
206209 } ) ;
207210
208- eventSourceInstance . emitMessage ( unboundedMyLargeSegmentsMessage ) ;
211+ eventSourceInstance . emitMessage ( unboundedLSMessage ) ;
209212 } , MILLIS_MEMBERSHIPS_LS_UPDATE_UNBOUNDED_FETCH - MILLIS_MORE_CLIENTS ) ;
210213
211214 setTimeout ( ( ) => {
@@ -225,12 +228,14 @@ export function testSynchronization(fetchMock, assert) {
225228 client . destroy ( ) . then ( ( ) => {
226229 assert . equal ( client . getTreatment ( 'whitelist' ) , 'control' , 'evaluation returns control for main client if it is destroyed' ) ;
227230 assert . equal ( eventSourceInstance . readyState , EventSourceMock . CLOSED , 'streaming is closed after destroy' ) ;
231+
232+ Backoff . __TEST__BASE_MILLIS = undefined ;
228233 assert . end ( ) ;
229234 } ) ;
230235 } ) ;
231236 } ) ;
232237
233- eventSourceInstance . emitMessage ( myLargeSegmentRemovalMessage ) ;
238+ eventSourceInstance . emitMessage ( segmentRemovalLSMessage ) ;
234239 } , MILLIS_MEMBERSHIPS_LS_UPDATE_SEGMENT_REMOVAL - MILLIS_MORE_CLIENTS ) ;
235240 } ) ;
236241 } , MILLIS_MORE_CLIENTS - MILLIS_NEW_CLIENT ) ;
@@ -321,15 +326,16 @@ export function testSynchronization(fetchMock, assert) {
321326 } ) ;
322327
323328 // 3 unbounded fetch for MEMBERSHIPS_MS_UPDATE + 1 unbounded fetch for MEMBERSHIPS_LS_UPDATE
324- fetchMock . get ( { url : url ( settings , '/memberships/nicolas%40split.io' ) , repeat : 3 } , function ( url , opts ) {
325- if ( ! hasNoCacheHeader ( opts ) ) assert . fail ( 'request must not include `Cache-Control` header' ) ;
326- return { status : 200 , body : membershipsNicolasMock2 } ;
327- } ) ;
328- fetchMock . getOnce ( url ( settings , '/memberships/nicolas%40split.io' ) , { status : 200 , body : { ...membershipsNicolasMock2 , ls : { k : [ { n : 'employees' } , { n : 'splitters' } ] } } } ) ;
329329 fetchMock . get ( { url : url ( settings , '/memberships/marcio%40split.io' ) , repeat : 4 } , function ( url , opts ) {
330330 if ( ! hasNoCacheHeader ( opts ) ) assert . fail ( 'request must not include `Cache-Control` header' ) ;
331331 return { status : 200 , body : membershipsMarcio } ;
332332 } ) ;
333+ fetchMock . get ( { url : url ( settings , '/memberships/nicolas%40split.io' ) , repeat : 3 } , function ( url , opts ) {
334+ if ( ! hasNoCacheHeader ( opts ) ) assert . fail ( 'request must not include `Cache-Control` header' ) ;
335+ return { status : 200 , body : membershipsNicolasMock2 } ;
336+ } ) ;
337+ fetchMock . getOnce ( url ( settings , '/memberships/nicolas%40split.io' ) , { status : 200 , body : { ms : { k : [ { n : 'developers' } , { n : 'engineers' } ] } , ls : { k : [ ] , cn : 1457552640000 } } } ) ; // not target changeNumber
338+ fetchMock . getOnce ( url ( settings , '/memberships/nicolas%40split.io' ) , { status : 200 , body : { ms : { k : [ { n : 'developers' } , { n : 'engineers' } ] } , ls : { k : [ { n : 'employees' } , { n : 'splitters' } ] , cn : 1457552650000 } } } ) ; // target changeNumber
333339
334340 // initial fetch of memberships for other clients + sync all after third SSE opened + 3 unbounded fetch for MEMBERSHIPS_MS_UPDATE + 1 unbounded fetch for MEMBERSHIPS_LS_UPDATE
335341 fetchMock . getOnce ( url ( settings , '/splitChanges?s=1.2&since=1457552650000' ) , { status : 200 , body : { splits : [ ] , since : 1457552650000 , till : 1457552650000 } } ) ;
0 commit comments