Skip to main content

Alert Dispatch Flow

How the system evaluates alert rules and delivers real-time in-app notifications.

Overview​

Alert dispatch uses a hybrid evaluation pipeline combining scheduled and event-driven triggers. Both paths use a shared IAlertRuleEvaluator for consistent business logic, and delivery is handled via SignalR with a Redis backplane for instant UI reactivity.


Hybrid Evaluation Pipeline​

The system ensures alert rules are checked whenever relevant data changes.

  1. Scheduled Path (SyncPricesJob): Runs on a cron schedule (config: WorkerSettings.Schedules.SyncPrices). Scans symbols, fetches quotes, evaluates rules, persists notifications, and pushes via SignalR.
  2. Event Path (MarketPriceAlertHandler): Triggered by SQS events (EventType: inventoryalert.pricing.price-drop.v1) for a specific symbol + price.
  3. Holdings Path (LowHoldingsHandler): Triggered by SQS events (EventType: inventoryalert.inventory.stock-low.v1) when a user’s holdings drop below a threshold.

Shared Evaluator Logic (IAlertRuleEvaluator)​


Real-Time Delivery (SignalR)​

SignalR provides an instant push architecture:

  1. Hub Host: InventoryAlert.Api hosts the NotificationHub at /hubs/notifications.
  2. The Signal: When the Worker (producer) identifies a breach, it calls NotifyAsync on the IAlertNotifier.
  3. The Relay: The notifier publishes the NotificationResponse to the Redis Backplane.
  4. The Push: Redis relays the message to all Api instances. The instance holding the user's connection pushes the JSON payload over the WebSocket tunnel.
  5. The UI: The Next.js NotificationProvider receives the event and updates the navbar badge instantly.

Traceability & Observability​

Every alert flow is traceable via a unique CorrelationId:

  1. API Initiated: The X-Correlation-Id from the HTTP request is propagated to the SQS EventEnvelope.
  2. Worker Context: The IntegrationMessageRouter extracts the CorrelationId from the envelope and pushes it to the Serilog LogContext.
  3. Cross-Project Trace: Logs in Seq from both the API and Worker are grouped by this ID, allowing deterministic verification in integration tests using SeqLogReader.
  4. Message Metadata: Each log entry also includes MessageId and EventType for granular debugging.

Notification Schema​

Notifications are now categorized for better UX:

FieldDetail
TypePrice, Holdings, System, News
SeverityInfo, Warning, Critical
StatusReal-time state maintained via React Context + SignalR.

Deduplication & Cooldown​

To prevent "Alert Storms," the system enforces a cooldown gate:

  • Key Pattern: inventoryalert:alerts:cooldown:v1:{userId}:{ruleId}
  • Standard TTL: 24 hours (set by the shared IAlertRuleEvaluator)
  • SQS message idempotency: msg:processed:{messageId} (24h TTL) prevents processing the same SQS message multiple times in the native polling worker.