Skip to content

fix(core): bound consumed job history - #46087

Open
Hona wants to merge 1 commit into
anomalyco:v2from
Hona:job-retention
Open

fix(core): bound consumed job history#46087
Hona wants to merge 1 commit into
anomalyco:v2from
Hona:job-retention

Conversation

@Hona

@Hona Hona commented Aug 29, 2026

Copy link
Copy Markdown
Member

Summary

Bound the process-global Job registry's consumed terminal history to the newest 100 jobs and 16 MiB of UTF-8 output/error text, evicting whole entries in completion order. Only packages/core/src/job.ts changes.

Completed foreground shell and subagent jobs currently remain in the registry for the server's lifetime. Closing a job's scope does not remove its Info and Deferred-held result snapshots. Notification acknowledgment currently removes only the durable KV marker.

Retention Policy

  • Running jobs, unclaimed results, and unacknowledged completion notifications remain protected.
  • block() claims a foreground result; registered waiters already hold their generation's Deferred and still receive the full result after eviction.
  • A successful terminal wait() claims non-recoverable output. Recoverable wait() alone does not: the existing wait -> background handoff remains supported, including immediately failed work.
  • Background registration resets the foreground claim and protects notification ownership. Acknowledgment releases that protection by notification ID, not just job ID.
  • Evicted get / wait / block calls use their existing missing-result shapes. Oversized results still reach the first caller in full; they are not truncated to fit history.
  • No TTL or grace timer, new configuration surface, durable schema, or public API change. Existing ID reuse and shutdown/recovery semantics remain intact.

The byte budget covers output and error strings, not arbitrary metadata or total heap size. Metadata is bounded only by the history entry count. Running work, unclaimed handoffs, pending notifications, and caller-held results can exceed these limits; this is not a hard cap on total Job or server memory.

Before / After

Two checkpoints comparing Job heap before and after 1000 claimed results, unfixed versus fixed

Version Before job 1 After job 1,000 + GC Results still retained/readable
Unfixed 12.54 MiB 1,016.32 MiB 1,000
Fixed 12.56 MiB 30.36 MiB 16

One graph, two measured checkpoints per version, with the median of five fresh processes on Windows x64 / Bun 1.4.0. The fixture uses the production Job service and real in-memory SQLite KV. Each job produces a distinct, materialized synthetic 1-MiB result string and has its foreground result claimed through block(). This is not 1 MiB of normal shell stdout; default shell previews are smaller.

The Job service remains alive during measurement. Both versions use the same warm-up and eight explicit full-GC rounds with 100-ms event-loop gaps. All unrelated weak controls are collected, retained metadata sentinels match readable history counts, and retained results remain complete. A separate 1,000-job run with 50-KiB results retains exactly 100 entries, exercising the count limit rather than the text-byte limit.

Metric: bun:jsc.heapStats().heapSize, including external memory, not RSS or a production-server savings forecast. A preliminary batch run alongside integration tests failed a reachability control; the final plotted batch ran separately and passed all controls. The graph and validation probes are local artifacts, not committed files.

Verification

  • Local lifecycle probe: 20 retention checks fail on the original implementation while 10 controls pass; all 30 cases pass with the fix on Windows Bun 1.4.0, Windows Bun 1.3.14, and Linux x64 Bun 1.4.0 under WSL.
  • Coverage includes count/UTF-8 byte pressure, completion order, full oversized-result delivery, pending notifications, late background registration, generation reuse, cancellation, missing-result shapes, and unchanged scope/recovery behavior.
  • Existing Job, shell, subagent, and restart suites: Windows 101 passed / 44 platform skips; Linux 110 passed / 36 platform skips.
  • Repository-pinned Bun 1.3.14: existing Job, subagent, and restart suites passed (57 tests).
  • Core bun typecheck, targeted Oxlint, Effect AST rules, Prettier, and git diff --check passed. The pre-push workspace typecheck passed all 33 tasks.

No test files or changesets are included. The running server was not patched or restarted for validation.

Retain at most 100 claimed terminal jobs and 16 MiB of output/error text in completion order. Preserve unclaimed handoffs, running work, pending notification ownership, and full results for registered waiters.
Copilot AI lite review requested due to automatic review settings August 29, 2026 04:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants