Skip to content

Implementing AlertChannel interface and dispatcher core - #290

Merged
AbdulmalikAlayande merged 3 commits into
TegoLabs:mainfrom
Olagoke22:main
Jul 5, 2026
Merged

AbdulmalikAlayande merged 3 commits into
TegoLabs:mainfrom
Olagoke22:main

Conversation

@Olagoke22

Copy link
Copy Markdown
Contributor

closes #109

@drips-wave

drips-wave Bot commented Jun 29, 2026

Copy link
Copy Markdown

@Olagoke22 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jun 29, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Olagoke22, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 53 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: d0dd26ee-bb9d-40b1-b2b2-9f9a564f8794

📥 Commits

Reviewing files that changed from the base of the PR and between 3f78cde and fb343ab.

📒 Files selected for processing (1)
  • src/alerts/types.ts
📝 Walkthrough

Walkthrough

Introduces an AlertChannel interface with a send() method in types.ts. Replaces the internal route() switch in dispatcher.ts with an exported DEFAULT_CHANNELS lookup map. Both deliverPendingAlerts and deliverSingleAlert gain an optional injectable channels parameter. Tests are refactored to use typed mock channels instead of per-module mocks.

AlertChannel interface and configurable dispatcher routing

Layer / File(s) Summary
AlertChannel interface and DEFAULT_CHANNELS contract
src/alerts/types.ts, src/alerts/dispatcher.ts
Adds AlertChannel interface with send(target, event, secret?) to types.ts. In dispatcher.ts, imports AlertChannel, defines DeliveryResult, and exports DEFAULT_CHANNELS mapping channel type strings to sender implementations; deliverPendingAlerts and deliverSingleAlert signatures gain an optional channels parameter defaulting to DEFAULT_CHANNELS.
Dispatcher routing implementation
src/alerts/dispatcher.ts
Removes internal route() switch; both deliverPendingAlerts and deliverSingleAlert now look up channels[alert.channelType], throw on unknown types (caught by existing retry/abandoned logic), and call channel.send().
Test suite refactored to injectable channels
tests/alerts/dispatcher.test.ts
Introduces mockChannel() returning an AlertChannel-typed object with a send mock; all test cases pass a channels map into deliverPendingAlerts and assert routing, delivery flags, retry counts, resilience, and payload correctness via channels.<type>.send.mock.calls.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~15 minutes

Possibly related PRs

Poem

🐇 A map replaced a switch today,
each channel found its proper way.
send() is the contract, clean and bright,
mock channels make the tests run right.
No more hard-wired routes to trace—
inject your channels, any place! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately reflects the added AlertChannel interface and dispatcher work.
Description check ✅ Passed The description is brief but still related to the linked alert dispatcher change.
Linked Issues check ✅ Passed The PR implements the dispatcher, routing, error isolation, DB updates, and tests required by #109.
Out of Scope Changes check ✅ Passed The changes stay focused on alert dispatching and related tests without clear unrelated additions.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/alerts/dispatcher.test.ts (1)

26-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep the fixture aligned with the full default channel map.

The helper and per-test channels fixture still only model webhook, slack, and pagerduty, but DEFAULT_CHANNELS now also ships discord and telegram. That leaves two production routes outside the typed test surface, so a broken mapping there would not fail this suite. Consider deriving these fixtures from DEFAULT_CHANNELS (or widening channelType) so new defaults stay covered automatically.

Also applies to: 77-85

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/alerts/dispatcher.test.ts` around lines 26 - 27, The test fixture types
in dispatcher.test.ts are out of sync with DEFAULT_CHANNELS because they only
cover webhook, slack, and pagerduty, so discord and telegram are untested.
Update the shared channel fixture and any helper types used by the dispatcher
tests to derive from DEFAULT_CHANNELS or otherwise include all current channel
types, and make sure the per-test channels setup still exercises the full
default channel map through the relevant test helpers and fixtures.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/alerts/dispatcher.ts`:
- Around line 66-76: The send and persistence steps in dispatcher logic are
currently wrapped in the same try/catch, so a failure in markAlertDelivered() is
treated like a channel.send() failure and causes an unnecessary retry. Update
the alert delivery flow in dispatcher.ts to separate the outbound send path from
the post-send database write, using distinct error handling around
channel.send() and markAlertDelivered(). Keep retry_count increments and
retry/error accounting only for send failures, and handle persistence errors
without re-queuing the alert as undelivered.

