Skip to content

CDC: expose pr_* (and future tracker_*) events to live consumers #110

@harshitsinghbhandari

Description

@harshitsinghbhandari

The CDC substrate has been writing PR events to change_log since the original PR table landed, and migration 0004_scm_observer_schema.sql (lines 95-137) added two more: pr_review_thread_added and pr_review_thread_resolved. PR #101 will add pr_session_changed. All of these are durable in change_log and the broadcaster in backend/internal/cdc fans them out internally, but no HTTP/SSE controller subscribes to them today. The only live consumer is the terminal session-state fan-out (backend/internal/daemon/daemon.go:76terminal.NewManager).

Effect: the frontend / ao CLI cannot react to PR state changes in real time even though the substrate is ready. Anything that wants observer output (dashboard, future ambient notifier, status overlays) has to poll the DB.

Acceptance

  • An HTTP route GET /api/v1/events (or a name picked during review) streams CDC events using SSE with Last-Event-ID resume semantics — reuse the offset model documented in backend/internal/cdc/doc.go.
  • The controller subscribes to cdcPipe.Broadcaster and serializes Event (backend/internal/cdc/event.go:37-44) per the existing JSON shape.
  • Initial implementation covers session_*, pr_*, pr_check_recorded, pr_review_thread_added, pr_review_thread_resolved, and pr_session_changed (the latter lands with PR feat: ao session claim-pr + spawn --claim-pr wiring #101).
  • Connection lifecycle is correct: client disconnect unsubscribes from the broadcaster, no goroutine leak.
  • Per-project scoping via query param (?project=...) — events for other projects must not leak.
  • Integration test with httptest + the real CDC pipeline asserts that a row inserted on the DB shows up in the SSE stream.

Why scope this now

Tracker observer (#35) will emit tracker-shaped CDC events when it lands. Designing the SSE shape now (and keeping the typed-event discriminated union out of the transport) saves us a v2 controller later.

Related

  • Depends on cdc package shape — no code change there, just a consumer.
  • Upstream design constraint: backend/internal/cdc/doc.go already documents the "change_log IS the durable, ordered source of truth; clients catch up by reading it from their own offset" contract.

Metadata

Metadata

Assignees

No one assigned

    Labels

    daemonHTTP daemon lanestoragePersistence lane

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions