@namzu/sdk 20.2.0 → 20.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +185 -0
- package/dist/manager/run/persistence.d.ts +2 -2
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +14 -5
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/public-runtime.d.ts +2 -1
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +6 -1
- package/dist/public-runtime.js.map +1 -1
- package/dist/runtime/query/checkpoint.d.ts +27 -1
- package/dist/runtime/query/checkpoint.d.ts.map +1 -1
- package/dist/runtime/query/checkpoint.js +34 -4
- package/dist/runtime/query/checkpoint.js.map +1 -1
- package/dist/runtime/query/context.d.ts +2 -0
- package/dist/runtime/query/context.d.ts.map +1 -1
- package/dist/runtime/query/context.js +1 -0
- package/dist/runtime/query/context.js.map +1 -1
- package/dist/runtime/query/index.d.ts +32 -1
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +5 -0
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/resume-run.d.ts +9 -1
- package/dist/runtime/query/resume-run.d.ts.map +1 -1
- package/dist/runtime/query/resume-run.js +2 -1
- package/dist/runtime/query/resume-run.js.map +1 -1
- package/dist/store/index.d.ts +2 -1
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +2 -1
- package/dist/store/index.js.map +1 -1
- package/dist/store/run/checkpoint-disk.d.ts +18 -2
- package/dist/store/run/checkpoint-disk.d.ts.map +1 -1
- package/dist/store/run/checkpoint-disk.js +50 -5
- package/dist/store/run/checkpoint-disk.js.map +1 -1
- package/dist/store/run/checkpoint-memory.d.ts +22 -2
- package/dist/store/run/checkpoint-memory.d.ts.map +1 -1
- package/dist/store/run/checkpoint-memory.js +99 -4
- package/dist/store/run/checkpoint-memory.js.map +1 -1
- package/dist/store/run/claim-disk.d.ts +130 -0
- package/dist/store/run/claim-disk.d.ts.map +1 -0
- package/dist/store/run/claim-disk.js +550 -0
- package/dist/store/run/claim-disk.js.map +1 -0
- package/dist/store/run/disk.d.ts +10 -8
- package/dist/store/run/disk.d.ts.map +1 -1
- package/dist/store/run/disk.js.map +1 -1
- package/dist/store/run/listing.d.ts +44 -1
- package/dist/store/run/listing.d.ts.map +1 -1
- package/dist/store/run/listing.js +92 -1
- package/dist/store/run/listing.js.map +1 -1
- package/dist/store/run/memory.d.ts +46 -0
- package/dist/store/run/memory.d.ts.map +1 -0
- package/dist/store/run/memory.js +104 -0
- package/dist/store/run/memory.js.map +1 -0
- package/dist/types/run/checkpoint-store.d.ts +178 -2
- package/dist/types/run/checkpoint-store.d.ts.map +1 -1
- package/dist/types/run/config.d.ts +12 -0
- package/dist/types/run/config.d.ts.map +1 -1
- package/dist/types/run/index.d.ts +1 -0
- package/dist/types/run/index.d.ts.map +1 -1
- package/dist/types/run/index.js +1 -0
- package/dist/types/run/index.js.map +1 -1
- package/dist/types/run/store.d.ts +103 -0
- package/dist/types/run/store.d.ts.map +1 -0
- package/dist/types/run/store.js +30 -0
- package/dist/types/run/store.js.map +1 -0
- package/package.json +1 -1
- package/src/manager/run/persistence.ts +17 -7
- package/src/public-runtime.ts +6 -0
- package/src/runtime/query/checkpoint.ts +42 -5
- package/src/runtime/query/context.ts +3 -0
- package/src/runtime/query/index.ts +39 -1
- package/src/runtime/query/resume-run.ts +12 -2
- package/src/store/index.ts +5 -0
- package/src/store/run/checkpoint-disk.ts +70 -5
- package/src/store/run/checkpoint-memory.ts +118 -3
- package/src/store/run/claim-disk.ts +593 -0
- package/src/store/run/disk.ts +10 -8
- package/src/store/run/listing.ts +116 -1
- package/src/store/run/memory.ts +121 -0
- package/src/types/run/checkpoint-store.ts +189 -2
- package/src/types/run/config.ts +13 -0
- package/src/types/run/index.ts +1 -0
- package/src/types/run/store.ts +112 -0
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A run claim on a filesystem, correct across PROCESSES.
|
|
3
|
+
*
|
|
4
|
+
* ## The fence is the filename
|
|
5
|
+
*
|
|
6
|
+
* A run's claims live at `{runDir}/claims/{fence}.json`. Taking the run means
|
|
7
|
+
* exclusively creating the next number; the kernel makes exactly one of any
|
|
8
|
+
* number of simultaneous callers the creator, and every other gets `EEXIST`.
|
|
9
|
+
* The current holding is the highest-numbered file.
|
|
10
|
+
*
|
|
11
|
+
* That single decision is the whole mechanism, and it is what the first
|
|
12
|
+
* version of this file got wrong. That version kept ONE mutable `claim.json`
|
|
13
|
+
* and protected it with a lock, which needed a stale-lock breaker, which was
|
|
14
|
+
* `unlink` followed by an exclusive create — two operations. An adversarial
|
|
15
|
+
* pass reproduced the consequence from separate processes: two workers both
|
|
16
|
+
* judge a stale guard breakable, the second unlinks the FIRST one's fresh
|
|
17
|
+
* guard, both end up inside the section believing they hold it, neither has
|
|
18
|
+
* written yet so neither can be the loser of a re-read, and both write the
|
|
19
|
+
* same fence. Twenty-six of three hundred runs went to two workers at an
|
|
20
|
+
* identical fence — and an identical fence fences nobody out, because the
|
|
21
|
+
* comparison is `<`.
|
|
22
|
+
*
|
|
23
|
+
* Numbering the files instead removes every one of those steps. There is no
|
|
24
|
+
* lock to go stale, so no breaker, so no window. Concurrency is decided by
|
|
25
|
+
* one `O_CREAT | O_EXCL`.
|
|
26
|
+
*
|
|
27
|
+
* ## Four properties this layout gives for free
|
|
28
|
+
*
|
|
29
|
+
* **Monotonic across release and deletion.** Fences are file names that stay,
|
|
30
|
+
* so releasing cannot rewind the counter. Deleting `claim.json` used to send
|
|
31
|
+
* the next caller down a fresh-claim path that minted fence 1 again — so a
|
|
32
|
+
* worker stalled at fence 1 could write alongside the new holder, and the
|
|
33
|
+
* documented `finally { releaseRun() }` did it on every pass. Releasing here
|
|
34
|
+
* appends a tombstone rather than removing anything.
|
|
35
|
+
*
|
|
36
|
+
* **Unreadable content cannot wedge the run.** The fence is in the name, so a
|
|
37
|
+
* damaged or half-written body never hides the ordering. A caller reads the
|
|
38
|
+
* highest number and takes the next one; the previous holder, alive or not,
|
|
39
|
+
* is fenced out by arithmetic. Refusing to take an unparseable claim was safe
|
|
40
|
+
* against double-writing and left the run permanently unclaimable, which is
|
|
41
|
+
* the failure a lease exists to prevent.
|
|
42
|
+
*
|
|
43
|
+
* **The write-time fence check needs no parsing at all.** It compares a
|
|
44
|
+
* number against a directory listing, so a corrupt body cannot make the check
|
|
45
|
+
* skip itself.
|
|
46
|
+
*
|
|
47
|
+
* **No `rename` and no `unlink` on the contended path.** Renaming over a path
|
|
48
|
+
* another process merely holds open for reading fails on non-POSIX
|
|
49
|
+
* filesystems — measured at 84% under two concurrent readers — and a listing
|
|
50
|
+
* sweep reads exactly these files. Creating a new name never collides with a
|
|
51
|
+
* reader.
|
|
52
|
+
*
|
|
53
|
+
* ## The name appears already complete, because `link` publishes it
|
|
54
|
+
*
|
|
55
|
+
* An exclusive create decides the winner, but `wx` is open-THEN-write: for an
|
|
56
|
+
* instant the winning name exists and is empty. A reader landing in it parses
|
|
57
|
+
* nothing, reports the holding expired, and a second worker takes the next
|
|
58
|
+
* fence. Their fences differ so the loser's first checkpoint is refused — and
|
|
59
|
+
* both have already restored the run and executed its tools by then, and tool
|
|
60
|
+
* side effects are fenced by nothing.
|
|
61
|
+
*
|
|
62
|
+
* So the body is written to a temporary name first and the fence name is
|
|
63
|
+
* created by `link`ing to it. `link` fails `EEXIST` when the destination
|
|
64
|
+
* exists, so it arbitrates exactly as `wx` did, and the destination it creates
|
|
65
|
+
* is a second name for a file that was already whole. There is no instant at
|
|
66
|
+
* which the fence name exists and its body does not.
|
|
67
|
+
*
|
|
68
|
+
* Measured from separate OS processes on both platform families:
|
|
69
|
+
*
|
|
70
|
+
* - `link` refused an existing destination 20,000/20,000 times. Six writers
|
|
71
|
+
* over 6,000 fences produced no fence with two winners and none with none.
|
|
72
|
+
* - Paired identical fixtures: `wx` showed an empty destination in 15,985 of
|
|
73
|
+
* 16,000 first observations, `link` in 0 of 16,000. All 156,000 frontier
|
|
74
|
+
* observations were `ENOENT` or a complete parseable body — none empty, none
|
|
75
|
+
* torn.
|
|
76
|
+
* - `rename` is disqualified, and not for the reason first assumed. It never
|
|
77
|
+
* reports `EEXIST`; it silently REPLACES, 20,000/20,000. It cannot arbitrate
|
|
78
|
+
* a race at all — two workers publishing one fence would both succeed and
|
|
79
|
+
* the second would erase the first. (Its `EPERM`-under-readers failure is
|
|
80
|
+
* real too, at 93.7% on the non-POSIX family, but the exclusivity failure
|
|
81
|
+
* disqualifies it first.)
|
|
82
|
+
*
|
|
83
|
+
* Cost: three syscalls rather than one, +1.0 ms per acquisition on the
|
|
84
|
+
* non-POSIX family and +0.04 ms on POSIX, for an operation that runs once per
|
|
85
|
+
* run plus renewals.
|
|
86
|
+
*
|
|
87
|
+
* ## What it still does not do
|
|
88
|
+
*
|
|
89
|
+
* It does not detect liveness. Nothing can from here: a stalled holder, a
|
|
90
|
+
* suspended container and a partitioned network are indistinguishable, and
|
|
91
|
+
* they are indistinguishable from the holder's own side too, which is why it
|
|
92
|
+
* keeps writing. The fence is the answer — the write is checked, not the
|
|
93
|
+
* writer.
|
|
94
|
+
*/
|
|
95
|
+
import { link, mkdir, readFile, readdir, stat, unlink, writeFile } from 'node:fs/promises';
|
|
96
|
+
import { join } from 'node:path';
|
|
97
|
+
import { NamzuError } from '../../types/errors/index.js';
|
|
98
|
+
/** Directory holding one file per holding, named for its fence. */
|
|
99
|
+
const CLAIMS_DIR = 'claims';
|
|
100
|
+
/**
|
|
101
|
+
* How many times a caller re-reads and retries after losing the create race.
|
|
102
|
+
*
|
|
103
|
+
* Losing means somebody else took the number, and the next read sees their
|
|
104
|
+
* live claim and returns `null` — so this is bounded by genuine contention
|
|
105
|
+
* rather than by chance. A handful is generous; the loop exists so a burst of
|
|
106
|
+
* simultaneous takers does not report "held" to a caller that never actually
|
|
107
|
+
* raced the eventual holder.
|
|
108
|
+
*/
|
|
109
|
+
const MAX_ATTEMPTS = 8;
|
|
110
|
+
/**
|
|
111
|
+
* How many holdings to keep below the current fence.
|
|
112
|
+
*
|
|
113
|
+
* Append-only is right — a name that disappears can be re-issued — but
|
|
114
|
+
* unbounded is not, and every operation lists this directory. Measured: 0.14
|
|
115
|
+
* ms per operation at 10 holdings, 3.4 at 10,000, 78.6 at 200,000, and three
|
|
116
|
+
* processes contending on ONE run produced 4,772 files in eight seconds. A
|
|
117
|
+
* single holder renewing a 60-second lease produced 4,421. One busy run
|
|
118
|
+
* reaches the 78 ms regime in minutes and drags the checkpoint write path of
|
|
119
|
+
* every claimed run with it.
|
|
120
|
+
*
|
|
121
|
+
* Pruning BELOW the maximum is safe by the design own argument: a rewind
|
|
122
|
+
* requires removing the highest name, and nothing reads a lower one — the
|
|
123
|
+
* current holding is the maximum and the fence check compares against it. A
|
|
124
|
+
* few are kept rather than none so an operator can still see the recent
|
|
125
|
+
* handover history, which is the evidence a contested run is reconstructed
|
|
126
|
+
* from.
|
|
127
|
+
*/
|
|
128
|
+
const KEEP_BELOW_MAX = 32;
|
|
129
|
+
/**
|
|
130
|
+
* How old a scratch file must be before {@link prune} reclaims it.
|
|
131
|
+
*
|
|
132
|
+
* It brackets a `writeFile` of sixty-odd bytes and a `link`. Ten minutes is
|
|
133
|
+
* four orders of magnitude more than that takes, and the asymmetry is the
|
|
134
|
+
* point: reclaiming late costs a stale file until the next acquisition,
|
|
135
|
+
* reclaiming early fails a live publish that did nothing wrong.
|
|
136
|
+
*/
|
|
137
|
+
const TEMP_TTL_MS = 10 * 60_000;
|
|
138
|
+
function isErrno(err, code) {
|
|
139
|
+
return typeof err === 'object' && err !== null && err.code === code;
|
|
140
|
+
}
|
|
141
|
+
function isClaimBody(value) {
|
|
142
|
+
if (typeof value !== 'object' || value === null)
|
|
143
|
+
return false;
|
|
144
|
+
const c = value;
|
|
145
|
+
return (typeof c.holder === 'string' && typeof c.expiresAt === 'number' && Number.isFinite(c.expiresAt));
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* A holding's name: its fence, and nothing else.
|
|
149
|
+
*
|
|
150
|
+
* **The destination name must be a pure function of the fence.** Putting the
|
|
151
|
+
* expiry in it too was tried, to close the window where `wx` has created the
|
|
152
|
+
* file and not yet written its body — and it silently destroyed the exclusion
|
|
153
|
+
* this whole design rests on. Two workers computing the same fence at
|
|
154
|
+
* different instants produce different names, so both creates succeed and
|
|
155
|
+
* both hold fence N. The race test caught it immediately: seventeen of three
|
|
156
|
+
* hundred runs went to two or three workers.
|
|
157
|
+
*
|
|
158
|
+
* **The temporary name must be the exact opposite — unique per attempt.** See
|
|
159
|
+
* {@link tempNameFor}. The two rules are mirror images, and the pair is the
|
|
160
|
+
* insight: an exclusive create is exclusive over the *exact* name, so the name
|
|
161
|
+
* that has to arbitrate must not vary, and the name that must never arbitrate
|
|
162
|
+
* must never repeat.
|
|
163
|
+
*
|
|
164
|
+
* Strict decimal, bounded to fifteen digits. `Number` accepts `0x10`, `" 7"`,
|
|
165
|
+
* `08` and `1e21`, and above 2^53 or in exponent form `fence + 1 === fence` —
|
|
166
|
+
* so a foreign writer could pin the counter and every taker after it would be
|
|
167
|
+
* issued a fence EQUAL to the current one, which fences nobody out. Names
|
|
168
|
+
* this store issues always match; anything else is not a holding, however
|
|
169
|
+
* numeric it looks.
|
|
170
|
+
*/
|
|
171
|
+
const NAME = /^([0-9]{1,15})\.json$/;
|
|
172
|
+
function nameFor(fence) {
|
|
173
|
+
return `${fence}.json`;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The scratch name a body is written to before {@link publish} links it into
|
|
177
|
+
* place. Never a holding — the leading dot and the dashes cannot match
|
|
178
|
+
* {@link NAME}, so no listing can mistake one for a claim.
|
|
179
|
+
*/
|
|
180
|
+
const TEMP = /^\.tmp-/;
|
|
181
|
+
/** Distinguishes two attempts inside one process; the pid does the rest. */
|
|
182
|
+
let attempts = 0;
|
|
183
|
+
/**
|
|
184
|
+
* A scratch name: unique per attempt, and deliberately NOT a function of the
|
|
185
|
+
* fence.
|
|
186
|
+
*
|
|
187
|
+
* This is the mirror of the rule on {@link NAME}, and it was measured by
|
|
188
|
+
* building it wrong on purpose. A temp named for the fence — the obvious
|
|
189
|
+
* choice, since that is what is being published — fails **silently** on POSIX:
|
|
190
|
+
* two workers write the same scratch path, one links the other's body, and 19
|
|
191
|
+
* of 20,000 fences published a body belonging to a process that did not win
|
|
192
|
+
* that name. The ledger looked perfect throughout: right count, no doubles,
|
|
193
|
+
* none missing, every body parseable. Only reading a body back and comparing
|
|
194
|
+
* its holder reveals it. On the non-POSIX family the same mistake crashed
|
|
195
|
+
* three of six writer processes with `EPERM`.
|
|
196
|
+
*
|
|
197
|
+
* So: pid to separate processes, a counter to separate attempts within one,
|
|
198
|
+
* and randomness to separate processes that share a pid across a container
|
|
199
|
+
* restart or a pid-namespace reuse.
|
|
200
|
+
*
|
|
201
|
+
* The fence is on the end as well, and it is the one part carrying no
|
|
202
|
+
* uniqueness — it is there so an operator reading a leaked scratch file can
|
|
203
|
+
* tell which publish abandoned it. Uniqueness comes entirely from the three
|
|
204
|
+
* parts before it, which is what keeps this the mirror of {@link NAME} rather
|
|
205
|
+
* than a second copy of it. Anything appended for a human must stay in that
|
|
206
|
+
* position: informative, and load-bearing for nothing.
|
|
207
|
+
*
|
|
208
|
+
* **The scratch file must live in the same directory as its destination.**
|
|
209
|
+
* `link` across filesystems fails `EXDEV` — measured, not assumed — so a temp
|
|
210
|
+
* directory anywhere else (`os.tmpdir()` being the tempting one) breaks every
|
|
211
|
+
* acquisition the moment the store's base directory is a mount of its own.
|
|
212
|
+
* That is a rule, not a preference.
|
|
213
|
+
*/
|
|
214
|
+
function tempNameFor(fence) {
|
|
215
|
+
attempts += 1;
|
|
216
|
+
return `.tmp-${process.pid}-${attempts}-${Math.random().toString(36).slice(2, 10)}-${fence}`;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Codes a filesystem with no hard-link support answers `link` with.
|
|
220
|
+
*
|
|
221
|
+
* `EXDEV` is in the list as a bug report rather than a platform limit: it can
|
|
222
|
+
* only mean the scratch file was moved out of the claims directory, against
|
|
223
|
+
* the rule on {@link tempNameFor}.
|
|
224
|
+
*/
|
|
225
|
+
const NO_LINK = new Set(['EPERM', 'ENOTSUP', 'EOPNOTSUPP', 'ENOSYS', 'EXDEV', 'EMLINK']);
|
|
226
|
+
/**
|
|
227
|
+
* Write `body` and make it visible at `fence` — completely, or not at all.
|
|
228
|
+
*
|
|
229
|
+
* Throws an `EEXIST` `ErrnoException` when another caller already published
|
|
230
|
+
* that fence. That is the arbitration, and it is the caller's ordinary signal,
|
|
231
|
+
* not a fault.
|
|
232
|
+
*
|
|
233
|
+
* Some filesystems — a few network and removable volumes — support no hard
|
|
234
|
+
* link at all. **This refuses rather than falling back**, per
|
|
235
|
+
* [refuse-do-not-degrade](../../../../../docs/conventions/refuse-do-not-degrade.md).
|
|
236
|
+
* The only available fallback is the `wx` publish this replaced, and that one
|
|
237
|
+
* carries the defect described in the module header: two workers restore and
|
|
238
|
+
* run the same run. A claim that silently becomes non-exclusive is worse than
|
|
239
|
+
* one that will not start, because the host cannot tell which it got — and a
|
|
240
|
+
* host told plainly that this volume cannot arbitrate can move the base
|
|
241
|
+
* directory or keep one writer per run. It is unmeasured, because no such
|
|
242
|
+
* volume was available to measure; the error says so rather than implying a
|
|
243
|
+
* diagnosis it did not make.
|
|
244
|
+
*/
|
|
245
|
+
async function publish(claimsDir, fence, body) {
|
|
246
|
+
const tmp = join(claimsDir, tempNameFor(fence));
|
|
247
|
+
try {
|
|
248
|
+
await writeFile(tmp, JSON.stringify(body), { flag: 'wx' });
|
|
249
|
+
}
|
|
250
|
+
catch (err) {
|
|
251
|
+
// A scratch name that already exists means the uniqueness rule on
|
|
252
|
+
// `tempNameFor` has been broken. Letting an `EEXIST` escape from HERE
|
|
253
|
+
// would read to the caller as "somebody else took this fence" — a lost
|
|
254
|
+
// race it never had — so it is renamed into what it actually is.
|
|
255
|
+
if (isErrno(err, 'EEXIST')) {
|
|
256
|
+
throw new NamzuError({
|
|
257
|
+
code: 'storage_error',
|
|
258
|
+
message: `acquireClaim: the scratch name ${tmp} already exists. Scratch names must be unique per attempt; a collision means two publishes are sharing one, which lets a claim publish a body it did not write. See the rule on \`tempNameFor\`.`,
|
|
259
|
+
details: { path: tmp, fence },
|
|
260
|
+
retryable: false,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// Anything else — no permission on the directory, a full disk, a
|
|
264
|
+
// read-only mount — escapes as a bare errno naming a dotted temporary
|
|
265
|
+
// file, with nothing in it about claims or runs. This write is the
|
|
266
|
+
// first thing that touches the directory, so it is where a
|
|
267
|
+
// misconfigured deployment surfaces, and `EPERM: open
|
|
268
|
+
// '…/.tmp-4131-2-k3f9a1x8-1'` is the least useful place to find out.
|
|
269
|
+
//
|
|
270
|
+
// Wrapped for the same reason as the `link` failure below it: the
|
|
271
|
+
// operator needs the run, the directory and the operation, not the
|
|
272
|
+
// scratch name this attempt happened to draw.
|
|
273
|
+
throw new NamzuError({
|
|
274
|
+
code: 'storage_error',
|
|
275
|
+
message: `acquireClaim: could not write a claim into ${claimsDir} (${err.code ?? 'unknown error'}). This is the run's claim directory, and taking a run writes to it — check that the process can create files there. Refusing rather than proceeding: a claim that cannot be recorded is a claim nobody else can be refused against.`,
|
|
276
|
+
details: { path: claimsDir, code: err.code, fence },
|
|
277
|
+
cause: err,
|
|
278
|
+
retryable: false,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
try {
|
|
282
|
+
// The one decision. Exactly one caller creates this name, and the file
|
|
283
|
+
// it names is already whole.
|
|
284
|
+
await link(tmp, join(claimsDir, nameFor(fence)));
|
|
285
|
+
}
|
|
286
|
+
catch (err) {
|
|
287
|
+
if (isErrno(err, 'EEXIST'))
|
|
288
|
+
throw err;
|
|
289
|
+
const code = err.code;
|
|
290
|
+
if (code !== undefined && NO_LINK.has(code)) {
|
|
291
|
+
throw new NamzuError({
|
|
292
|
+
code: 'capability_unavailable',
|
|
293
|
+
message: `acquireClaim: this filesystem answered \`link\` with ${code}, so it cannot publish a run claim. The claim decides which of two workers owns a run by exclusively creating a hard link, and a filesystem without hard links cannot make that decision. Refusing rather than degrading: the only fallback is a non-atomic create, under which two workers both restore the run and both execute its tools with nothing fencing the side effects. Put the store's base directory on a filesystem with hard-link support (${claimsDir}), or run a single writer per run.`,
|
|
294
|
+
details: { path: claimsDir, code, fence },
|
|
295
|
+
retryable: false,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
throw err;
|
|
299
|
+
}
|
|
300
|
+
finally {
|
|
301
|
+
// The link, if it landed, is an independent name for the same file.
|
|
302
|
+
// Failure here leaks a scratch file and nothing else; `prune` sweeps
|
|
303
|
+
// it, and no listing can mistake it for a holding.
|
|
304
|
+
await unlink(tmp).catch(() => undefined);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Every holding this run has on record, newest first.
|
|
309
|
+
*
|
|
310
|
+
* Names only — no expiry. It used to report `expiresAt: 0` alongside each
|
|
311
|
+
* name, which read as data and was a placeholder: the expiry has never been in
|
|
312
|
+
* the name since the fence became the whole of it. A caller that wants a
|
|
313
|
+
* deadline has to read the body, and {@link readClaim} is the only thing that
|
|
314
|
+
* does.
|
|
315
|
+
*/
|
|
316
|
+
async function listHoldings(runDir) {
|
|
317
|
+
let names;
|
|
318
|
+
try {
|
|
319
|
+
names = await readdir(join(runDir, CLAIMS_DIR));
|
|
320
|
+
}
|
|
321
|
+
catch (err) {
|
|
322
|
+
if (isErrno(err, 'ENOENT'))
|
|
323
|
+
return [];
|
|
324
|
+
throw err;
|
|
325
|
+
}
|
|
326
|
+
const found = [];
|
|
327
|
+
for (const name of names) {
|
|
328
|
+
const match = NAME.exec(name);
|
|
329
|
+
if (!match)
|
|
330
|
+
continue;
|
|
331
|
+
found.push({ name, fence: Number(match[1]) });
|
|
332
|
+
}
|
|
333
|
+
return found.sort((a, b) => b.fence - a.fence);
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* The highest fence ever issued for this run, or 0 when it has never been
|
|
337
|
+
* claimed.
|
|
338
|
+
*
|
|
339
|
+
* Reads names only. This is deliberately the one question the contended path
|
|
340
|
+
* asks, because a name cannot be half-written: a file either exists or does
|
|
341
|
+
* not, where a body can be observed mid-write.
|
|
342
|
+
*/
|
|
343
|
+
export async function currentFence(runDir) {
|
|
344
|
+
const holdings = await listHoldings(runDir);
|
|
345
|
+
return holdings[0]?.fence ?? 0;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Drop holdings far below the current fence.
|
|
349
|
+
*
|
|
350
|
+
* Only ever below the maximum. A rewind requires removing the HIGHEST name,
|
|
351
|
+
* and nothing reads a lower one — the current holding is the maximum and the
|
|
352
|
+
* write check compares against it — so this cannot re-issue a number. A
|
|
353
|
+
* window of recent handovers is kept, because that is the evidence a
|
|
354
|
+
* contested run gets reconstructed from.
|
|
355
|
+
*
|
|
356
|
+
* Failures are swallowed: pruning is housekeeping, and a run must not fail
|
|
357
|
+
* because a tidy-up lost a race with another worker doing the same tidy-up.
|
|
358
|
+
*/
|
|
359
|
+
async function prune(claimsDir, max) {
|
|
360
|
+
let names;
|
|
361
|
+
try {
|
|
362
|
+
names = await readdir(claimsDir);
|
|
363
|
+
}
|
|
364
|
+
catch {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const floor = max - KEEP_BELOW_MAX;
|
|
368
|
+
// Real time, deliberately, and not the caller's `now`. A lease clock is
|
|
369
|
+
// injectable so a test can age a claim out in one tick; the age of a file
|
|
370
|
+
// on disk is a question about the wall clock, and judging one with the
|
|
371
|
+
// other would let a test with `now: 1000` sweep every scratch file on the
|
|
372
|
+
// volume.
|
|
373
|
+
const wallClock = Date.now();
|
|
374
|
+
for (const name of names) {
|
|
375
|
+
const match = NAME.exec(name);
|
|
376
|
+
if (match) {
|
|
377
|
+
if (floor <= 0)
|
|
378
|
+
continue;
|
|
379
|
+
if (Number(match[1]) >= floor)
|
|
380
|
+
continue;
|
|
381
|
+
await unlink(join(claimsDir, name)).catch(() => undefined);
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
if (!TEMP.test(name))
|
|
385
|
+
continue;
|
|
386
|
+
// A crash between the scratch write and its unlink leaves one behind.
|
|
387
|
+
// It can never be read as a holding — the name cannot match `NAME` —
|
|
388
|
+
// but nothing reclaimed it either, so a run whose worker crashes in
|
|
389
|
+
// that window accumulated scratch files forever.
|
|
390
|
+
//
|
|
391
|
+
// By age, because ownership is unknowable: another process may be
|
|
392
|
+
// publishing through this very file right now, and unlinking it would
|
|
393
|
+
// fail its `link` for no reason. The threshold is enormous relative to
|
|
394
|
+
// the work it brackets — a `writeFile` of sixty-odd bytes followed by a
|
|
395
|
+
// `link` — so a scratch file this old belongs to a process that is not
|
|
396
|
+
// coming back.
|
|
397
|
+
const path = join(claimsDir, name);
|
|
398
|
+
try {
|
|
399
|
+
const info = await stat(path);
|
|
400
|
+
if (wallClock - info.mtimeMs < TEMP_TTL_MS)
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
await unlink(path).catch(() => undefined);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* The run's current holding, or `null` when it has never been claimed.
|
|
411
|
+
*
|
|
412
|
+
* Returns `null` for an unreadable body too, and that is safe HERE in a way
|
|
413
|
+
* it was not in the previous design: the fence is known from the name
|
|
414
|
+
* regardless, so an unreadable body means "somebody took this number and its
|
|
415
|
+
* details are unavailable", and the caller's response is to take the NEXT
|
|
416
|
+
* number rather than to give up. Nothing is inferred from the absence.
|
|
417
|
+
*/
|
|
418
|
+
export async function readClaim(runDir) {
|
|
419
|
+
const [top] = await listHoldings(runDir);
|
|
420
|
+
if (!top)
|
|
421
|
+
return null;
|
|
422
|
+
// Fence from the name, expiry only from the body — and an expiry of 0 says
|
|
423
|
+
// "no deadline could be established", which every caller reads as expired.
|
|
424
|
+
//
|
|
425
|
+
// This comment used to claim the expiry came from the name too, and was
|
|
426
|
+
// therefore known the instant the file existed. It was stale by a
|
|
427
|
+
// redesign, and it described the file's one real defect as handled: under
|
|
428
|
+
// the old `wx` publish a reader could land on a created-but-empty file,
|
|
429
|
+
// fail to parse it, and report a LIVE holding expired — which invited a
|
|
430
|
+
// second worker onto a running run. Both restored it and executed its
|
|
431
|
+
// tools before either was refused at its first checkpoint.
|
|
432
|
+
//
|
|
433
|
+
// What makes falling back safe now is the publish, not the naming: `link`
|
|
434
|
+
// makes the fence name appear complete or not at all, so an unparseable
|
|
435
|
+
// body means a genuinely damaged record rather than one being written. A
|
|
436
|
+
// damaged record SHOULD read as reclaimable — refusing to take it is what
|
|
437
|
+
// leaves a run permanently unclaimable, which is the failure a lease
|
|
438
|
+
// exists to prevent — and the taker is safe regardless, because it takes
|
|
439
|
+
// the next fence and the write check compares numbers.
|
|
440
|
+
const claim = { holder: '', fence: top.fence, expiresAt: 0 };
|
|
441
|
+
let raw;
|
|
442
|
+
try {
|
|
443
|
+
raw = await readFile(join(runDir, CLAIMS_DIR, top.name), 'utf-8');
|
|
444
|
+
}
|
|
445
|
+
catch (err) {
|
|
446
|
+
// Gone between the listing and the read. The name already told us
|
|
447
|
+
// everything the taker needs.
|
|
448
|
+
//
|
|
449
|
+
// Only `ENOENT` is tolerated, and on the non-POSIX family that is not
|
|
450
|
+
// the only code a vanishing file produces: a file already unlinked but
|
|
451
|
+
// still open elsewhere is delete-pending, and a reader gets `EPERM` —
|
|
452
|
+
// 4.6% of misses, measured. It cannot be reached from here today,
|
|
453
|
+
// because `prune` only unlinks fences far below the top and this reads
|
|
454
|
+
// only the top. Widen either one and this throws where it should
|
|
455
|
+
// return. Whoever does that should extend this catch, not delete the
|
|
456
|
+
// comment.
|
|
457
|
+
if (isErrno(err, 'ENOENT'))
|
|
458
|
+
return claim;
|
|
459
|
+
throw err;
|
|
460
|
+
}
|
|
461
|
+
try {
|
|
462
|
+
const parsed = JSON.parse(raw);
|
|
463
|
+
// The body is advisory now — it names the holder for an operator and
|
|
464
|
+
// distinguishes a clean release from a damaged record. The two facts
|
|
465
|
+
// the algorithm depends on are both in the name.
|
|
466
|
+
if (isClaimBody(parsed)) {
|
|
467
|
+
return {
|
|
468
|
+
holder: parsed.holder,
|
|
469
|
+
fence: top.fence,
|
|
470
|
+
expiresAt: parsed.expiresAt,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
catch {
|
|
475
|
+
// fall through: an unreadable body leaves the holding intact and
|
|
476
|
+
// anonymous, which is what `holder: ''` says.
|
|
477
|
+
}
|
|
478
|
+
return claim;
|
|
479
|
+
}
|
|
480
|
+
/** Take or extend the run's claim. `null` when somebody else holds it. */
|
|
481
|
+
export async function acquireClaim(runDir, options) {
|
|
482
|
+
const now = options.now ?? Date.now();
|
|
483
|
+
const claimsDir = join(runDir, CLAIMS_DIR);
|
|
484
|
+
await mkdir(claimsDir, { recursive: true });
|
|
485
|
+
for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
|
|
486
|
+
const held = await readClaim(runDir);
|
|
487
|
+
// Held, live, and by somebody else. Not an error: two readers on one
|
|
488
|
+
// queue is the ordinary case.
|
|
489
|
+
if (held && now < held.expiresAt && held.holder !== options.holder)
|
|
490
|
+
return null;
|
|
491
|
+
const fence = (held?.fence ?? 0) + 1;
|
|
492
|
+
const body = {
|
|
493
|
+
holder: options.holder,
|
|
494
|
+
expiresAt: now + options.ttlMs,
|
|
495
|
+
};
|
|
496
|
+
try {
|
|
497
|
+
// One name, one winner, and the winner's body is already whole
|
|
498
|
+
// when the name appears. The expiry lives only in the body; see
|
|
499
|
+
// the note on NAME for why it must not appear in the name.
|
|
500
|
+
await publish(claimsDir, fence, body);
|
|
501
|
+
await prune(claimsDir, fence);
|
|
502
|
+
return { holder: options.holder, fence, expiresAt: body.expiresAt };
|
|
503
|
+
}
|
|
504
|
+
catch (err) {
|
|
505
|
+
// Somebody else took this number. Re-read and decide again — they
|
|
506
|
+
// may hold it live, in which case the next pass returns `null`.
|
|
507
|
+
if (!isErrno(err, 'EEXIST'))
|
|
508
|
+
throw err;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
// Lost the create race MAX_ATTEMPTS times without ever reading a live
|
|
512
|
+
// holder. Reporting "held" is the honest answer: something is taking this
|
|
513
|
+
// run repeatedly and this caller is not winning.
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Give up a holding early, so the run returns to the queue without waiting
|
|
518
|
+
* out its lease.
|
|
519
|
+
*
|
|
520
|
+
* Appends a tombstone at the next fence rather than deleting anything. The
|
|
521
|
+
* counter must never rewind: a worker stalled at an old fence has to stay
|
|
522
|
+
* fenced out forever, and removing the record would let a later claimer be
|
|
523
|
+
* issued a number that stalled worker already believes it holds.
|
|
524
|
+
*
|
|
525
|
+
* A stale fence releases nothing — a worker that stalled past its lease must
|
|
526
|
+
* not be able to hand away a run somebody else now holds.
|
|
527
|
+
*/
|
|
528
|
+
export async function releaseClaim(runDir, fence) {
|
|
529
|
+
const held = await readClaim(runDir);
|
|
530
|
+
if (!held || held.fence !== fence)
|
|
531
|
+
return;
|
|
532
|
+
const claimsDir = join(runDir, CLAIMS_DIR);
|
|
533
|
+
// Expiry 0 and no holder: free the instant it lands. That pair IS the
|
|
534
|
+
// tombstone — an empty holder with a zero expiry is not a shape a live
|
|
535
|
+
// claim can take, so it reads as a clean handover to anyone looking at the
|
|
536
|
+
// directory, without a flag no caller consumes. See {@link ClaimBody}.
|
|
537
|
+
//
|
|
538
|
+
// Published the same way as a claim, so nothing can catch it half-written.
|
|
539
|
+
const body = { holder: '', expiresAt: 0 };
|
|
540
|
+
try {
|
|
541
|
+
await publish(claimsDir, fence + 1, body);
|
|
542
|
+
}
|
|
543
|
+
catch (err) {
|
|
544
|
+
// Somebody already took the next fence, which means the run is claimed
|
|
545
|
+
// again and there is nothing to release.
|
|
546
|
+
if (!isErrno(err, 'EEXIST'))
|
|
547
|
+
throw err;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
//# sourceMappingURL=claim-disk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-disk.js","sourceRoot":"","sources":["../../../src/store/run/claim-disk.ts"],"names":[],"mappings":"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"}
|
package/dist/store/run/disk.d.ts
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import type { CheckpointId, IterationCheckpoint } from '../../types/hitl/index.js';
|
|
2
2
|
import type { Run, RunEvent, RunStoreConfig } from '../../types/run/index.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
import type { CompletedToolRecord, RunStore } from '../../types/run/store.js';
|
|
4
|
+
/**
|
|
5
|
+
* One finished tool call, recovered from the transcript.
|
|
6
|
+
*
|
|
7
|
+
* Re-exported from the store contract rather than declared twice. Two
|
|
8
|
+
* declarations of one concept, each populated by its own mapper, is the shape
|
|
9
|
+
* this repository has a rule about.
|
|
10
|
+
*/
|
|
11
|
+
export type { CompletedToolRecord };
|
|
12
|
+
export declare class RunDiskStore implements RunStore {
|
|
11
13
|
private baseDir;
|
|
12
14
|
private runDir;
|
|
13
15
|
private log;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;
|
|
1
|
+
{"version":3,"file":"disk.d.ts","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAA;AAClF,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAe7E;;;;;;GAMG;AACH,YAAY,EAAE,mBAAmB,EAAE,CAAA;AAEnC,qBAAa,YAAa,YAAW,QAAQ;IAC5C,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,SAAS,CAAmC;gBAExC,MAAM,EAAE,cAAc;IAKlC,OAAO,CAAC,WAAW;IAOb,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAW7D,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAWjD;;;;;;;;;;;;;;OAcG;IACG,kBAAkB,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IA0C/D,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BrC,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtC,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASnD,SAAS,IAAI,MAAM,GAAG,IAAI;IAIpB,eAAe,CAAC,UAAU,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAc/D,cAAc,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAW/E,eAAe,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;IAIjD,gBAAgB,CAAC,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IASjE;;;;;;;;;;;;;;;;;;;;;;OAsBG;WACU,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAC9C,KAAK,CAAC;QACL,EAAE,EAAE,MAAM,CAAA;QACV,SAAS,EAAE,MAAM,CAAA;QACjB,MAAM,EAAE,MAAM,CAAA;QACd,SAAS,EAAE,MAAM,CAAA;QACjB,OAAO,CAAC,EAAE,MAAM,CAAA;KAChB,CAAC,CACF;IAWK,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CA8CzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAiBtF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"disk.js","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"disk.js","sourceRoot":"","sources":["../../../src/store/run/disk.ts"],"names":[],"mappings":"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"}
|