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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use Builder;
use ;
pub const DEFAULT_PERSIST_EVENTS_BATCH_SIZE: usize = 5000;
/// How long the persistent cache waits before the first gap-fill attempt
/// for a stalled broadcast sequence. Most gaps are in-flight transactions
/// that committed out of sequence-allocation order and resolve on their own
/// within a few ms (and this process's own commit-failed allocations are
/// compensated reactively, never waiting for a fill attempt at all);
/// attempting immediately wastes a page re-read per gap. At high posting
/// rates (hundreds of sequences/s) there is nearly always an in-flight
/// frontier gap, so a sub-second grace is guaranteed-too-short and turns
/// the fill into a permanent background load — hence seconds, not
/// milliseconds. Attempts are read-only until the missing sequences are
/// *provably abandoned* (every transaction that could have produced them
/// has ended — see `MailboxTables::abandonment_proof_passed`), so a fill
/// can never collide with a live writer regardless of this setting.
pub const DEFAULT_GAP_FILL_GRACE: Duration = from_secs;
/// Maximum number of placeholder rows a single gap-fill query may insert.
/// Bounds the worst case (a mass rollback or long outage leaving thousands
/// of lost sequences) to a small, predictable statement instead of one
/// giant insert; the fixed 1s retry cadence picks up the remainder, so a
/// cap delays recovery of a pathological backlog without ever losing
/// sequences.
pub const DEFAULT_GAP_FILL_BATCH_LIMIT: usize = 1000;
/// How long the per-process notifier coalesces committed-batch reports
/// before emitting one `pg_notify` wake-up hint. Notify-bearing commits
/// serialize on a cluster-wide lock, so app transactions no longer notify;
/// this bounds the added cross-process wake-up latency (in-process delivery
/// is unaffected).
pub const DEFAULT_NOTIFY_DEBOUNCE: Duration = from_millis;
/// How long the persistent cache goes without authoritative progress (a
/// newly-seen committed row or a confirmed head read) before polling the
/// sequence head (the O(1) `last_value` query). Backstops lost wake-ups: a
/// writer crashing between commit and notify, a dead remote notifier, or
/// external writers that never notify.
pub const DEFAULT_IDLE_RESYNC_INTERVAL: Duration = from_secs;
/// Width, in `sequence` units, of each `persistent_outbox_events` partition.
///
/// A fixed schema constant, deliberately **not** runtime-configurable: it must
/// equal the range of the initial `p0` partition hard-coded in the migration
/// (`[0, 2_000_000)`), or the maintainer would create partitions that overlap
/// `p0`. Changing the size means editing both this constant and the migration
/// together.
///
/// Sized from real event data: outbox rows measure ~760 B each (payloads
/// average a few hundred bytes and rarely TOAST), so 2M rows ≈ ~1.5 GB per
/// partition — small enough that the hot partition stays cache-resident and a
/// per-partition vacuum is quick, while keeping the partition count low.
pub const DEFAULT_PARTITION_WIDTH: u64 = 2_000_000;
/// How many partitions ahead of the current sequence head the maintainer
/// keeps created — including on the initial synchronous `ensure` at
/// registration, so a fresh install starts with a multi-partition runway
/// (the migration itself ships only `p0` + `DEFAULT`). `premake * width` must
/// comfortably exceed the events produced between two maintainer ticks so the
/// head never reaches the last pre-made boundary (which would spill into the
/// `DEFAULT` partition). Empty partitions are cheap, so this errs generous:
/// 5 * 2M = 10M sequences of headroom by default.
pub const DEFAULT_PARTITION_PREMAKE: u64 = 5;
/// How often the partition maintainer wakes to pre-create partitions ahead of
/// the head. Each tick is idempotent (`CREATE ... IF NOT EXISTS`), so this is
/// a cheap steady-state poll; premake margin, not cadence, is the safety
/// budget against bursts.
pub const DEFAULT_PARTITION_MAINTAINER_INTERVAL: Duration =
from_secs;