1
1
import { MySegmentsUpdateWorker } from '../MySegmentsUpdateWorker' ;
2
- import { MySegmentsCacheInMemory } from '../../../../storages/inMemory/MySegmentsCacheInMemory' ;
3
2
import { loggerMock } from '../../../../logger/__tests__/sdkLogger.mock' ;
4
3
import { syncTaskFactory } from '../../../syncTask' ;
5
4
import { Backoff } from '../../../../utils/Backoff' ;
6
5
import { telemetryTrackerFactory } from '../../../../trackers/telemetryTracker' ;
7
6
import { MEMBERSHIPS_LS_UPDATE , MEMBERSHIPS_MS_UPDATE } from '../../constants' ;
8
7
9
- function createStorage ( ) {
8
+ function storageMock ( ) {
10
9
return {
11
- segments : new MySegmentsCacheInMemory ( ) ,
12
- largeSegments : new MySegmentsCacheInMemory ( ) ,
10
+ segments : {
11
+ _changeNumber : - 1 ,
12
+ getChangeNumber ( ) {
13
+ return this . _changeNumber ;
14
+ }
15
+ } ,
16
+ largeSegments : {
17
+ _changeNumber : - 1 ,
18
+ getChangeNumber ( ) {
19
+ return this . _changeNumber ;
20
+ }
21
+ } ,
13
22
} ;
14
23
}
15
24
@@ -55,7 +64,7 @@ describe('MySegmentsUpdateWorker', () => {
55
64
// setup
56
65
const mySegmentsSyncTask = mySegmentsSyncTaskMock ( ) ;
57
66
Backoff . __TEST__BASE_MILLIS = 1 ; // retry immediately
58
- const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , createStorage ( ) , mySegmentsSyncTask as any , telemetryTracker ) ;
67
+ const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , storageMock ( ) as any , mySegmentsSyncTask as any , telemetryTracker ) ;
59
68
60
69
// assert calling `mySegmentsSyncTask.execute` if `isExecuting` is false
61
70
expect ( mySegmentsSyncTask . isExecuting ( ) ) . toBe ( false ) ;
@@ -123,7 +132,7 @@ describe('MySegmentsUpdateWorker', () => {
123
132
// setup
124
133
Backoff . __TEST__BASE_MILLIS = 50 ;
125
134
const mySegmentsSyncTask = mySegmentsSyncTaskMock ( [ false , false , false ] ) ; // fetch fail
126
- const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , createStorage ( ) , mySegmentsSyncTask as any , telemetryTracker ) ;
135
+ const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , storageMock ( ) as any , mySegmentsSyncTask as any , telemetryTracker ) ;
127
136
128
137
// while fetch fails, should retry with backoff
129
138
mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_MS_UPDATE , cn : 100 } ) ;
@@ -138,7 +147,7 @@ describe('MySegmentsUpdateWorker', () => {
138
147
test ( 'stop' , async ( ) => {
139
148
// setup
140
149
const mySegmentsSyncTask = mySegmentsSyncTaskMock ( [ false ] ) ;
141
- const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , createStorage ( ) , mySegmentsSyncTask as any , telemetryTracker ) ;
150
+ const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , storageMock ( ) as any , mySegmentsSyncTask as any , telemetryTracker ) ;
142
151
143
152
mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 100 } ) ;
144
153
mySegmentUpdateWorker . stop ( ) ;
@@ -153,36 +162,53 @@ describe('MySegmentsUpdateWorker', () => {
153
162
expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 1 ) ;
154
163
} ) ;
155
164
156
- test ( 'put with delay' , async ( ) => {
165
+ test ( 'put, with delay and storage change number ' , async ( ) => {
157
166
// setup
167
+ Backoff . __TEST__BASE_MILLIS = 1 ; // retry immediately
158
168
const mySegmentsSyncTask = mySegmentsSyncTaskMock ( ) ;
159
- const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , createStorage ( ) , mySegmentsSyncTask as any , telemetryTracker ) ;
169
+ const storage = storageMock ( ) ;
170
+ const mySegmentUpdateWorker = MySegmentsUpdateWorker ( loggerMock , storage as any , mySegmentsSyncTask as any , telemetryTracker ) ;
160
171
161
- // If a delayed fetch request is queued while another fetch request is waiting, it is discarded
172
+ // notification with delay
162
173
mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 100 } , undefined , 50 ) ;
163
- mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 150 } , undefined , 100 ) ;
174
+
175
+ // If a notification is queued while a fetch request is waiting, the notification is discarded but its change number is used to update the target change number
176
+ mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_MS_UPDATE , cn : 150 } , undefined , 100 ) ; // target for segments storage is 150
177
+ mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 120 } ) ; // target for large segments storage is 120
164
178
165
179
await new Promise ( res => setTimeout ( res , 60 ) ) ;
166
180
expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 1 ) ;
167
181
expect ( mySegmentsSyncTask . execute ) . toHaveBeenLastCalledWith ( undefined , true , undefined ) ;
182
+ storage . largeSegments . _changeNumber = 100 ; // change number update but not the expected one
168
183
mySegmentsSyncTask . __resolveMySegmentsUpdaterCall ( ) ; // fetch success
169
184
170
185
await new Promise ( res => setTimeout ( res , 60 ) ) ;
171
- expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 1 ) ;
186
+ expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 2 ) ; // fetch retry due to target change number mismatch
187
+
188
+ storage . largeSegments . _changeNumber = 120 ;
189
+ mySegmentsSyncTask . __resolveMySegmentsUpdaterCall ( ) ;
190
+ await new Promise ( res => setTimeout ( res , 60 ) ) ;
191
+ expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 2 ) ; // no more fetches since target change number is reached
172
192
173
193
// If an event with segmentData (i.e., an instant update) is queued while a delayed fetch request is waiting, the instant update is discarded
174
194
mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 200 } , undefined , 50 ) ;
175
195
await new Promise ( res => setTimeout ( res , 10 ) ) ;
176
196
mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 230 } , { added : [ 'some_segment' ] , removed : [ ] } ) ;
177
197
178
198
await new Promise ( res => setTimeout ( res , 60 ) ) ;
179
- expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 2 ) ;
199
+ expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 3 ) ;
180
200
expect ( mySegmentsSyncTask . execute ) . toHaveBeenLastCalledWith ( undefined , true , undefined ) ;
181
201
mySegmentsSyncTask . __resolveMySegmentsUpdaterCall ( ) ; // fetch success
182
202
await new Promise ( res => setTimeout ( res ) ) ;
183
203
184
204
mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_LS_UPDATE , cn : 250 } , { added : [ 'some_segment' ] , removed : [ ] } ) ;
185
- expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 3 ) ;
205
+ expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 4 ) ;
186
206
expect ( mySegmentsSyncTask . execute ) . toHaveBeenLastCalledWith ( { type : MEMBERSHIPS_LS_UPDATE , cn : 250 , added : [ 'some_segment' ] , removed : [ ] } , true , undefined ) ;
207
+
208
+ // Stop should clear the delayed fetch request
209
+ mySegmentUpdateWorker . put ( { type : MEMBERSHIPS_MS_UPDATE , cn : 300 } , undefined , 10 ) ;
210
+ mySegmentUpdateWorker . stop ( ) ;
211
+ await new Promise ( res => setTimeout ( res , 20 ) ) ;
212
+ expect ( mySegmentsSyncTask . execute ) . toBeCalledTimes ( 4 ) ;
187
213
} ) ;
188
214
} ) ;
0 commit comments