( jobType: CleanupJobType, onChunk: (payload: CleanupJobPayload) => Promise<void> )
| 205 | } |
| 206 | |
| 207 | async function forEachCleanupChunk( |
| 208 | jobType: CleanupJobType, |
| 209 | onChunk: (payload: CleanupJobPayload) => Promise<void> |
| 210 | ): Promise<{ chunkCount: number; workspaceCount: number }> { |
| 211 | const config = CLEANUP_CONFIG[jobType] |
| 212 | const chunkCountByPlan: Partial<Record<NonEnterprisePlan, number>> = {} |
| 213 | const housekeepingPlan = GLOBAL_HOUSEKEEPING_PLAN[jobType] |
| 214 | let housekeepingAssigned = false |
| 215 | let workspaceCount = 0 |
| 216 | let chunkCount = 0 |
| 217 | let afterId: string | null = null |
| 218 | |
| 219 | const emitChunk = async (payload: CleanupJobPayload) => { |
| 220 | if (payload.plan === housekeepingPlan && !housekeepingAssigned) { |
| 221 | payload.runGlobalHousekeeping = true |
| 222 | housekeepingAssigned = true |
| 223 | } |
| 224 | chunkCount++ |
| 225 | await onChunk(payload) |
| 226 | } |
| 227 | |
| 228 | while (true) { |
| 229 | const rows = await listActiveWorkspaceCleanupScopeRowsPage(afterId) |
| 230 | if (rows.length === 0) break |
| 231 | |
| 232 | afterId = rows[rows.length - 1].id |
| 233 | const planByWorkspaceId = await resolvePlanTypesByWorkspaceId(rows) |
| 234 | |
| 235 | for (const plan of NON_ENTERPRISE_PLANS) { |
| 236 | const retentionHours = config.defaults[plan] |
| 237 | if (retentionHours === null) continue |
| 238 | |
| 239 | const workspaceIds = rows |
| 240 | .filter((row) => planByWorkspaceId.get(row.id) === plan) |
| 241 | .map((row) => row.id) |
| 242 | if (workspaceIds.length === 0) continue |
| 243 | |
| 244 | workspaceCount += workspaceIds.length |
| 245 | const planChunks = chunkArray(workspaceIds, WORKSPACES_PER_CLEANUP_CHUNK) |
| 246 | for (const ws of planChunks) { |
| 247 | const chunkNumber = (chunkCountByPlan[plan] ?? 0) + 1 |
| 248 | chunkCountByPlan[plan] = chunkNumber |
| 249 | await emitChunk({ |
| 250 | plan, |
| 251 | workspaceIds: ws, |
| 252 | retentionHours, |
| 253 | label: `${plan}/${chunkNumber}`, |
| 254 | }) |
| 255 | } |
| 256 | } |
| 257 | |
| 258 | for (const row of rows) { |
| 259 | if (planByWorkspaceId.get(row.id) !== 'enterprise') continue |
| 260 | const hours = resolveEffectiveRetentionHours({ |
| 261 | orgSettings: row.organizationSettings, |
| 262 | workspaceId: row.id, |
| 263 | key: config.key, |
| 264 | }) |
no test coverage detected