---

Outside diff comments:
In `@tests/alerts/dispatcher.test.ts`:
- Around line 26-27: The test fixture types in dispatcher.test.ts are out of
sync with DEFAULT_CHANNELS because they only cover webhook, slack, and
pagerduty, so discord and telegram are untested. Update the shared channel
fixture and any helper types used by the dispatcher tests to derive from
DEFAULT_CHANNELS or otherwise include all current channel types, and make sure
the per-test channels setup still exercises the full default channel map through
the relevant test helpers and fixtures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 643a8120-b101-4c51-b3ea-2d5738a57ea6

📥 Commits

Reviewing files that changed from the base of the PR and between 92a2417 and 3f78cde.

📒 Files selected for processing (3)
  • src/alerts/dispatcher.ts
  • src/alerts/types.ts
  • tests/alerts/dispatcher.test.ts
📜 Review details
🔇 Additional comments (2)
src/alerts/types.ts (1)

56-58: LGTM!

src/alerts/dispatcher.ts (1)

104-116: LGTM!

Comment thread src/alerts/dispatcher.ts
Comment on lines +66 to 76
await channel.send(alert.channelTarget, event, alert.webhookSecret);
markAlertDelivered(db, alert.alertFiredId);
result.delivered++;

logger.info(
`Alert delivered — id: ${alert.alertFiredId}, ` +
`channel: ${alert.channelType}, contract: ${alert.contractId}`,
`Alert delivered — id: ${alert.alertFiredId}, channel: ${alert.channelType}, contract: ${alert.contractId}`,
);
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
result.failed++;
result.errors.push(message);

incrementRetryCount(db, alert.alertFiredId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Separate send failures from post-send persistence failures.

markAlertDelivered() is inside the same try as channel.send(). If the outbound send succeeds and the DB write throws, Line 76 increments retry_count and the same alert will be retried on the next cycle, duplicating the notification. Handle the post-send persistence path separately instead of funneling it into the resend logic.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/alerts/dispatcher.ts` around lines 66 - 76, The send and persistence
steps in dispatcher logic are currently wrapped in the same try/catch, so a
failure in markAlertDelivered() is treated like a channel.send() failure and
causes an unnecessary retry. Update the alert delivery flow in dispatcher.ts to
separate the outbound send path from the post-send database write, using
distinct error handling around channel.send() and markAlertDelivered(). Keep
retry_count increments and retry/error accounting only for send failures, and
handle persistence errors without re-queuing the alert as undelivered.

@gitguardian

gitguardian Bot commented Jun 29, 2026

Copy link
Copy Markdown

⚠️ GitGuardian has uncovered 6 secrets following the scan of your pull request.

Please consider investigating the findings and remediating the incidents. Failure to do so may lead to compromising the associated services or software components.

Since your pull request originates from a forked repository, GitGuardian is not able to associate the secrets uncovered with secret incidents on your GitGuardian dashboard.
Skipping this check run and merging your pull request will create secret incidents on your GitGuardian dashboard.

🔎 Detected hardcoded secrets in your pull request
GitGuardian id GitGuardian status Secret Commit Filename
- - Generic High Entropy Secret 3dd17ce tests/core/vault.test.ts View secret
- - Generic High Entropy Secret 3dd17ce tests/core/vault.test.ts View secret
- - Generic High Entropy Secret 3dd17ce tests/core/vault.test.ts View secret
- - Generic High Entropy Secret b59bef4 tests/core/vault.test.ts View secret
- - Generic High Entropy Secret b59bef4 tests/core/vault.test.ts View secret
- - Generic High Entropy Secret b59bef4 tests/core/vault.test.ts View secret
🛠 Guidelines to remediate hardcoded secrets
  1. Understand the implications of revoking this secret by investigating where it is used in your code.
  2. Replace and store your secrets safely. Learn here the best practices.
  3. Revoke and rotate these secrets.
  4. If possible, rewrite git history. Rewriting git history is not a trivial act. You might completely break other contributing developers' workflow and you risk accidentally deleting legitimate data.

To avoid such incidents in the future consider


🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request.

@AbdulmalikAlayande
AbdulmalikAlayande merged commit fb343ab into TegoLabs:main Jul 5, 2026
2 of 3 checks passed
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.

feat(alerts): implement AlertChannel interface and dispatcher core

2 participants