Skip to main content

Escalation System

Escalation is driven by Symfony Messenger DelayStamp — no polling cron required.

Flow

  1. When TransportHandler successfully sends a notification, it dispatches an EscalationMessage with a DelayStamp equal to escalation_rules.ack_timeout_seconds for the matching rule.
  2. The Messenger worker holds the message in the queue until the delay expires.
  3. When the delay expires, EscalationHandler checks notification.escalation_cancelled_at. If set (already ACKed) — exits immediately.
  4. If not cancelled, EscalationEngine:
    • Loads the EscalationRule matching the incident priority and PSAP agency
    • Sends alerts to each PSAP user in rule.notify_psap_user_ids via their transport preferences
    • Re-notifies the next company user in rule.escalation_order
    • Writes an EscalationEvent row
    • Logs escalation_triggered and escalation_alert via CommunicationLogger
  5. A new EscalationMessage with DelayStamp is dispatched for the newly notified user — repeating the chain.

Cancellation

ACK at any point in the chain dispatches an EscalationCancelMessage. The handler sets escalation_cancelled_at and the pending EscalationMessage becomes a no-op.

EscalationRule Fields

FieldDescription
priority_filterWhich incident priorities trigger this rule
ack_timeout_secondsHow long to wait before escalating
escalation_orderOrdered array of user IDs to notify in sequence
notify_psap_user_idsPSAP users to alert when escalation fires