# Flow F4 — Failsafe Outbox Drain → RabbitMQ Stream Cross-reference: `system-flows.md` → Flow F4. ## Sequence ```mermaid sequenceDiagram autonumber participant FP as FailsafeProducer (02, IHostedService) participant DB participant Path as PathResolver (06) participant FS as Filesystem participant RMQ as RabbitMQ Stream "azaion-annotations" loop while host running FP->>DB: SELECT FROM annotations_queue_records DB-->>FP: pending rows (operation, annotation_ids JSON) loop per row alt operation = Created FP->>Path: GetImagePath(annotationId) FP->>FS: read bytes end FP->>FP: serialize MessagePack (Annotation*QueueMessage) FP->>RMQ: publish stream entry alt publish ok FP->>DB: DELETE annotations_queue_records WHERE id = :id else stream unavailable FP->>FP: log + backoff end end end ``` ## State ```mermaid stateDiagram-v2 [*] --> Idle Idle --> Draining: queue rows present Draining --> Publishing: row picked Publishing --> Acked: stream publish ok Acked --> Idle: row deleted Publishing --> Backoff: stream unavailable Backoff --> Idle: backoff elapsed ``` ## Notes - See ADR-003 in `architecture.md` for rationale. - Multi-instance drain: no leasing in DB → duplicate stream entries possible. Suite consumer contract should dedupe. - Bulk message (`AnnotationBulkQueueMessage`) carries multiple annotation ids; `Created` semantics on bulk are out of scope here — confirm during Step 4 verification.