1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Postgres `NOTIFY`-based publisher — Phase 5 Task 11.5.
//!
//! `NotifyPublisher` delivers outbox rows by issuing `SELECT pg_notify($1, $2)`
//! over a regular database connection. It requires no external broker and is
//! available whenever the `outbox` feature is enabled.
//!
//! # Channel routing
//!
//! The Phase 5 plan's `NotifyPublisher` snippet used `row.model_table` to build
//! the channel name per-row. `OutboxRow` does not carry a `model_table` field
//! (the worker outbox is a generic table and rows do not remember their source
//! table beyond the outbox table name itself). Rather than adding that field
//! to `OutboxRow`, `NotifyPublisher` accepts a fixed `channel` string at
//! construction time and the reference relay binary builds one publisher per
//! outbox table with `format!("{channel_prefix}{table}")` — keeping per-table
//! NOTIFY routing while leaving `OutboxRow` minimal. Callers that need
//! finer-grained routing (e.g. per-action channels) create additional
//! publishers the same way.
//!
//! # Usage
//!
//! ```ignore
//! let publisher = NotifyPublisher::new(pool.clone(), "orders_outbox".to_string());
//! ```
//!
//! The channel name is embedded verbatim in `SELECT pg_notify($1, $2)` as a
//! bind parameter, so it is safe regardless of content.
//!
//! # Message payload
//!
//! The NOTIFY payload is the JSON string representation of `OutboxRow::payload`.
//! Subscribers receive a raw JSON string they can parse independently. Postgres
//! NOTIFY payloads are limited to 8000 bytes; payloads exceeding this limit will
//! silently truncate on the wire. For large payloads, use a broker-backed
//! publisher instead.
use crateRawAccessExt as _;
use crateDjogiContext;
use crate;
use crateOutboxRow;
use crateDjogiPool;
use async_trait;
/// Delivers outbox rows via Postgres `NOTIFY`.
///
/// Uses the pool to acquire a fresh connection per publish call. This is
/// intentional: the relay loop typically calls `mark_published` on the same
/// context as the claim, but `publish` should not run inside the same
/// transaction (NOTIFY delivery semantics are per-connection, not per-transaction
/// — the listener on a separate connection sees the notification when the
/// publishing transaction commits, or immediately if outside a transaction).
///
/// # Constructor
///
/// ```ignore
/// let publisher = NotifyPublisher::new(pool, "my_outbox_channel".to_string());
/// ```
///
/// If you need per-action channels, create multiple publishers:
///
/// ```ignore
/// let create_publisher = NotifyPublisher::new(pool.clone(), "orders_created".to_string());
/// let delete_publisher = NotifyPublisher::new(pool.clone(), "orders_deleted".to_string());
/// ```