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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! Row ids: minting them, and reading one that arrived from outside.
//!
//! Every id this server mints is a **UUID version 7** (RFC 9562 §5.7): a
//! 48-bit big-endian millisecond timestamp, then random bits. Two properties
//! follow, and both are why the version moved from 4.
//!
//! The ids of rows created close together share a prefix, so an index over
//! them is written at its right-hand edge rather than at a fresh random leaf
//! per insert. SQLite feels that only mildly — an id column is a secondary
//! index over the rowid, and one writer at a time dominates — but the
//! PostgreSQL backend `TODO.md` plans is where a random primary key costs a
//! page split and a full-page WAL write per row.
//!
//! And they sort by creation. `ORDER BY created_at, id` is the tie-break seven
//! paged listings use on a whole-second `created_at`, so that tie-break is now
//! chronological where a v4 gave a fresh random permutation per pair. Only
//! among rows minted since the change: the ids already in a table were
//! converted in place and keep the v4 bits they were minted with, so a v4 and a
//! v7 in the same second still tie arbitrarily, for ever.
//!
//! Ids are stored as the 16 bytes themselves, not as text — `sqlx`'s `uuid`
//! feature encodes a [`Uuid`] as a SQLite BLOB and decodes it with
//! `Uuid::from_slice`, and maps the same type to Postgres's native `uuid`. So
//! there is no decode helper here: `row.try_get::<Uuid, _>("id")` is the whole
//! of it. What there is instead is [`parse`], for the one direction that can
//! fail.
//!
//! Three mints in this crate are deliberately **not** row ids and do not come
//! through [`mint`]: the `x-request-id` fallback
//! ([`crate::middlewares::access`]), the job runner's lease-owner id
//! ([`crate::jobs::runner`]) and a notification's `delivery_id`
//! ([`crate::notify`]). None is the identity of a row, and reaching into the
//! storage layer for a value that never reaches storage would be backwards.
use Uuid;
/// A fresh row id.
///
/// The single place the version is chosen, which is what lets
/// `declared_id_widths_match_a_minted_id` (`crate::sqlite::db`) pin it and what
/// would make a move to some later version one line plus one test.
/// Parses an id that arrived from outside the process.
///
/// `None` for anything an id column could not hold — a `kid` a client invented,
/// a path segment an operator mistyped, a scanner probing `/acct/../..`. Every
/// caller turns that into the same answer an unknown-but-well-formed id gets,
/// so no request path grows a "malformed id" case RFC 8555 has no code for.
///
/// Deliberately narrower than [`Uuid::try_parse`], which also accepts the
/// 32-character simple form, `{braced}` and `urn:uuid:` spellings, and
/// upper-case hex. Every id this server has ever written came from
/// `Uuid::to_string()`, so 36 hyphenated characters is the only shape a column
/// holds and the only one a URL this server minted can carry. Accepting the
/// others would start resolving URLs that answer "not found" today, which is a
/// change of behaviour wearing a refactor's clothes.