Skip to content

id(outbox): finished entries are kept forever — the in-memory map, the append-only journal and the deliveries view all grow with the server's entire delivery history #1726

Open

Description

@dezren39

Problem

The envelope outbox (pkgs/id/src/envelope_outbox.rs) never forgets a finished delivery:

  • Outbox.entries (envelope_outbox.rs:121) is a BTreeMap<String, Entry> holding every payload ever queued. The only removal anywhere in the module is the Withdrawn arm of apply (envelope_outbox.rs:322), and withdraw itself refuses any entry that has been attempted or finished — so a Delivered / Refused / GaveUp entry can never leave the map for the life of the process.
  • The on-disk journal has the same shape: commit (envelope_outbox.rs:278) only appends one JSON line per queue/attempt/finish, and open (envelope_outbox.rs:130) only ever truncates a torn final line (set_len, :160). No compaction or pruning exists anywhere in the crate (verified by searching src/ for the outbox file's writers: commit/open are the only ones).
  • The cost is paid on every restart and every directory view: open replays and re-parses every line ever written, and deliveries() (pkgs/id/src/directory_view.rs:432) iterates all entries and clones a DeliveryView for each one the viewer may see. The view's own doc promises only envelopes "still in, or recently left, the outbox" (directory_view.rs:86) — the implementation has no recency bound at all, so a long-lived server's directory view grows linearly with its entire delivery history, forever.

This is a queue, not a journal of record: the directory log is where history lives. Nothing else in the crate reads finished outbox entries except deliveries() and entry() status lookups.

Evidence (verified this run, main 8c6bdc09)

  • Line trace of envelope_outbox.rs (whole file): apply arms are Queued, QueuedArtifact, Attempted, Finished, Withdrawn; only Withdrawn removes, and withdraw() (same file) errors unless attempts == 0 && finish.is_none().
  • grep over pkgs/id/src for compaction/pruning of the outbox (set_len, remove, rewrite): the only hits are the torn-tail truncation in open and the Withdrawn removal above.
  • deliveries() at directory_view.rs:432-448 filters by viewer only — no age, count, or finish-time bound — while its field doc at :86 says "recently left".

Distinct from #1620 (torn-tail acceptance in the same file) and from #1713 (SaveRateLimiter map growth in web/) — this is the outbox store itself, its journal file, and its directory view.

Why it matters

A world server runs for months and flushes its outbox on a timer (world_hub.rs spawn_outbox_flush). Every friend envelope and artifact push adds permanent in-memory entries (including full payload clones), permanent journal lines, restart replay time, and directory-view response size. Growth is slow but strictly unbounded and invisible until the file and the view are large.

Acceptance criteria

  • A retention rule is pinned and documented at Outbox (e.g. finished entries kept for a bounded age or bounded count, still long enough for deliveries() to honestly show "recently left" ones).
  • Finished entries past the bound are dropped from the in-memory map, and the journal is compacted (rewritten without the dropped history) at a safe point, e.g. on open after replay.
  • deliveries() output is bounded by the same rule; a test with an old finished entry and a recent finished entry shows only the recent one.
  • Existing outbox tests keep passing (envelope_outbox + envelope_net flush tests), including torn-tail handling (id(outbox): a parseable torn tail is accepted, then merged into the next record — Outbox::open only drops unterminated final lines that fail to parse #1620's area must not regress: compaction must keep the crash-torn-tail rule working).
  • A restart test: after compaction, reopening the file yields the same due/pending set as before.

Activity

  1. developing-today commented on Oct 28, 2026

    @developing-today
    Contributor
  2. added
    kind/performancePerformance problem or optimization
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/lowNice to have; do when convenient
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Oct 28, 2026
  3. dezren39 commented on Oct 28, 2026

    @dezren39
    MemberAuthor

    Filed this run by new-issue-creator-code-a (lane A). Found via: full line trace of pkgs/id/src/envelope_outbox.rs plus a crate-wide search for any outbox compaction/pruning (none exists outside the torn-tail truncation), and the deliveries() view in pkgs/id/src/directory_view.rs:432 vs its 'recently left' doc at :86. Verified on main 8c6bdc0. Enqueued as a repo-task/v1 triage packet in repo-health-code-pilot.

  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 2, 2026
  5. 39 remaining items

  6. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

    • Agent: fleet monitor (repo-fleet-monitor)
    • Session / ID: task 8101 · repo-fleet-monitor run 2026-11-03 20:12 CST
    • Found via: monitor reconciliation
    • Task: Claim evaporated — task 8101 returned to queued and unclaimed in repo-health-code-pilot after the holding run ended without a terminal verb (checkpoint stage: handed_off). Labels reset to the truth: queue/queued + status/needs-triage. The task cap was also raised this run where it had sat dead-in-queue, so it is claimable again.
    • Expectation: next claimant picks up from the checkpoint stage named above.
  7. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: picked-up
    queue: repo-health-code-pilot
    task: 8101 (triage, worker repo-worker-code, lane 262eb403-3347-4a7c-ba6b-e7bc263ca853)
    by: openchamber-scheduled-lane
    at: 2026-11-04T04:09Z

    Resuming the prior handed-off triage. Fresh issue state is OPEN; PR #4710 (queue/6512-1726-outbox-retention) is still open and directly linked. I’m checking the PR and current queue ownership before deciding whether this is already routed or needs a new packet.

  8. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 4, 2026
  9. dezren39 commented on Nov 4, 2026

    @dezren39
    MemberAuthor

    agent-note:v1
    state: escalated
    queue: repo-health-code-pilot
    task: 8101 (triage, worker repo-worker-code, lane 262eb403-3347-4a7c-ba6b-e7bc263ca853)
    by: openchamber-scheduled-lane
    at: 2026-11-04T04:14Z

    Triage verdict: the original outbox-retention problem remains actionable, and the canonical fix is already in open PR #4710 (queue/6512-1726-outbox-retention); it has one passing check. I will not open a competing PR or modify this PR because it is authored/owned by the repo owner. Fresh review state has one unresolved high Copilot finding: compaction uses fs::rename(src, dst) while the destination exists, which typically fails on Windows and may make Outbox::open() fail. The owner needs to choose/approve the replacement strategy (platform-specific atomic replace versus a documented non-atomic fallback) on the existing PR. No duplicate fix packet was enqueued. This task is blocked/escalated to the owner pending that decision; after the PR finding is addressed, resume the canonical PR and re-check its CI/review state.

  10. added
    queue/blockedQueue or user escalation state
    status/blockedQueue or user escalation state
    user/escalatedQueue or user escalation state
    and removed
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    on Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/performancePerformance problem or optimizationpriority/lowNice to have; do when convenientqueue/blockedQueue or user escalation statesource/creatorFiled by the new-issue-creator jobstatus/blockedQueue or user escalation statetask/triageQueue packet kind: verify, reproduce, and route this itemuser/escalatedQueue or user escalation state

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions