@@ -10,8 +10,8 @@ describe('CountItems::CountWorker', () => {
1010 mongoMock . close . mockReset ( ) ;
1111 mongoMock . setup . mockReset ( ) ;
1212 mongoMock . client . isConnected . mockReset ( ) ;
13- mongoMock . _getIsTransient . mockReset ( ) ;
1413 mongoMock . getObjectMDStats . mockReset ( ) ;
14+ mongoMock . getObject . mockReset ( ) ;
1515 } ) ;
1616
1717 const t = [
@@ -180,13 +180,11 @@ describe('CountItems::CountWorker', () => {
180180 sendFn : testSendFn ,
181181 client : mongoMock ,
182182 } ) ;
183+ w . getIsTransient = jest . fn ( ( bucketInfo , cb ) => cb ( ...tc . mock . getIsTransient ) ) ;
183184 mongoMock . setup . mockImplementationOnce ( cb => cb ( ...tc . mock . setup ) ) ;
184185 mongoMock . close . mockImplementationOnce ( cb => cb ( ...tc . mock . close ) ) ;
185186 mongoMock . client . isConnected
186187 . mockImplementationOnce ( ( ) => tc . mock . isConnected ) ;
187- mongoMock . _getIsTransient . mockImplementationOnce (
188- ( _a , _b , cb ) => cb ( ...tc . mock . getIsTransient ) ,
189- ) ;
190188 mongoMock . getObjectMDStats . mockImplementationOnce (
191189 ( _a , _b , _c , _d , cb ) => cb ( ...tc . mock . getObjectMDStats ) ,
192190 ) ;
@@ -213,15 +211,212 @@ describe('CountItems::CountWorker', () => {
213211 _creationDate : Date . now ( ) . toString ( ) ,
214212 website : { indexDocument : 'index.html' } ,
215213 } ;
214+ w . getIsTransient = jest . fn ( ( bucketInfo , cb ) => cb ( null , true ) ) ;
216215 mongoMock . setup . mockImplementationOnce ( cb => cb ( ) ) ;
217216 mongoMock . close . mockImplementationOnce ( cb => cb ( ) ) ;
218217 mongoMock . client . isConnected . mockImplementationOnce ( ( ) => false ) ;
219- mongoMock . _getIsTransient . mockImplementationOnce ( ( _a , _b , cb ) => cb ( null , true ) ) ;
220218 mongoMock . getObjectMDStats . mockImplementationOnce ( ( _a , _b , _c , _d , cb ) => cb ( null , { value : 42 } ) ) ;
221219 w . countItems ( bucketInfo , ( err , results ) => {
222220 expect ( err ) . toBeNull ( ) ;
223221 expect ( results ) . toEqual ( { value : 42 } ) ;
224222 done ( ) ;
225223 } ) ;
226224 } ) ;
225+
226+ describe ( 'CountWorker.getIsTransient method' , ( ) => {
227+ let worker ;
228+ let mockBucketInfo ;
229+
230+ beforeEach ( ( ) => {
231+ worker = new CountWorker ( {
232+ log : new DummyLogger ( ) ,
233+ sendFn : jest . fn ( ) ,
234+ client : mongoMock ,
235+ } ) ;
236+ mockBucketInfo = {
237+ _name : 'test-bucket' ,
238+ _owner : 'any' ,
239+ _ownerDisplayName : 'any' ,
240+ _creationDate : Date . now ( ) . toString ( ) ,
241+ getLocationConstraint : jest . fn ( ( ) => 'test-location' ) ,
242+ } ;
243+ } ) ;
244+
245+ test ( 'should use client.isLocationTransient if available and return true' , done => {
246+ mongoMock . isLocationTransient = jest . fn ( ( loc , lg , cb ) => cb ( null , true ) ) ;
247+ worker . getIsTransient ( mockBucketInfo , ( err , isTransient ) => {
248+ expect ( err ) . toBeNull ( ) ;
249+ expect ( isTransient ) . toBe ( true ) ;
250+ expect ( mongoMock . isLocationTransient ) . toHaveBeenCalledWith ( 'test-location' , worker . log , expect . any ( Function ) ) ;
251+ done ( ) ;
252+ } ) ;
253+ } ) ;
254+
255+ test ( 'should use client.isLocationTransient if available and return false' , done => {
256+ mongoMock . isLocationTransient = jest . fn ( ( loc , lg , cb ) => cb ( null , false ) ) ;
257+ worker . getIsTransient ( mockBucketInfo , ( err , isTransient ) => {
258+ expect ( err ) . toBeNull ( ) ;
259+ expect ( isTransient ) . toBe ( false ) ;
260+ done ( ) ;
261+ } ) ;
262+ } ) ;
263+
264+ test ( 'should propagate error from client.isLocationTransient' , done => {
265+ const testError = new Error ( 'client.isLocationTransient error' ) ;
266+ mongoMock . isLocationTransient = jest . fn ( ( loc , lg , cb ) => cb ( testError ) ) ;
267+ worker . getIsTransient ( mockBucketInfo , ( err , isTransient ) => {
268+ expect ( err ) . toBe ( testError ) ;
269+ expect ( isTransient ) . toBeUndefined ( ) ;
270+ done ( ) ;
271+ } ) ;
272+ } ) ;
273+
274+ describe ( 'when client.isLocationTransient is not available (fallback to pensieve)' , ( ) => {
275+ beforeEach ( ( ) => {
276+ mongoMock . isLocationTransient = undefined ;
277+ } ) ;
278+
279+ test ( 'should fallback to pensieveLocationIsTransient and return true' , done => {
280+ mongoMock . getObject
281+ . mockImplementationOnce ( ( bucket , key , params , log , cb ) => cb ( null , 'v1' ) ) // 1st call
282+ . mockImplementationOnce ( ( bucket , key , params , log , cb ) => cb ( null , { // 2nd call
283+ locations : { 'test-location' : { isTransient : true } } ,
284+ } ) ) ;
285+ worker . getIsTransient ( mockBucketInfo , ( err , isTransient ) => {
286+ expect ( err ) . toBeNull ( ) ;
287+ expect ( isTransient ) . toBe ( true ) ;
288+ expect ( mongoMock . getObject ) . toHaveBeenCalledTimes ( 2 ) ;
289+ done ( ) ;
290+ } ) ;
291+ } ) ;
292+
293+ test ( 'should fallback to pensieveLocationIsTransient and return false' , done => {
294+ mongoMock . getObject
295+ . mockImplementationOnce ( ( bucket , key , params , log , cb ) => cb ( null , 'v1' ) )
296+ . mockImplementationOnce ( ( bucket , key , params , log , cb ) => cb ( null , {
297+ locations : { 'test-location' : { isTransient : false } } ,
298+ } ) ) ;
299+ worker . getIsTransient ( mockBucketInfo , ( err , isTransient ) => {
300+ expect ( err ) . toBeNull ( ) ;
301+ expect ( isTransient ) . toBe ( false ) ;
302+ done ( ) ;
303+ } ) ;
304+ } ) ;
305+
306+ test ( 'should propagate error from pensieveLocationIsTransient (e.g., first getObject fails)' , done => {
307+ const pensieveError = new Error ( 'Pensieve getObject error' ) ;
308+ mongoMock . getObject . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( pensieveError ) ) ;
309+ worker . getIsTransient ( mockBucketInfo , ( err , isTransient ) => {
310+ expect ( err ) . toBe ( pensieveError ) ;
311+ expect ( isTransient ) . toBeUndefined ( ) ;
312+ done ( ) ;
313+ } ) ;
314+ } ) ;
315+ } ) ;
316+ } ) ;
317+
318+ describe ( 'CountWorker.pensieveLocationIsTransient method' , ( ) => {
319+ let worker ;
320+ const PENSIEVE_BUCKET_NAME = 'PENSIEVE' ;
321+
322+ beforeEach ( ( ) => {
323+ worker = new CountWorker ( {
324+ log : new DummyLogger ( ) ,
325+ sendFn : jest . fn ( ) ,
326+ client : mongoMock ,
327+ } ) ;
328+ } ) ;
329+
330+ test ( 'should return true if location is transient in Pensieve config' , done => {
331+ mongoMock . getObject
332+ . mockImplementationOnce ( ( bucket , key , params , log , cb ) => {
333+ expect ( bucket ) . toBe ( PENSIEVE_BUCKET_NAME ) ;
334+ expect ( key ) . toBe ( 'configuration/overlay-version' ) ;
335+ cb ( null , 'v-p-1' ) ;
336+ } )
337+ . mockImplementationOnce ( ( bucket , key , params , log , cb ) => {
338+ expect ( bucket ) . toBe ( PENSIEVE_BUCKET_NAME ) ;
339+ expect ( key ) . toBe ( 'configuration/overlay/v-p-1' ) ;
340+ cb ( null , { locations : { 'loc-A' : { isTransient : true } } } ) ;
341+ } ) ;
342+
343+ worker . pensieveLocationIsTransient ( 'loc-A' , ( err , isTransient ) => {
344+ expect ( err ) . toBeNull ( ) ;
345+ expect ( isTransient ) . toBe ( true ) ;
346+ done ( ) ;
347+ } ) ;
348+ } ) ;
349+
350+ test ( 'should return false if location is not transient in Pensieve config' , done => {
351+ mongoMock . getObject
352+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , 'v-p-2' ) )
353+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , { locations : { 'loc-B' : { isTransient : false } } } ) ) ;
354+
355+ worker . pensieveLocationIsTransient ( 'loc-B' , ( err , isTransient ) => {
356+ expect ( err ) . toBeNull ( ) ;
357+ expect ( isTransient ) . toBe ( false ) ;
358+ done ( ) ;
359+ } ) ;
360+ } ) ;
361+
362+ test ( 'should return false if isTransient property is missing' , done => {
363+ mongoMock . getObject
364+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , 'v-p-3' ) )
365+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , { locations : { 'loc-C' : { } } } ) ) ;
366+
367+ worker . pensieveLocationIsTransient ( 'loc-C' , ( err , isTransient ) => {
368+ expect ( err ) . toBeNull ( ) ;
369+ expect ( isTransient ) . toBe ( false ) ;
370+ done ( ) ;
371+ } ) ;
372+ } ) ;
373+
374+ test ( 'should propagate error from first getObject call' , done => {
375+ const testError = new Error ( 'getObject overlay-version failed' ) ;
376+ mongoMock . getObject . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( testError ) ) ;
377+
378+ worker . pensieveLocationIsTransient ( 'loc-D' , ( err , isTransient ) => {
379+ expect ( err ) . toBe ( testError ) ;
380+ expect ( isTransient ) . toBeUndefined ( ) ;
381+ done ( ) ;
382+ } ) ;
383+ } ) ;
384+
385+ test ( 'should propagate error from second getObject call' , done => {
386+ const testError = new Error ( 'getObject overlay-config failed' ) ;
387+ mongoMock . getObject
388+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , 'v-p-4' ) )
389+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( testError ) ) ;
390+
391+ worker . pensieveLocationIsTransient ( 'loc-E' , ( err , isTransient ) => {
392+ expect ( err ) . toBe ( testError ) ;
393+ expect ( isTransient ) . toBeUndefined ( ) ;
394+ done ( ) ;
395+ } ) ;
396+ } ) ;
397+
398+ test ( 'should handle case when locConstraint is not in locations' , done => {
399+ mongoMock . getObject
400+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , 'v-p-5' ) )
401+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , { locations : { 'other-loc' : { isTransient : true } } } ) ) ;
402+
403+ worker . pensieveLocationIsTransient ( 'loc-F-not-in-response' , ( err , isTransient ) => {
404+ expect ( err ) . toBeNull ( ) ;
405+ expect ( isTransient ) . toBe ( false ) ;
406+ done ( ) ;
407+ } ) ;
408+ } ) ;
409+
410+ test ( 'should handle case where no location is provided' , done => {
411+ mongoMock . getObject
412+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , 'v-p-6' ) )
413+ . mockImplementationOnce ( ( b , k , p , l , cb ) => cb ( null , { locations : { } } ) ) ;
414+
415+ worker . pensieveLocationIsTransient ( 'loc-G' , ( err , isTransient ) => {
416+ expect ( err ) . toBeNull ( ) ;
417+ expect ( isTransient ) . toBe ( false ) ;
418+ done ( ) ;
419+ } ) ;
420+ } ) ;
421+ } ) ;
227422} ) ;
0 commit comments