docs(spike): inline Mermaid for store-and-forward lifecycle

Swap the store-and-forward Message Lifecycle PNG embed for an inline
mermaid block to verify whether gitea renders mermaid in markdown. If it
does, the standard flow/state/hierarchy diagrams can move to inline
mermaid (text-only, auto-layout) instead of draw.io source + PNG.
This commit is contained in:
Joseph Doherty
2026-05-31 23:53:04 -04:00
parent bdee12f4e9
commit 4c5e7eb917
+22 -2
View File
@@ -25,8 +25,28 @@ Site clusters only. The central cluster does not buffer messages.
## Message Lifecycle
![storeforward-message-lifecycle](diagrams/storeforward-message-lifecycle.png)
<!-- source: diagrams/storeforward-message-lifecycle.drawio — edit, then re-export with export-drawio.sh -->
```mermaid
flowchart TD
A([Script submits message]) --> B[Attempt immediate delivery]
B --> C{Delivered?}
C -->|Success| D([Remove from buffer])
C -->|Failure| E[Buffer message]
E --> F[Retry loop<br/>per retry policy]
F --> G{Retry outcome}
G -->|Success| H([Remove from buffer<br/>+ notify standby])
G -->|Max retries exhausted| I([Park message<br/>dead-letter])
classDef ok fill:#d5e8d4,stroke:#82b366;
classDef proc fill:#dae8fc,stroke:#6c8ebf;
classDef dec fill:#fff2cc,stroke:#d6b656;
classDef buf fill:#ffe6cc,stroke:#d79b00;
classDef bad fill:#f8cecc,stroke:#b85450;
class A,D,H ok
class B,F proc
class C,G dec
class E buf
class I bad
```
For notifications, "delivery" means forwarding the message to the central cluster via CentralSite Communication; "success" is central's ack, on which the message is cleared. Notifications are retried at the fixed forward interval until central acks, but — like every other category — they are bounded by the engine's `DefaultMaxRetries` cap: a sustained central outage that exceeds `DefaultMaxRetries × forward-interval` will park the buffered notification, after which an operator can Retry/Discard it via the parked-message UI. Operationally, the cap is sized so the normal central-recovery window stays well inside it; "do not park" is the design's operational intent on the happy path, not an absolute invariant. Callers that genuinely require unbounded retry pass `maxRetries: 0` on `EnqueueAsync` (the documented "no limit" escape hatch — see `StoreAndForward-015`).