[feat](alarm): add a durable per-device delivery ledger

pg_notify and the socket fan-out are not durable, so an offline phone used to miss a trigger forever and no-auto-stop would leave it ringing at nobody. Write one ledger row per enabled subscription in the trigger transaction, replay what a subscription still owes on every socket connect, and clear a row only on an explicit ack (live socket ack or ackAlarm); alarmStatus is a read-only check-in that answers 409 ERR_ALARM_TRIGGERED_OFFLINE with the missed frame. Ack is idempotent, and a destroyed alert cascades its debt away so a client is never told it missed an alarm that no longer exists.
This commit is contained in:
2026-10-19 02:26:46 +01:00
parent 0334d7fe93
commit 6e6a1e9c8a
12 changed files with 1128 additions and 77 deletions
+6 -7
View File
@@ -44,13 +44,12 @@ func TestBroadcastLatency(t *testing.T) {
for i := 0; i < iterations; i++ {
eventID := uuid.NewString()
frame := AlarmFrame{
Type: "alarm",
AlertID: alertID.String(),
EventID: eventID,
Action: "trigger",
Message: "latency probe",
ServerTime: time.Now().UTC().Format(time.RFC3339Nano),
AutoStopSeconds: 300,
Type: "alarm",
AlertID: alertID.String(),
EventID: eventID,
Action: "trigger",
Message: "latency probe",
ServerTime: time.Now().UTC().Format(time.RFC3339Nano),
}
start := time.Now()
if delivered := hub.Broadcast(alertID, frame); delivered != 2 {