Skip to content

Sink Health Monitoring: Context Module & CRUD Operations #2

Description

@joejohnson123

Overview

Create the Sequin.Monitors context module providing all CRUD operations and business logic for sink monitors.

Depends on: #1 (Database Schema & Migrations)

Context: Sequin.Monitors

Monitor CRUD

  • list_monitors_for_consumer(consumer_id) — returns all monitors for a sink, preloading notification channels
  • list_monitors_for_account(account_id) — all monitors across all sinks for an account
  • list_enabled_monitors() — all enabled monitors across all accounts (used by evaluation worker)
  • get_monitor(id) — fetch by ID with preloads
  • get_monitor!(id) — raising version
  • create_monitor(sink_consumer_id, attrs) — creates monitor + nested notification channels
  • update_monitor(monitor, attrs) — updates monitor + upserts/removes channels
  • delete_monitor(monitor) — cascading delete
  • toggle_monitor(monitor, enabled) — enable/disable shortcut

Notification Channel CRUD

  • add_notification_channel(monitor, attrs)
  • update_notification_channel(channel, attrs)
  • remove_notification_channel(channel)

Alert Operations

  • create_alert(monitor, attrs) — records a new alert
  • resolve_alert(alert) — sets status: :resolved and resolved_at
  • list_alerts_for_monitor(monitor_id, opts) — paginated, ordered by triggered_at desc
  • get_active_alert(monitor_id) — gets current triggered (unresolved) alert if any
  • prune_old_alerts(older_than) — cleanup alerts older than N days

Metric Samples (for anomaly detection)

  • record_metric_sample(monitor, value) — inserts a sample
  • get_recent_samples(monitor_id, window_seconds) — returns samples within window
  • prune_old_samples(older_than) — removes samples older than 2 hours

Helper Functions

  • current_metric_value(monitor) — fetches the live metric value:
    • :pending_messagesSlotMessageStore.count_messages(consumer)
    • :failed_messagesConsumers.count_messages_for_consumer(consumer, delivery_count_gte: 1)
  • cooldown_active?(monitor) — checks if last alert was within cooldown_seconds

Files to Create

  • lib/sequin/monitors/monitors.ex

Implementation Notes

  • Preload notification_channels by default on monitor queries
  • Use Repo.transact for create/update operations that touch channels
  • Follow existing context patterns (see Sequin.Consumers, Sequin.Health)
  • current_metric_value/1 needs to preload the sink_consumer association
  • Consider caching monitor list for the evaluation worker (refreshed every cycle)

Acceptance Criteria

  • All CRUD operations work correctly
  • Nested channel create/update/delete within monitor operations
  • current_metric_value/1 returns correct counts for both metrics
  • cooldown_active?/1 correctly checks timing
  • Proper error handling with Sequin.Error types
  • Tests for all public functions

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions