@@ -331,28 +331,50 @@ describe('deleted workspace storage sweep', () => {
331331 expect ( checkpointPayload ) . toHaveBeenCalledWith ( { family : 1 , pageToken : null } )
332332 } )
333333
334- it ( 'walks the family from the start when its saved position no longer lists' , async ( ) => {
335- vi . mocked ( listStorageKeyPage ) . mockRejectedValueOnce (
336- new Error ( 'The continuation token is invalid' )
337- )
334+ it ( 'retries a saved position that failed to list once instead of walking from the start' , async ( ) => {
335+ let payload : Record < string , unknown > = {
336+ version : 1 ,
337+ workspaceId : 'wsdoomed1' ,
338+ pageToken : 'workspace/wsdoomed1/a.txt' ,
339+ }
340+ const checkpointPayload = vi . fn ( async ( patch : Record < string , unknown > ) => {
341+ payload = { ...payload , ...patch }
342+ } )
343+ vi . mocked ( listStorageKeyPage ) . mockRejectedValueOnce ( new Error ( 'Service unavailable' ) )
338344
339- await expect (
340- sweep ( { version : 1 , workspaceId : 'wsdoomed1' , pageToken : 'expired-token' } , outboxContext ( ) )
341- ) . resolves . toBe ( undefined )
345+ await expect ( sweep ( payload , outboxContext ( { checkpointPayload } ) ) ) . rejects . toThrow (
346+ 'Service unavailable'
347+ )
348+ for ( const key of DOOMED_KEYS ) expect ( await exists ( key ) ) . toBe ( true )
349+ expect ( payload ) . toMatchObject ( { pageToken : 'workspace/wsdoomed1/a.txt' , tokenFailures : 1 } )
342350
343- for ( const key of DOOMED_KEYS ) expect ( await exists ( key ) ) . toBe ( false )
351+ await expect ( sweep ( payload , outboxContext ( { checkpointPayload } ) ) ) . resolves . toBe ( undefined )
352+ expect ( await exists ( 'workspace/wsdoomed1/a.txt' ) ) . toBe ( true )
353+ expect ( await exists ( 'workspace/wsdoomed1/nested/b.txt' ) ) . toBe ( false )
354+ expect ( payload ) . toMatchObject ( { tokenFailures : 0 } )
344355 } )
345356
346- it ( 'walks the family from the start when its saved position is not a key under the prefix' , async ( ) => {
347- await expect (
348- sweep (
349- { version : 1 , workspaceId : 'wsdoomed1' , pageToken : 'zz-other-provider' } ,
350- outboxContext ( )
351- )
352- ) . resolves . toBe ( undefined )
357+ it . each ( [
358+ { name : 'no longer lists' , pageToken : 'expired-token' , rejects : true } ,
359+ { name : 'is not a key under the prefix' , pageToken : 'zz-other-provider' , rejects : false } ,
360+ ] ) (
361+ 'walks the family from the start once its saved position $name on a second attempt' ,
362+ async ( { pageToken, rejects } ) => {
363+ let payload : Record < string , unknown > = { version : 1 , workspaceId : 'wsdoomed1' , pageToken }
364+ const checkpointPayload = vi . fn ( async ( patch : Record < string , unknown > ) => {
365+ payload = { ...payload , ...patch }
366+ } )
367+ const invalid = new Error ( 'The continuation token is invalid' )
368+ if ( rejects )
369+ vi . mocked ( listStorageKeyPage ) . mockRejectedValueOnce ( invalid ) . mockRejectedValueOnce ( invalid )
353370
354- for ( const key of DOOMED_KEYS ) expect ( await exists ( key ) ) . toBe ( false )
355- } )
371+ await expect ( sweep ( payload , outboxContext ( { checkpointPayload } ) ) ) . rejects . toThrow ( )
372+ for ( const key of DOOMED_KEYS ) expect ( await exists ( key ) ) . toBe ( true )
373+
374+ await expect ( sweep ( payload , outboxContext ( { checkpointPayload } ) ) ) . resolves . toBe ( undefined )
375+ for ( const key of DOOMED_KEYS ) expect ( await exists ( key ) ) . toBe ( false )
376+ }
377+ )
356378
357379 it ( 'spends an attempt when a restart from a rejected position only walks kept objects' , async ( ) => {
358380 const keptKeys = await putKept ( 500 )
@@ -362,7 +384,7 @@ describe('deleted workspace storage sweep', () => {
362384 const checkpointPayload = vi . fn ( async ( ) => { } )
363385
364386 const outcome = await sweep (
365- { version : 1 , workspaceId : 'wsdoomed1' , pageToken : 'expired-token' } ,
387+ { version : 1 , workspaceId : 'wsdoomed1' , pageToken : 'expired-token' , tokenFailures : 1 } ,
366388 deadlineAfter ( 2 , { checkpointPayload } )
367389 )
368390
@@ -404,6 +426,8 @@ describe('deleted workspace storage sweep', () => {
404426 { version : 1 , workspaceId : 'wsdoomed1' , pageToken : 'x' . repeat ( 4097 ) } ,
405427 { version : 1 , workspaceId : 'wsdoomed1' , resumes : - 1 } ,
406428 { version : 1 , workspaceId : 'wsdoomed1' , resumes : '1' } ,
429+ { version : 1 , workspaceId : 'wsdoomed1' , tokenFailures : 2 } ,
430+ { version : 1 , workspaceId : 'wsdoomed1' , tokenFailures : '1' } ,
407431 ] ) ( 'rejects an unbounded or malformed payload %o' , async ( payload ) => {
408432 await expect ( sweep ( payload , outboxContext ( ) ) ) . rejects . toThrow ( )
409433 for ( const key of DOOMED_KEYS ) expect ( await exists ( key ) ) . toBe ( true )
0 commit comments