( scope: WorkspaceFileScope )
| 99 | } |
| 100 | |
| 101 | async function cleanupWorkspaceFileStorage( |
| 102 | scope: WorkspaceFileScope |
| 103 | ): Promise<{ filesDeleted: number; filesFailed: number }> { |
| 104 | const stats = { filesDeleted: 0, filesFailed: 0 } |
| 105 | if (!isUsingCloudStorage()) return stats |
| 106 | |
| 107 | const keysByContext = new Map<StorageContext, string[]>() |
| 108 | for (const r of scope.legacyRows) { |
| 109 | const bucket = keysByContext.get('workspace') |
| 110 | if (bucket) bucket.push(r.key) |
| 111 | else keysByContext.set('workspace', [r.key]) |
| 112 | } |
| 113 | for (const r of scope.multiContextRows) { |
| 114 | const bucket = keysByContext.get(r.context) |
| 115 | if (bucket) bucket.push(r.key) |
| 116 | else keysByContext.set(r.context, [r.key]) |
| 117 | } |
| 118 | |
| 119 | for (const [context, keys] of keysByContext) { |
| 120 | const result = await StorageService.deleteFiles(keys, context) |
| 121 | stats.filesDeleted += result.deleted |
| 122 | stats.filesFailed += result.failed.length |
| 123 | for (const { key, error } of result.failed) { |
| 124 | logger.error(`Failed to delete storage file ${key} (context: ${context}):`, { error }) |
| 125 | } |
| 126 | } |
| 127 | |
| 128 | return stats |
| 129 | } |
| 130 | |
| 131 | /** |
| 132 | * Tables cleaned by the generic workspace-scoped batched DELETE. Tables whose |
no test coverage detected