Skip to content

feat(ingest): board webhook arm — fan-out sink + hydrating ingest queue (RIG-2883) - #706

Open
rigel-mintaka wants to merge 1 commit into
mainfrom
compass-forge/rig-2883-t1-board-arm
Open

feat(ingest): board webhook arm — fan-out sink + hydrating ingest queue (RIG-2883)#706
rigel-mintaka wants to merge 1 commit into
mainfrom
compass-forge/rig-2883-t1-board-arm

Conversation

@rigel-mintaka

Copy link
Copy Markdown
Contributor

T1 of the board-ingestion forge poll→webhook cutover: BoardWebhookArm, a second consumer behind the one GitHub ingress.

Enqueue satisfies server.ForgeEventSink's non-blocking contract — it filters to board-relevant issue events (Change ∈ {OPENED, STATE, UPDATE} ∧ Kind == ISSUE; PR-kind and COMMENT-change dropped) then channel try-sends; a full queue DROPS the event with an exported expvar drop metric + Warn (the T3 reconciler heals it).

Run drains until ctx cancel (returns nil, driver.go:95-99 idiom). Each drain COALESCES per NORMALIZED (repo, number) coordinate first, so an N-event edit storm on one issue costs ONE hydrate GET. Per coordinate: lowercase the event repo (Global Constraint 8), IsEnabledRepo gate, unconditional GetIssueConditional(repo, number, ""), then IngestIssues through the shared owner-strip/translate/stamp pipeline. Per-event errors log-and-continue; ErrBudgetExhausted pauses the drain until the client gate reopens.

Interfaces (issueHydrator, TargetChecker) are defined LOCALLY — structural seams the concrete *forge.GitHub and *store.Store satisfy at T5 wiring; this package imports no store and no concrete forge client on the hydrate path.

Refs RIG-2883
Co-authored-by: Matt Wilkinson matt@rigel.build

…ue (RIG-2883)

T1 of the board-ingestion forge poll→webhook cutover: `BoardWebhookArm`, a second consumer behind the one GitHub ingress.

`Enqueue` satisfies `server.ForgeEventSink`'s non-blocking contract — it filters to board-relevant issue events (`Change ∈ {OPENED, STATE, UPDATE} ∧ Kind == ISSUE`; PR-kind and COMMENT-change dropped) then channel try-sends; a full queue DROPS the event with an exported `expvar` drop metric + Warn (the T3 reconciler heals it).

`Run` drains until ctx cancel (returns nil, driver.go:95-99 idiom). Each drain COALESCES per NORMALIZED `(repo, number)` coordinate first, so an N-event edit storm on one issue costs ONE hydrate GET. Per coordinate: lowercase the event repo (Global Constraint 8), `IsEnabledRepo` gate, unconditional `GetIssueConditional(repo, number, "")`, then `IngestIssues` through the shared owner-strip/translate/stamp pipeline. Per-event errors log-and-continue; `ErrBudgetExhausted` pauses the drain until the client gate reopens.

Interfaces (`issueHydrator`, `TargetChecker`) are defined LOCALLY — structural seams the concrete `*forge.GitHub` and `*store.Store` satisfy at T5 wiring; this package imports no store and no concrete forge client on the hydrate path.

Refs RIG-2883
Co-authored-by: Matt Wilkinson <matt@rigel.build>
@linear-code

linear-code Bot commented Aug 28, 2026

Copy link
Copy Markdown

RIG-2883

@github-actions

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-forge-rig-2883-t1-bo.compass-eng-docs.pages.dev

Deployed from compass-forge/rig-2883-t1-board-arm at 3619c6d.

@rigel-mintaka
rigel-mintaka marked this pull request as ready for review August 28, 2026 05:41
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.

1 participant