Skip to content

server: bound the in-memory cancel_tree marker-reuse lookup (unbounded journal read per candidate under the global write lock) #375

Description

@luizParreira

The in-memory cancel_tree's idempotent marker append (journaled_marker_for, crates/agent-server/src/journal/store.rs) calls EventRepository::get_events(thread_id) — an unbounded read that clones the thread's entire event vec — once per marker candidate on EVERY cancel, inside the task store's global write lock. On long-lived threads that's an O(N) clone + linear scan on the cancel path, stalling every worker acquire/complete/heartbeat for its duration. A deployment wiring the in-memory task store to a DURABLE event repository turns it into a full per-thread table read from Postgres/SQLite while holding that lock.

Correctness is unaffected (the scan is exact); this is latency/contention on the embedded backend.

Options:

  1. Cache journaled markers in-process: HashMap<AgentTaskId, CommittedEvent> populated on append — O(1), exactly as correct because the in-memory task store dies with the process, and it preserves returning the existing marker event to the caller/notifier.
  2. Bound the read with get_events_in_range from a remembered per-thread floor.

Found during PR #369 review (2026-07-13).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions