@@ -368,21 +368,46 @@ async function archiveTableChildren(context: CascadeChildrenContext): Promise<nu
368368/**
369369 * Restores the tables this cascade archived, through the canonical table restore so a table
370370 * whose name was taken while it was gone is renamed instead of tripping the active-name
371- * unique index.
371+ * unique index. If a later member fails, the successful prefix is re-archived under the
372+ * original timestamp so no active referrer can point at a still-archived cohort target.
372373 */
373374async function restoreTableChildren ( context : CascadeChildrenContext ) : Promise < number > {
374- const { restoreTable } = await import ( '@/lib/table/service' )
375+ const { deleteTables , restoreTable } = await import ( '@/lib/table/service' )
375376 const ids = await selectChildIds ( FOLDER_RESOURCES . table , context , 'archived' )
376377 const restoringFolderIds = new Set ( context . folderIds )
377378 const restoringTableIds = new Set ( ids )
378-
379- for ( const id of ids ) {
380- // restoreFolder fires one folder-level live-list notify for the whole subtree.
381- await restoreTable ( id , `folder-cascade-${ context . folderIds [ 0 ] } ` , {
382- restoringFolderIds,
383- restoringTableIds,
384- skipNotify : true ,
385- } )
379+ const restoredIds : string [ ] = [ ]
380+
381+ try {
382+ for ( const id of ids ) {
383+ // restoreFolder fires one folder-level live-list notify for the whole subtree.
384+ await restoreTable ( id , `folder-cascade-${ context . folderIds [ 0 ] } ` , {
385+ restoringFolderIds,
386+ restoringTableIds,
387+ skipNotify : true ,
388+ } )
389+ restoredIds . push ( id )
390+ }
391+ } catch ( error ) {
392+ const rollback = await deleteTables (
393+ restoredIds ,
394+ `folder-restore-rollback-${ context . folderIds [ 0 ] } ` ,
395+ {
396+ expectedWorkspaceId : context . workspaceId ,
397+ archivedAt : context . timestamp ,
398+ skipNotify : true ,
399+ archiveAsCohort : true ,
400+ }
401+ )
402+ if ( rollback . terminalError ) throw rollback . terminalError
403+ if (
404+ rollback . failed . length > 0 ||
405+ rollback . notFound . length > 0 ||
406+ rollback . archived . length !== restoredIds . length
407+ ) {
408+ throw new OrchestrationError ( 'internal' , 'Failed to roll back the table restore cohort' )
409+ }
410+ throw error
386411 }
387412
388413 return ids . length
0 commit comments