Escalation System
Escalation is driven by Symfony Messenger DelayStamp — no polling cron required.
Flow
- When
TransportHandlersuccessfully sends a notification, it dispatches anEscalationMessagewith aDelayStampequal toescalation_rules.ack_timeout_secondsfor the matching rule. - The Messenger worker holds the message in the queue until the delay expires.
- When the delay expires,
EscalationHandlerchecksnotification.escalation_cancelled_at. If set (already ACKed) — exits immediately. - If not cancelled,
EscalationEngine:- Loads the
EscalationRulematching the incident priority and PSAP agency - Sends alerts to each PSAP user in
rule.notify_psap_user_idsvia their transport preferences - Re-notifies the next company user in
rule.escalation_order - Writes an
EscalationEventrow - Logs
escalation_triggeredandescalation_alertviaCommunicationLogger
- Loads the
- A new
EscalationMessagewithDelayStampis 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
| Field | Description |
|---|---|
priority_filter | Which incident priorities trigger this rule |
ack_timeout_seconds | How long to wait before escalating |
escalation_order | Ordered array of user IDs to notify in sequence |
notify_psap_user_ids | PSAP users to alert when escalation fires |