@apexops/kernel 0.10.0-next.5 → 0.11.0-next.1
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/dist/.tsbuildinfo +1 -1
- package/dist/directory-lock.d.ts +118 -0
- package/dist/directory-lock.d.ts.map +1 -0
- package/dist/directory-lock.js +587 -0
- package/dist/directory-lock.js.map +1 -0
- package/dist/files.d.ts +63 -0
- package/dist/files.d.ts.map +1 -1
- package/dist/files.js +158 -2
- package/dist/files.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/object-store.js +2 -2
- package/dist/object-store.js.map +1 -1
- package/dist/project-store.d.ts +2 -1
- package/dist/project-store.d.ts.map +1 -1
- package/dist/project-store.js +1 -0
- package/dist/project-store.js.map +1 -1
- package/dist/repeat-files.d.ts +66 -0
- package/dist/repeat-files.d.ts.map +1 -0
- package/dist/repeat-files.js +214 -0
- package/dist/repeat-files.js.map +1 -0
- package/dist/repeat-guard.d.ts +197 -0
- package/dist/repeat-guard.d.ts.map +1 -0
- package/dist/repeat-guard.js +462 -0
- package/dist/repeat-guard.js.map +1 -0
- package/dist/review-capture.d.ts +170 -0
- package/dist/review-capture.d.ts.map +1 -0
- package/dist/review-capture.js +570 -0
- package/dist/review-capture.js.map +1 -0
- package/dist/run-repository.d.ts +52 -2
- package/dist/run-repository.d.ts.map +1 -1
- package/dist/run-repository.js +198 -52
- package/dist/run-repository.js.map +1 -1
- package/dist/tasks.d.ts.map +1 -1
- package/dist/tasks.js +16 -2
- package/dist/tasks.js.map +1 -1
- package/dist/test/files.test.d.ts +2 -0
- package/dist/test/files.test.d.ts.map +1 -0
- package/dist/test/files.test.js +140 -0
- package/dist/test/files.test.js.map +1 -0
- package/dist/test/policies.test.js +1 -1
- package/dist/test/policies.test.js.map +1 -1
- package/dist/test/repeat-guard.test.d.ts +2 -0
- package/dist/test/repeat-guard.test.d.ts.map +1 -0
- package/dist/test/repeat-guard.test.js +1106 -0
- package/dist/test/repeat-guard.test.js.map +1 -0
- package/dist/test/review-capture.test.d.ts +2 -0
- package/dist/test/review-capture.test.d.ts.map +1 -0
- package/dist/test/review-capture.test.js +291 -0
- package/dist/test/review-capture.test.js.map +1 -0
- package/dist/test/run-repository.test.js +451 -7
- package/dist/test/run-repository.test.js.map +1 -1
- package/dist/test/workflow.test.js +30 -1
- package/dist/test/workflow.test.js.map +1 -1
- package/dist/test/writer-transfer.test.js +6 -1
- package/dist/test/writer-transfer.test.js.map +1 -1
- package/dist/validator-registry.d.ts.map +1 -1
- package/dist/validator-registry.js +10 -1
- package/dist/validator-registry.js.map +1 -1
- package/dist/workflow-validator-ownership.d.ts.map +1 -1
- package/dist/workflow-validator-ownership.js +2 -1
- package/dist/workflow-validator-ownership.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A share window could not be closed, so snapshot readers may still trust it. The hold refuses to share again; its
|
|
3
|
+
* holder must write nothing more before it releases the lock, which takes the window with it.
|
|
4
|
+
*/
|
|
5
|
+
export declare class DirectoryLockShareCloseError extends Error {
|
|
6
|
+
constructor(label: string, cause: unknown);
|
|
7
|
+
}
|
|
8
|
+
/** One acquisition of a {@link DirectoryLock}. */
|
|
9
|
+
export interface DirectoryLockHold {
|
|
10
|
+
/** Gives the lock up. Idempotent. */
|
|
11
|
+
release(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Runs `operation` with this generation open to {@link DirectoryLock.readShared} snapshot readers, for example while
|
|
14
|
+
* the holder waits for an external process. The lock stays held, so other holders still wait. The holder must not
|
|
15
|
+
* write the state the lock protects until `operation` settles: the window closes before `share` returns, and closing
|
|
16
|
+
* it is what invalidates a snapshot read that overlapped it. Concurrent calls run their operations in one window,
|
|
17
|
+
* which closes when the last of them settles, and none returns before it closed. A call made inside a shared
|
|
18
|
+
* operation runs in the enclosing window and returns into that operation, which must still not write. When the
|
|
19
|
+
* window cannot be closed `share` throws {@link DirectoryLockShareCloseError},
|
|
20
|
+
* then and on every later call; the holder must then stop writing until it releases the lock.
|
|
21
|
+
*/
|
|
22
|
+
share<T>(operation: () => Promise<T>): Promise<T>;
|
|
23
|
+
}
|
|
24
|
+
export interface DirectoryLockOptions {
|
|
25
|
+
/** Prefix of metadata error messages, for example "Run mutation lock". */
|
|
26
|
+
label: string;
|
|
27
|
+
clock: () => Date;
|
|
28
|
+
idSource: () => string;
|
|
29
|
+
/** A generation is only taken over once it has expired and its local owner process is gone. */
|
|
30
|
+
ttlMs: number;
|
|
31
|
+
/** Selects Windows transient file-sharing handling. */
|
|
32
|
+
platform: NodeJS.Platform;
|
|
33
|
+
busyError: () => Error;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Cross-process exclusive lock published as a directory `<name>.lock` holding owner metadata. A generation is staged
|
|
37
|
+
* in `<name>.pending-*` and published by rename, so the lock path never holds partial metadata. A live owner is waited
|
|
38
|
+
* for; an expired generation whose local owner process is gone is taken over into a permanent tombstone under
|
|
39
|
+
* `<name>.retired/`, which makes takeover compare-and-swap; released generations are parked there and deleted.
|
|
40
|
+
*/
|
|
41
|
+
export declare class DirectoryLock {
|
|
42
|
+
private readonly lockPath;
|
|
43
|
+
private readonly retiredLockPath;
|
|
44
|
+
private readonly stagingPrefix;
|
|
45
|
+
private readonly label;
|
|
46
|
+
private readonly clock;
|
|
47
|
+
private readonly idSource;
|
|
48
|
+
private readonly ttlMs;
|
|
49
|
+
private readonly platform;
|
|
50
|
+
private readonly busyError;
|
|
51
|
+
constructor(lockPath: string, options: DirectoryLockOptions);
|
|
52
|
+
/** Runs `operation` while holding the lock; throws the configured busy error when it cannot be acquired in time. */
|
|
53
|
+
run<T>(operation: () => Promise<T>, options?: {
|
|
54
|
+
onContention?: () => Promise<Error | undefined>;
|
|
55
|
+
waitMs?: number;
|
|
56
|
+
}): Promise<T>;
|
|
57
|
+
/**
|
|
58
|
+
* Acquires the lock and returns its release, for holders that give the lock up and take it again while they run.
|
|
59
|
+
* Throws the configured busy error when it cannot be acquired in time. Release is idempotent.
|
|
60
|
+
*/
|
|
61
|
+
acquire(options?: {
|
|
62
|
+
onContention?: () => Promise<Error | undefined>;
|
|
63
|
+
waitMs?: number;
|
|
64
|
+
}): Promise<DirectoryLockHold>;
|
|
65
|
+
/**
|
|
66
|
+
* Runs `read` without the lock while a holder shares its generation (see {@link DirectoryLockHold.share}) and returns
|
|
67
|
+
* its outcome only when the same window was still open after `read` settled, so the holder wrote nothing meanwhile.
|
|
68
|
+
* Returns undefined, discarding the outcome, when no window was open or it closed during the read; the caller then
|
|
69
|
+
* retries or waits for the lock. `read` must not write the state the lock protects.
|
|
70
|
+
*/
|
|
71
|
+
readShared<T>(read: () => Promise<T>): Promise<{
|
|
72
|
+
value: T;
|
|
73
|
+
} | undefined>;
|
|
74
|
+
private openShare;
|
|
75
|
+
private closeShare;
|
|
76
|
+
/**
|
|
77
|
+
* Identity of the open share window: the holding generation's token and the window id, or undefined when there is no
|
|
78
|
+
* readable window. Any failure to read it counts as no window, so a reader falls back to the lock.
|
|
79
|
+
*/
|
|
80
|
+
private shareWindow;
|
|
81
|
+
private acquireLock;
|
|
82
|
+
/** Cheap pre-check so contended waiters do not stage and fsync lock metadata on every poll. */
|
|
83
|
+
private lockPublished;
|
|
84
|
+
private readLock;
|
|
85
|
+
private ownerMayBeAlive;
|
|
86
|
+
/**
|
|
87
|
+
* Take over an expired generation whose local owner was confirmed dead after `snapshot` was read. Re-reading the lock
|
|
88
|
+
* after that liveness check is what lets released generations skip tombstones: a generation still present after its
|
|
89
|
+
* owner died can no longer be released by that owner, so it can only leave the lock path through another takeover,
|
|
90
|
+
* which leaves the permanent tombstone that makes this rename fail instead of retiring a replacement generation.
|
|
91
|
+
*/
|
|
92
|
+
private retireStaleLock;
|
|
93
|
+
/**
|
|
94
|
+
* Retire a taken-over generation into a permanent tombstone named by its recovery id. Rename is not compare-and-swap,
|
|
95
|
+
* so the tombstone is the guard: a delayed contender that confirmed the same generation renames onto the existing
|
|
96
|
+
* non-empty tombstone and fails rather than moving a replacement lock. Tombstones are therefore never swept; they
|
|
97
|
+
* accumulate only once per crashed lock owner, not per mutation.
|
|
98
|
+
*/
|
|
99
|
+
private retireLock;
|
|
100
|
+
/**
|
|
101
|
+
* Release a generation this process owns. While the owner is alive no contender can take its generation over (see
|
|
102
|
+
* `retireStaleLock`), so the rename moves exactly this generation and needs no tombstone: it is parked under a fresh
|
|
103
|
+
* unique name and deleted by `sweepReleasedLocks`.
|
|
104
|
+
*/
|
|
105
|
+
private releaseLock;
|
|
106
|
+
private ensureRetiredRoot;
|
|
107
|
+
/**
|
|
108
|
+
* Best-effort deletion of every released generation, including ones left by earlier cleanup failures or crashes
|
|
109
|
+
* between release and deletion. Any process may delete any released entry at any time: each has a unique name that
|
|
110
|
+
* only its releasing owner ever renames to, and nothing reads, renames, or locks through it afterwards. Takeover
|
|
111
|
+
* tombstones, the live lock, and other processes' `.pending-` staging directories are never touched. Failures never
|
|
112
|
+
* fail the caller; Windows sharing violations (for example a contender's metadata handle still open) are retried
|
|
113
|
+
* briefly and otherwise left for the next sweep.
|
|
114
|
+
*/
|
|
115
|
+
private sweepReleasedLocks;
|
|
116
|
+
private removeReleasedLock;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=directory-lock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directory-lock.d.ts","sourceRoot":"","sources":["../src/directory-lock.ts"],"names":[],"mappings":"AAgCA;;;GAGG;AACH,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,YAAY,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAGxC;CACF;AASD,kDAAkD;AAClD,MAAM,WAAW,iBAAiB;IAChC,qCAAqC;IACrC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB;;;;;;;;;OASG;IACH,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACnD;AAQD,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,IAAI,CAAC;IAClB,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,+FAA+F;IAC/F,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC1B,SAAS,EAAE,MAAM,KAAK,CAAC;CACxB;AAwBD;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IAExC,YAAY,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,oBAAoB,EAY1D;IAED,oHAAoH;IAC9G,GAAG,CAAC,CAAC,EACT,SAAS,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAC3B,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GACjF,OAAO,CAAC,CAAC,CAAC,CAOZ;IAED;;;OAGG;IACG,OAAO,CACX,OAAO,GAAE;QAAE,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAO,GACjF,OAAO,CAAC,iBAAiB,CAAC,CA0G5B;IAED;;;;;OAKG;IACG,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,CAAC,CAAA;KAAE,GAAG,SAAS,CAAC,CAY7E;YAEa,SAAS;YAmBT,UAAU;IAcxB;;;OAGG;YACW,WAAW;YAoCX,WAAW;IAuCzB,+FAA+F;YACjF,aAAa;YAUb,QAAQ;IAgGtB,OAAO,CAAC,eAAe;IAUvB;;;;;OAKG;YACW,eAAe;IAM7B;;;;;OAKG;YACW,UAAU;IAYxB;;;;OAIG;YACW,WAAW;YAKX,iBAAiB;IAQ/B;;;;;;;OAOG;YACW,kBAAkB;YAgBlB,kBAAkB;CAajC"}
|