refactor(alerts): add a notification dispatch seam - #2918
refactor(alerts): add a notification dispatch seam#2918jordan-simonovski wants to merge 3 commits into
Conversation
template.ts mixed Handlebars templating with the HTTP transport for Slack/generic/incident.io webhooks. Move the transport (notifyChannel, handleSendSlackWebhook, handleSendGenericWebhook, sendGenericWebhook, delivery metrics) into tasks/checkAlerts/notifications.ts unchanged, so the upcoming multi-channel dispatch work lands in a focused module.
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThe PR extracts alert notification delivery behind an injectable dispatcher while retaining synchronous inline delivery as the default.
Confidence Score: 5/5The PR appears safe to merge with the existing inline notification behavior preserved. The default dispatcher forwards the same populated channel, message, and group to the existing transport and continues awaiting delivery so failures propagate through the existing alert error path.
|
| Filename | Overview |
|---|---|
| packages/api/src/tasks/checkAlerts/notifications.ts | Defines the notification job and dispatcher contracts and provides an inline implementation that preserves delivery timing and errors. |
| packages/api/src/tasks/checkAlerts/template.ts | Replaces direct transport invocation with an optional dispatcher while preserving the existing default payload and behavior. |
| packages/api/src/tasks/checkAlerts/tests/notifications.test.ts | Verifies inline dispatch waits for delivery, propagates failures, and has an immediate no-op shutdown. |
Sequence Diagram
sequenceDiagram
participant Eval as Alert evaluation
participant Template as renderAlertTemplate
participant Dispatcher as NotificationDispatcher
participant Transport as deliverToChannel
participant Webhook as Webhook
Eval->>Template: Render alert notification
Template->>Template: Build NotificationJob
Template->>Dispatcher: await dispatch(job)
Dispatcher->>Transport: deliverNotification(job)
Transport->>Webhook: Send message
Webhook-->>Transport: Delivery result
Transport-->>Dispatcher: Resolve or reject
Dispatcher-->>Template: Resolve or reject
Template-->>Eval: Preserve inline result
Reviews (1): Last reviewed commit: "refactor(alerts): add a notification dis..." | Re-trigger Greptile
Deep ReviewRefactor introducing a notification dispatch seam in the alerts task: a new ✅ No critical issues found. 🟡 P2 -- recommended
🔵 P3 nitpicks (4)
Pre-existing (not counted toward verdict)
Reviewers (9): correctness, adversarial, testing, maintainability, project-standards, api-contract, reliability, kieran-typescript, agent-native. Testing gaps:
Coverage: Two low-confidence single-reviewer findings were suppressed below the confidence gate — |
77ccf05 to
f17f741
Compare
Why
Alert notifications are delivered inline, on the evaluation tick. That is the right default, but it hardwires one delivery strategy into the render path: anything wanting to queue deliveries, bound concurrency, or survive across ticks has to edit
renderAlertTemplateitself.This adds the seam so delivery becomes swappable. No behaviour changes — the inline dispatcher is the default and does exactly what the code did before.
The contract worth reading
dispatch()has two legitimate implementations with different timing, and the difference matters to callers:executionErrors.Anything depending on synchronous error propagation from
dispatch()is depending on the inline implementation specifically. That is documented on the interface.Naming
NotificationJob.populatedChannelis deliberately not calledchannel. A job may carry both a serializable channel reference and the resolved document; reusing one name for both makes the two indistinguishable. Only the resolved form exists here today — the name is chosen so it stays correct when the other appears.Not a behaviour change
checkAlerts.int.test.ts(277) andrenderAlertTemplate.int.test.ts(74) pass unmodified — that is the gate. Thedispatcherparameter is optional and defaults to inline, so no existing caller changed.eventIdis byte-identical: same hash, same inputs, same place.