You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: add purgeRuns API and retainRuns auto-cleanup option (#109)
* feat: add purgeRuns API and retainRuns auto-cleanup option
- `durably.purgeRuns({ olderThan, limit })` for manual batch deletion of
terminal runs (completed, failed, cancelled) with cascading cleanup of
steps, logs, and labels
- `retainRuns: '30d'` option on createDurably for automatic periodic purge
(runs once per 60s during worker polling, batch size 100)
- Migration v2: adds (status, completed_at) index for efficient purge queries
- Duration parser supports 'd' (days), 'h' (hours), 'm' (minutes)
- 11 new tests covering all purge scenarios
Closes#88
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: simplify purge implementation per review
- Extract cascadeDeleteRuns() helper to eliminate duplication between
deleteRun() and purgeRuns()
- Extract TERMINAL_STATUSES constant to module scope
- Move PURGE_INTERVAL_MS to module scope (was recreated per processOne call)
- Make auto-purge fire-and-forget (void) so it doesn't block job claiming
or lease renewal in the worker polling loop
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: consolidate purge index into migration v1
No backward compatibility needed — merge the (status, completed_at) index
into the single v1 migration instead of keeping a separate v2.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address simplify review findings
- Move TERMINAL_STATUSES after RunStatus type definition (ordering)
- Replace void fire-and-forget with .catch() to prevent unhandled rejection
- Use single Date.now() variable in purge block instead of calling 3 times
- Add comment documenting intentional immediate purge on first cycle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* perf: remove redundant getRuns({ status: 'leased' }) from processOne hot path
The claimNext SQL already contains an activeLeaseGuard subquery that
checks NOT EXISTS for active leases with the same concurrency key.
The JS-side getRuns → filter → excludeConcurrencyKeys flow was
redundant and added a full table scan + JOIN + JSON parse per poll cycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: add purgeRuns and retainRuns to website API reference
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: fix purgeRuns signature — olderThan is required Date, not optional string
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address CodeRabbit review findings
- Move auto-purge after claimNext so it never serializes with job claiming
- Add positive auto-purge test with backdated completed_at
- Clarify retainRuns runs only during worker polling in docs
- Fix purgeRuns(options?) → purgeRuns(options) in API quick reference
- Clarify olderThan matches completedAt, not just "completed" status
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
For automatic cleanup, use the `retainRuns` option (see Quick Start). Cleanup runs during idle worker polling cycles, at most once per minute, in batches of 100.
0 commit comments