Push Outbox and Suppression Audit
An audit trail from source changes through suppression decisions, outbox claims, and APNs results
Hangangjari creates notification candidates from source changes, applies delivery rules, and places only passing items in the outbox. APNs results and suppression reasons are both stored in the audit trail.
Operators need to distinguish no candidate, no matching subscription, policy suppression, and APNs delivery failure. Successful-send records alone cannot separate those states.
From Source Change to Notification Candidate
The push worker normalizes source events into canonical facts. A parking lot falling below a remaining-space threshold, a park crowding change, and an event cancellation each become a fact.
Then each fact is matched with subscriptions. The system checks which parks or lots the user cares about, which notification types are enabled, and whether quiet hours apply.
flowchart LR Source["Source change"] --> Fact["Notification fact"] Fact --> Match["Candidate matching"] Subscription["Subscriptions/settings"] --> Match Match --> Policy["Send decision"] Policy --> Decision["push_now or suppress"] Decision --> Outbox["Push outbox"]
Suppression Rules Applied First
Hangangjari has explicit suppression rules.
| Example | Reason |
|---|---|
| Suppress broad parking-lot state-change notifications | Users are closer to wanting remaining-space threshold alerts |
| Suppress threshold alerts for lots without remaining-space values | There is no actionable number |
| Suppress broad park state-change notifications | Too broad, with unclear user action |
| Suppress unclear crowding changes | A safe message body cannot be made |
Candidates that pass these rules receive user-setting and impact checks.
User Settings and Impact
After a candidate passes the suppression rules, the system evaluates the user’s notification mode and the fact’s priority.
The checks run in this order:
- Did the user turn notifications off?
- Is this change high urgency?
- In parking-first mode, is this an important parking signal?
- In outing-brief mode, is this an important park/event signal?
- Otherwise, is it important enough for smart mode?
The result is push_now or suppress, and it must leave a reason code.
flowchart TD
Candidate["Matched candidate"] --> Off{"Notifications off?"}
Off -->|Yes| Suppress["Record suppression reason"]
Off -->|No| Rule{"Stop rule applies?"}
Rule -->|Yes| SuppressRule["Suppress with reason"]
Rule -->|No| Tier{"Important or T0?"}
Tier -->|Yes| Push["push_now"]
Tier -->|No| Mode["Mode-specific decision"]
Non-Delivery Recorded in the Delivery Decision
Non-delivery is recorded as no candidate, subscription mismatch, policy suppression, or delivery failure.
The delivery-decision record stores subscription, fact, target, decision, reason code, policy mode, and policy version. It also prevents the same fact/subscription pair from being processed twice.
When reason-code distribution changes abruptly, fact generation and subscription matching are checked separately. Suppression records a candidate that intentionally did not proceed to delivery.
APNs Delivery from the Outbox
The outbox stores delivery work transactionally and lets a separate dispatcher send it to APNs.
sequenceDiagram
autonumber
participant Worker as Push worker
participant Outbox as Outbox table
participant Dispatcher as Push dispatcher
participant APNs as APNs
participant Repo as Delivery repository
Worker->>Outbox: Enqueue notification for delivery
Dispatcher->>Outbox: Fetch notification ready to send
Dispatcher->>APNs: Send message to APNs
alt Success
Dispatcher->>Repo: Record delivery success
else Invalid device token
Dispatcher->>Repo: Record terminal failure and token-cleanup candidate
else APNs auth error
Dispatcher->>Repo: Defer remaining work
else Retryable failure
Dispatcher->>Repo: Store next attempt time and backoff
end
When sending from the outbox, the system distinguishes:
- Expired items are not sent.
- Messages without prepared translations become terminal failures.
- Invalid device tokens become cleanup candidates.
- When APNs authentication fails, remaining items are deferred instead of being forced through.
- Retryable failures reflect attempt count and backoff.
A Dashboard for Decision Reasons
The dashboard shows sends, suppressions, retries, invalid device tokens, long-waiting outbox items, and backlog by priority. An increase in suppression reasons leads to checks of fact generation and subscription rules; APNs errors are separated by retry and token-cleanup actions.
Reason Codes and Delivery Attempts
Delivery decisions record both sends and suppressions with reason codes. The outbox and delivery attempts connect missing translations, invalid device tokens, APNs authentication errors, and retryable failures to different follow-up actions.
Comments
No comments yet. Be the first to leave one.
Pending review