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
//! Shared test plumbing: a single, guarded, migrate-once entry point.
//!
//! Migration runs `CREATE INDEX` / `ALTER TABLE`, which take table-level
//! locks that conflict with in-flight writers — even on the idempotent
//! "already applied" path, since Postgres grabs the lock before the
//! `IF NOT EXISTS` check. If every test re-ran `migrate()` concurrently
//! with peers that hold an open [`mire::TransactionScope`], a migrate could
//! block on that writer's locks while the writer's own progress queues
//! behind the migrate's pending lock — a cross-connection cycle Postgres
//! can't break (the tx-holding connection just looks `idle in transaction`),
//! so the whole binary wedges.
//!
//! The fix is sequencing, not luck: migrate **exactly once per test
//! binary, on its own dedicated connection, behind a guard**; every test
//! blocks on that guard and only then opens its own pool + transaction
//! scopes. By the time any operational write runs, the DDL is long done,
//! so there is never migrate-vs-writer lock contention.
use EventStore;
use PgPool;
use OnceCell;
/// The guard: the schema is migrated the first time any test asks for a
/// store, and never again for the lifetime of this binary.
static MIGRATED: = const_new;
/// A store backed by a fresh per-call pool, with the schema guaranteed
/// migrated. Returns `None` (so the caller can skip) when `DATABASE_URL`
/// is unset.
pub async
/// Like [`store`], but lets the caller configure the operational pool
/// (e.g. a larger `max_connections` for contention tests). The one-time
/// migration still runs on its own dedicated connection behind the guard.
pub async