Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit 69b6ba5

Browse files
committed
feat: add progress logging to checkpoint culling
- Log number of tasks being scanned - Log how many tasks have checkpoints - Log how many need culling (older than 30 days) - Log progress every 100 deletions during large culls
1 parent 0540d27 commit 69b6ba5

1 file changed

Lines changed: 19 additions & 2 deletions

File tree

src/utils/task-history-retention.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -485,15 +485,22 @@ export async function purgeOldCheckpoints(
485485
const totalTasks = taskDirs.length
486486

487487
if (totalTasks === 0) {
488+
log?.(`[Checkpoints] No tasks found`)
488489
return { culledCount: 0, cutoff }
489490
}
490491

492+
log?.(`[Checkpoints] Scanning ${totalTasks} tasks for old checkpoints...`)
493+
491494
// Phase 1: Read metadata for all tasks with checkpoints
492495
const metadataLimit = pLimit(METADATA_READ_CONCURRENCY)
493496
const metadataResults = await Promise.all(
494497
taskDirs.map((d) => metadataLimit(() => readCheckpointTaskMetadata(d.name, tasksDir))),
495498
)
496499

500+
// Count tasks that have checkpoints
501+
const tasksWithCheckpoints = metadataResults.filter((m) => m !== null).length
502+
log?.(`[Checkpoints] Found ${tasksWithCheckpoints} tasks with checkpoints`)
503+
497504
// Phase 2: Filter tasks with checkpoints that need culling
498505
const tasksToCull: CheckpointTaskMetadata[] = []
499506

@@ -507,10 +514,12 @@ export async function purgeOldCheckpoints(
507514
}
508515

509516
if (tasksToCull.length === 0) {
510-
log?.(`[Checkpoints] No checkpoints met cull criteria`)
517+
log?.(`[Checkpoints] No checkpoints older than 30 days`)
511518
return { culledCount: 0, cutoff }
512519
}
513520

521+
log?.(`[Checkpoints] ${tasksToCull.length} tasks have checkpoints older than 30 days`)
522+
514523
// Dry run mode
515524
if (dryRun) {
516525
for (const metadata of tasksToCull) {
@@ -523,14 +532,22 @@ export async function purgeOldCheckpoints(
523532
}
524533

525534
// Phase 3: Delete checkpoints directories in parallel
535+
log?.(`[Checkpoints] Deleting checkpoints from ${tasksToCull.length} tasks...`)
526536
const deleteLimit = pLimit(DELETION_CONCURRENCY)
537+
let deletedCount = 0
538+
527539
const deleteResults = await Promise.all(
528540
tasksToCull.map((metadata) =>
529541
deleteLimit(async (): Promise<boolean> => {
530542
try {
531543
await fs.rm(metadata.checkpointsDir, { recursive: true, force: true })
532544
const stillExists = await pathExists(metadata.checkpointsDir)
533545
if (!stillExists) {
546+
deletedCount++
547+
// Log progress every 100 deletions
548+
if (deletedCount % 100 === 0) {
549+
log?.(`[Checkpoints] Progress: ${deletedCount}/${tasksToCull.length} deleted`)
550+
}
534551
return true
535552
}
536553
} catch {
@@ -544,7 +561,7 @@ export async function purgeOldCheckpoints(
544561
const culled = deleteResults.filter(Boolean).length
545562

546563
if (culled > 0) {
547-
log?.(`[Checkpoints] Culled checkpoints from ${culled} task(s); cutoff=${new Date(cutoff).toISOString()}`)
564+
log?.(`[Checkpoints] Culled checkpoints from ${culled} task(s)`)
548565
}
549566

550567
return { culledCount: culled, cutoff }

0 commit comments

Comments
 (0)