@openclaw/fs-safe 0.14.0 → 0.16.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 +88 -0
- package/README.md +38 -10
- package/dist/advanced.d.ts +2 -1
- package/dist/advanced.d.ts.map +1 -1
- package/dist/advanced.js +2 -1
- package/dist/archive-kind.d.ts +0 -1
- package/dist/archive-kind.d.ts.map +1 -1
- package/dist/archive-kind.js +5 -17
- package/dist/archive-merge.d.ts.map +1 -1
- package/dist/archive-merge.js +113 -46
- package/dist/archive-parser.wasm +0 -0
- package/dist/archive-read.d.ts.map +1 -1
- package/dist/archive-read.js +10 -11
- package/dist/archive-tar-stream.d.ts +3 -0
- package/dist/archive-tar-stream.d.ts.map +1 -1
- package/dist/archive-tar-stream.js +56 -37
- package/dist/archive-tar-wasm.d.ts +16 -4
- package/dist/archive-tar-wasm.d.ts.map +1 -1
- package/dist/archive-tar-wasm.js +134 -34
- package/dist/archive-zip-directory.d.ts +4 -0
- package/dist/archive-zip-directory.d.ts.map +1 -1
- package/dist/archive-zip-directory.js +2 -0
- package/dist/archive-zip-entry.d.ts +6 -2
- package/dist/archive-zip-entry.d.ts.map +1 -1
- package/dist/archive-zip-entry.js +23 -8
- package/dist/archive-zip-integrity.d.ts.map +1 -1
- package/dist/archive-zip-integrity.js +3 -4
- package/dist/archive-zip-loader.d.ts.map +1 -1
- package/dist/archive-zip-loader.js +107 -31
- package/dist/archive-zip-names.d.ts +1 -0
- package/dist/archive-zip-names.d.ts.map +1 -1
- package/dist/archive-zip-names.js +6 -0
- package/dist/archive.d.ts.map +1 -1
- package/dist/archive.js +11 -11
- package/dist/bounded-read-stream.d.ts +0 -1
- package/dist/bounded-read-stream.d.ts.map +1 -1
- package/dist/bounded-read-stream.js +0 -6
- package/dist/clone-metadata.d.ts +1 -0
- package/dist/clone-metadata.d.ts.map +1 -1
- package/dist/clone-metadata.js +6 -2
- package/dist/copy-publication.d.ts +6 -0
- package/dist/copy-publication.d.ts.map +1 -1
- package/dist/copy-publication.js +3 -0
- package/dist/copy-tree-portable.d.ts.map +1 -1
- package/dist/copy-tree-portable.js +44 -24
- package/dist/copy.d.ts.map +1 -1
- package/dist/copy.js +29 -11
- package/dist/create-directory.d.ts +20 -0
- package/dist/create-directory.d.ts.map +1 -0
- package/dist/create-directory.js +130 -0
- package/dist/create-file-async.d.ts +7 -0
- package/dist/create-file-async.d.ts.map +1 -0
- package/dist/create-file-async.js +121 -0
- package/dist/create-file.d.ts +8 -0
- package/dist/create-file.d.ts.map +1 -0
- package/dist/create-file.js +190 -0
- package/dist/create-owned-file.d.ts +8 -0
- package/dist/create-owned-file.d.ts.map +1 -0
- package/dist/create-owned-file.js +16 -0
- package/dist/create.d.ts +4 -0
- package/dist/create.d.ts.map +1 -0
- package/dist/create.js +2 -0
- package/dist/creation-darwin.d.ts +7 -0
- package/dist/creation-darwin.d.ts.map +1 -0
- package/dist/creation-darwin.js +79 -0
- package/dist/creation-file-state.d.ts +19 -0
- package/dist/creation-file-state.d.ts.map +1 -0
- package/dist/creation-file-state.js +118 -0
- package/dist/creation-path.d.ts +21 -0
- package/dist/creation-path.d.ts.map +1 -0
- package/dist/creation-path.js +71 -0
- package/dist/creation-permissions.d.ts +19 -0
- package/dist/creation-permissions.d.ts.map +1 -0
- package/dist/creation-permissions.js +125 -0
- package/dist/directory-durability.d.ts +1 -1
- package/dist/directory-durability.d.ts.map +1 -1
- package/dist/directory-durability.js +22 -80
- package/dist/directory-guard.d.ts +3 -0
- package/dist/directory-guard.d.ts.map +1 -1
- package/dist/directory-mode-node.d.ts +2 -0
- package/dist/directory-mode-node.d.ts.map +1 -1
- package/dist/directory-mode-node.js +8 -0
- package/dist/directory-mode-owner.js +5 -5
- package/dist/directory-receipt.d.ts +24 -0
- package/dist/directory-receipt.d.ts.map +1 -0
- package/dist/directory-receipt.js +127 -0
- package/dist/file-cleanup.d.ts +19 -0
- package/dist/file-cleanup.d.ts.map +1 -0
- package/dist/file-cleanup.js +78 -0
- package/dist/file-handle-transfer.d.ts +2 -0
- package/dist/file-handle-transfer.d.ts.map +1 -1
- package/dist/file-handle-transfer.js +57 -2
- package/dist/file-identity.d.ts.map +1 -1
- package/dist/file-identity.js +18 -4
- package/dist/file-lock-sync-admission.d.ts +19 -0
- package/dist/file-lock-sync-admission.d.ts.map +1 -0
- package/dist/file-lock-sync-admission.js +93 -0
- package/dist/file-lock-sync-root-acquire.d.ts +4 -0
- package/dist/file-lock-sync-root-acquire.d.ts.map +1 -0
- package/dist/file-lock-sync-root-acquire.js +370 -0
- package/dist/file-lock-sync-root-arbitration.d.ts +18 -0
- package/dist/file-lock-sync-root-arbitration.d.ts.map +1 -0
- package/dist/file-lock-sync-root-arbitration.js +66 -0
- package/dist/file-lock-sync-root-held.d.ts +34 -0
- package/dist/file-lock-sync-root-held.d.ts.map +1 -0
- package/dist/file-lock-sync-root-held.js +393 -0
- package/dist/file-lock-sync-root-io.d.ts +44 -0
- package/dist/file-lock-sync-root-io.d.ts.map +1 -0
- package/dist/file-lock-sync-root-io.js +209 -0
- package/dist/file-lock-sync-root-mutation.d.ts +17 -0
- package/dist/file-lock-sync-root-mutation.d.ts.map +1 -0
- package/dist/file-lock-sync-root-mutation.js +277 -0
- package/dist/file-lock-sync-root-options.d.ts +20 -0
- package/dist/file-lock-sync-root-options.d.ts.map +1 -0
- package/dist/file-lock-sync-root-options.js +58 -0
- package/dist/file-lock-sync-root-registration.d.ts +2 -0
- package/dist/file-lock-sync-root-registration.d.ts.map +1 -0
- package/dist/file-lock-sync-root-registration.js +90 -0
- package/dist/file-lock-sync-root.d.ts +36 -0
- package/dist/file-lock-sync-root.d.ts.map +1 -0
- package/dist/file-lock-sync-root.js +361 -0
- package/dist/file-lock-sync-stale-admission.d.ts +24 -0
- package/dist/file-lock-sync-stale-admission.d.ts.map +1 -0
- package/dist/file-lock-sync-stale-admission.js +205 -0
- package/dist/file-lock-sync.d.ts.map +1 -1
- package/dist/file-lock-sync.js +245 -205
- package/dist/file-observation.d.ts +1 -1
- package/dist/file-observation.d.ts.map +1 -1
- package/dist/file-store-boundary.d.ts +2 -6
- package/dist/file-store-boundary.d.ts.map +1 -1
- package/dist/file-store-boundary.js +3 -9
- package/dist/file-store-prune.d.ts.map +1 -1
- package/dist/file-store-prune.js +5 -1
- package/dist/file-store-sync-write.d.ts.map +1 -1
- package/dist/file-store-sync-write.js +5 -8
- package/dist/file-store.d.ts.map +1 -1
- package/dist/file-store.js +47 -12
- package/dist/guarded-mkdir.d.ts +1 -0
- package/dist/guarded-mkdir.d.ts.map +1 -1
- package/dist/guarded-mkdir.js +36 -7
- package/dist/json-document-store.d.ts.map +1 -1
- package/dist/json-document-store.js +22 -15
- package/dist/json-durable-queue-ownership.d.ts +0 -1
- package/dist/json-durable-queue-ownership.d.ts.map +1 -1
- package/dist/json-durable-queue-ownership.js +0 -6
- package/dist/move-path.js +1 -1
- package/dist/native-binding.d.ts +13 -1
- package/dist/native-binding.d.ts.map +1 -1
- package/dist/native-fallback-warning.d.ts +4 -0
- package/dist/native-fallback-warning.d.ts.map +1 -0
- package/dist/native-fallback-warning.js +11 -0
- package/dist/native-operations.d.ts +0 -2
- package/dist/native-operations.d.ts.map +1 -1
- package/dist/native-operations.js +0 -24
- package/dist/native-parent-admission.d.ts +5 -2
- package/dist/native-parent-admission.d.ts.map +1 -1
- package/dist/native-parent-admission.js +27 -7
- package/dist/native-pinned-write-windows.d.ts +1 -1
- package/dist/native-pinned-write-windows.d.ts.map +1 -1
- package/dist/native-pinned-write-windows.js +174 -29
- package/dist/native-pinned-write.d.ts.map +1 -1
- package/dist/native-pinned-write.js +26 -14
- package/dist/native-policy-parent-windows.d.ts +14 -0
- package/dist/native-policy-parent-windows.d.ts.map +1 -0
- package/dist/native-policy-parent-windows.js +209 -0
- package/dist/native-rename-outcome.d.ts +4 -0
- package/dist/native-rename-outcome.d.ts.map +1 -0
- package/dist/native-rename-outcome.js +8 -0
- package/dist/native-staged-file.d.ts +3 -2
- package/dist/native-staged-file.d.ts.map +1 -1
- package/dist/native-staged-file.js +121 -72
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +12 -8
- package/dist/owner-dacl.d.ts.map +1 -1
- package/dist/owner-dacl.js +10 -4
- package/dist/path-prefix.d.ts.map +1 -1
- package/dist/path-prefix.js +30 -8
- package/dist/path-suffix-aliases.d.ts +2 -0
- package/dist/path-suffix-aliases.d.ts.map +1 -1
- package/dist/path-suffix-aliases.js +25 -17
- package/dist/permission-exec.d.ts +2 -0
- package/dist/permission-exec.d.ts.map +1 -1
- package/dist/permission-exec.js +150 -21
- package/dist/permissions-windows.js +1 -1
- package/dist/pinned-mutation-admission.d.ts.map +1 -1
- package/dist/pinned-mutation-admission.js +10 -5
- package/dist/pinned-mutation-observation.d.ts +0 -1
- package/dist/pinned-mutation-observation.d.ts.map +1 -1
- package/dist/pinned-mutation-observation.js +0 -19
- package/dist/pinned-mutation-shared-route.d.ts +1 -0
- package/dist/pinned-mutation-shared-route.d.ts.map +1 -1
- package/dist/pinned-mutation-shared-route.js +1 -1
- package/dist/pinned-write-input.d.ts +4 -0
- package/dist/pinned-write-input.d.ts.map +1 -0
- package/dist/pinned-write-input.js +25 -0
- package/dist/pinned-write-mode.d.ts +5 -0
- package/dist/pinned-write-mode.d.ts.map +1 -0
- package/dist/pinned-write-mode.js +24 -0
- package/dist/pinned-write-staged.d.ts +6 -0
- package/dist/pinned-write-staged.d.ts.map +1 -0
- package/dist/pinned-write-staged.js +187 -0
- package/dist/pinned-write-types.d.ts +5 -0
- package/dist/pinned-write-types.d.ts.map +1 -1
- package/dist/pinned-write.d.ts.map +1 -1
- package/dist/pinned-write.js +35 -145
- package/dist/private-directory.d.ts.map +1 -1
- package/dist/private-directory.js +18 -4
- package/dist/private-producer-handoff-sync.d.ts +14 -0
- package/dist/private-producer-handoff-sync.d.ts.map +1 -0
- package/dist/private-producer-handoff-sync.js +114 -0
- package/dist/private-producer-handoff.d.ts +22 -4
- package/dist/private-producer-handoff.d.ts.map +1 -1
- package/dist/private-producer-handoff.js +140 -77
- package/dist/private-temp-workspace.d.ts.map +1 -1
- package/dist/private-temp-workspace.js +75 -121
- package/dist/publish-copy-stage.d.ts +2 -1
- package/dist/publish-copy-stage.d.ts.map +1 -1
- package/dist/publish-copy-stage.js +16 -7
- package/dist/publish-file.d.ts.map +1 -1
- package/dist/publish-file.js +2 -2
- package/dist/regular-file.d.ts.map +1 -1
- package/dist/regular-file.js +1 -15
- package/dist/replace-directory.d.ts.map +1 -1
- package/dist/replace-directory.js +256 -18
- package/dist/replace-file-copy-fallback.d.ts.map +1 -1
- package/dist/replace-file-copy-fallback.js +62 -70
- package/dist/replace-file-copy-source.d.ts.map +1 -1
- package/dist/replace-file-copy-source.js +10 -12
- package/dist/replace-file-temp-owner.d.ts +5 -9
- package/dist/replace-file-temp-owner.d.ts.map +1 -1
- package/dist/replace-file-temp-owner.js +56 -72
- package/dist/replace-file.js +6 -6
- package/dist/retained-directory-replacement.d.ts +26 -0
- package/dist/retained-directory-replacement.d.ts.map +1 -0
- package/dist/retained-directory-replacement.js +193 -0
- package/dist/root-boundary.d.ts +1 -0
- package/dist/root-boundary.d.ts.map +1 -1
- package/dist/root-boundary.js +4 -0
- package/dist/root-context.d.ts +0 -8
- package/dist/root-context.d.ts.map +1 -1
- package/dist/root-context.js +0 -3
- package/dist/root-create-input.d.ts +8 -1
- package/dist/root-create-input.d.ts.map +1 -1
- package/dist/root-create-input.js +17 -4
- package/dist/root-directory-creation.d.ts +3 -3
- package/dist/root-directory-creation.d.ts.map +1 -1
- package/dist/root-directory-creation.js +15 -3
- package/dist/root-directory-list.d.ts +1 -0
- package/dist/root-directory-list.d.ts.map +1 -1
- package/dist/root-directory-list.js +1 -0
- package/dist/root-impl.d.ts.map +1 -1
- package/dist/root-impl.js +46 -17
- package/dist/root-move-noreplace.d.ts.map +1 -1
- package/dist/root-move-noreplace.js +24 -15
- package/dist/root-options.d.ts +12 -4
- package/dist/root-options.d.ts.map +1 -1
- package/dist/root-path-errors.d.ts +1 -0
- package/dist/root-path-errors.d.ts.map +1 -1
- package/dist/root-path-errors.js +11 -2
- package/dist/root-path-existing.d.ts.map +1 -1
- package/dist/root-path-existing.js +11 -35
- package/dist/root-path-stat.d.ts.map +1 -1
- package/dist/root-path-stat.js +59 -7
- package/dist/root-path.js +1 -13
- package/dist/root-remove.d.ts +1 -0
- package/dist/root-remove.d.ts.map +1 -1
- package/dist/root-remove.js +4 -0
- package/dist/root-walk.d.ts +1 -1
- package/dist/root-walk.d.ts.map +1 -1
- package/dist/root-walk.js +17 -2
- package/dist/root-write-admission.d.ts +0 -2
- package/dist/root-write-admission.d.ts.map +1 -1
- package/dist/root-write-admission.js +1 -15
- package/dist/root-write-complete-parent.d.ts.map +1 -1
- package/dist/root-write-complete-parent.js +7 -23
- package/dist/root-write-publication.js +1 -1
- package/dist/root-write-verification.d.ts.map +1 -1
- package/dist/root-write-verification.js +29 -42
- package/dist/secret-file.d.ts.map +1 -1
- package/dist/secret-file.js +3 -24
- package/dist/secret-read-async.d.ts.map +1 -1
- package/dist/secret-read-async.js +3 -24
- package/dist/secret-read-policy.d.ts +6 -2
- package/dist/secret-read-policy.d.ts.map +1 -1
- package/dist/secret-read-policy.js +26 -2
- package/dist/secure-file-windows.d.ts +6 -0
- package/dist/secure-file-windows.d.ts.map +1 -1
- package/dist/secure-file-windows.js +34 -117
- package/dist/secure-file.js +2 -2
- package/dist/sibling-temp.d.ts.map +1 -1
- package/dist/sibling-temp.js +23 -12
- package/dist/sidecar-lock-acquire.d.ts +2 -28
- package/dist/sidecar-lock-acquire.d.ts.map +1 -1
- package/dist/sidecar-lock-acquire.js +288 -199
- package/dist/sidecar-lock-admission-context.d.ts +19 -0
- package/dist/sidecar-lock-admission-context.d.ts.map +1 -0
- package/dist/sidecar-lock-admission-context.js +60 -0
- package/dist/sidecar-lock-admission-parser.d.ts +43 -0
- package/dist/sidecar-lock-admission-parser.d.ts.map +1 -0
- package/dist/sidecar-lock-admission-parser.js +113 -0
- package/dist/sidecar-lock-admission.d.ts +35 -0
- package/dist/sidecar-lock-admission.d.ts.map +1 -0
- package/dist/sidecar-lock-admission.js +7 -0
- package/dist/sidecar-lock-reclaim.d.ts +9 -4
- package/dist/sidecar-lock-reclaim.d.ts.map +1 -1
- package/dist/sidecar-lock-reclaim.js +80 -25
- package/dist/sidecar-lock-root.d.ts.map +1 -1
- package/dist/sidecar-lock-root.js +2 -1
- package/dist/sidecar-lock-stale-admission.d.ts +39 -0
- package/dist/sidecar-lock-stale-admission.d.ts.map +1 -0
- package/dist/sidecar-lock-stale-admission.js +232 -0
- package/dist/sidecar-lock-target.d.ts +8 -0
- package/dist/sidecar-lock-target.d.ts.map +1 -0
- package/dist/sidecar-lock-target.js +55 -0
- package/dist/sidecar-lock.d.ts.map +1 -1
- package/dist/sidecar-lock.js +100 -16
- package/dist/staged-directory.d.ts.map +1 -1
- package/dist/staged-directory.js +6 -6
- package/dist/staged-file-settlement.d.ts +17 -0
- package/dist/staged-file-settlement.d.ts.map +1 -0
- package/dist/staged-file-settlement.js +57 -0
- package/dist/temp-workspace-descriptor.d.ts.map +1 -1
- package/dist/temp-workspace-descriptor.js +9 -27
- package/dist/temp-workspace-owner.d.ts.map +1 -1
- package/dist/temp-workspace-owner.js +8 -8
- package/dist/walk.d.ts +5 -1
- package/dist/walk.d.ts.map +1 -1
- package/dist/walk.js +19 -6
- package/dist/windows-owner.d.ts.map +1 -1
- package/dist/windows-owner.js +4 -3
- package/dist/windows-security-bridge.cs +336 -0
- package/dist/windows-security-bridge.ps1 +15 -0
- package/dist/windows-security-command.d.ts +26 -0
- package/dist/windows-security-command.d.ts.map +1 -0
- package/dist/windows-security-command.js +363 -0
- package/dist/windows-security-facts.d.ts +6 -0
- package/dist/windows-security-facts.d.ts.map +1 -0
- package/dist/windows-security-facts.js +108 -0
- package/docs/advanced.md +4 -2
- package/docs/archive.md +97 -46
- package/docs/atomic.md +85 -8
- package/docs/config.md +6 -2
- package/docs/contributing.md +44 -4
- package/docs/copy.md +37 -0
- package/docs/creation.md +128 -0
- package/docs/durability.md +24 -0
- package/docs/file-store.md +19 -0
- package/docs/install.md +31 -7
- package/docs/json-store.md +5 -0
- package/docs/migrating-to-0.5.md +15 -6
- package/docs/migrating-to-0.6.md +9 -4
- package/docs/native-helper.md +32 -12
- package/docs/native.md +38 -7
- package/docs/output.md +6 -0
- package/docs/path-prefix.md +10 -0
- package/docs/path-suffix-aliases.md +51 -6
- package/docs/permissions.md +50 -14
- package/docs/public-api.md +3 -2
- package/docs/root.md +56 -3
- package/docs/secret-file.md +11 -2
- package/docs/secure-file.md +9 -4
- package/docs/sidecar-lock.md +114 -8
- package/docs/staged-file.md +12 -3
- package/docs/temp.md +20 -3
- package/docs/walk.md +67 -1
- package/docs/writing.md +76 -6
- package/package.json +19 -16
- package/dist/darwin-acl.d.ts +0 -4
- package/dist/darwin-acl.d.ts.map +0 -1
- package/dist/darwin-acl.js +0 -24
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecar-lock-admission-context.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-admission-context.ts"],"names":[],"mappings":"AAEA,KAAK,iBAAiB,GAAG;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,KAAK,wBAAwB,GAAG,SAAS,iBAAiB,EAAE,CAAC;AAkB7D,wFAAwF;AACxF,wBAAgB,+BAA+B,IAAI,wBAAwB,CAM1E;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,oBAAoB,EAAE,MAAM,GAC3B,OAAO,CAGT;AA4BD,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC/B,oBAAoB,EAAE,MAAM;mBAMd,OAAO;oBAHA,OAAO;eAKf,IAAI;eAKJ,IAAI;QAMX,CAAC,YAAY,MAAM,CAAC,GAAG,CAAC;EAI/B"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
const EMPTY_ANCESTRY = Object.freeze([]);
|
|
3
|
+
const GLOBAL_CONTEXT_KEY = Symbol.for("fsSafe.sidecarLockAdmissionAsyncContext");
|
|
4
|
+
function admissionContext() {
|
|
5
|
+
const shared = globalThis;
|
|
6
|
+
return shared[GLOBAL_CONTEXT_KEY] ??=
|
|
7
|
+
new AsyncLocalStorage();
|
|
8
|
+
}
|
|
9
|
+
/** Capture active ancestry now; later lifecycle changes cannot reclassify this call. */
|
|
10
|
+
export function captureSidecarAdmissionAncestry() {
|
|
11
|
+
const current = admissionContext().getStore();
|
|
12
|
+
if (!current)
|
|
13
|
+
return EMPTY_ANCESTRY;
|
|
14
|
+
const active = current.ancestry.filter((entry) => entry.active);
|
|
15
|
+
if (current.active)
|
|
16
|
+
active.push(current);
|
|
17
|
+
return active.length === 0 ? EMPTY_ANCESTRY : active;
|
|
18
|
+
}
|
|
19
|
+
export function ancestryHasSidecarAdmission(ancestry, admissions, normalizedTargetPath) {
|
|
20
|
+
return ancestry.some((entry) => entry.admissions === admissions && entry.normalizedTargetPath === normalizedTargetPath);
|
|
21
|
+
}
|
|
22
|
+
function createSidecarAdmissionScope(ancestry, admissions, normalizedTargetPath, token) {
|
|
23
|
+
return { active: false, admissions, ancestry, normalizedTargetPath, started: false, token };
|
|
24
|
+
}
|
|
25
|
+
function activateSidecarAdmissionScope(scope) {
|
|
26
|
+
if (scope.started)
|
|
27
|
+
throw new Error("sidecar admission scope cannot be reactivated");
|
|
28
|
+
scope.started = true;
|
|
29
|
+
scope.active = true;
|
|
30
|
+
}
|
|
31
|
+
function deactivateSidecarAdmissionScope(scope) {
|
|
32
|
+
if (scope)
|
|
33
|
+
scope.active = false;
|
|
34
|
+
}
|
|
35
|
+
function runInSidecarAdmissionScope(scope, callback) {
|
|
36
|
+
return scope?.active ? admissionContext().run(scope, callback) : callback();
|
|
37
|
+
}
|
|
38
|
+
export function createSidecarAdmissionController(ancestry, admissions, normalizedTargetPath) {
|
|
39
|
+
let scope;
|
|
40
|
+
const hasToken = () => scope !== undefined && admissions.get(normalizedTargetPath) === scope.token;
|
|
41
|
+
return {
|
|
42
|
+
get owns() { return scope !== undefined; },
|
|
43
|
+
hasToken,
|
|
44
|
+
release() {
|
|
45
|
+
deactivateSidecarAdmissionScope(scope);
|
|
46
|
+
if (hasToken())
|
|
47
|
+
admissions.delete(normalizedTargetPath);
|
|
48
|
+
scope = undefined;
|
|
49
|
+
},
|
|
50
|
+
reserve() {
|
|
51
|
+
const token = {};
|
|
52
|
+
scope = createSidecarAdmissionScope(ancestry, admissions, normalizedTargetPath, token);
|
|
53
|
+
admissions.set(normalizedTargetPath, token);
|
|
54
|
+
activateSidecarAdmissionScope(scope);
|
|
55
|
+
},
|
|
56
|
+
run(callback) {
|
|
57
|
+
return runInSidecarAdmissionScope(scope, callback);
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Root } from "./root-impl.js";
|
|
2
|
+
import type { HeldSidecarLock } from "./sidecar-lock-admission.js";
|
|
3
|
+
import { readSidecarLockRawSnapshot, type SidecarLockSnapshot } from "./sidecar-lock-reclaim.js";
|
|
4
|
+
type SidecarAdmissionRunner = {
|
|
5
|
+
hasToken(): boolean;
|
|
6
|
+
run<T>(callback: () => T): T;
|
|
7
|
+
};
|
|
8
|
+
export declare function runSidecarAdmissionBoundary<T>(admission: SidecarAdmissionRunner, assertCurrent: () => void, callback: () => T): T;
|
|
9
|
+
export declare function awaitSidecarAdmissionBoundary<T>(admission: SidecarAdmissionRunner, assertCurrent: () => void, callback: () => T | PromiseLike<T>): Promise<{
|
|
10
|
+
readonly value: Awaited<T>;
|
|
11
|
+
}>;
|
|
12
|
+
export type SidecarLockParserState = {
|
|
13
|
+
observed: boolean;
|
|
14
|
+
parser?: (raw: string) => unknown;
|
|
15
|
+
};
|
|
16
|
+
export declare function observeSidecarLockParser(state: SidecarLockParserState, admission: SidecarAdmissionRunner, accessor: () => ((raw: string) => unknown) | undefined, assertCurrent: () => void): void;
|
|
17
|
+
export declare function scopedSidecarLockParser(state: SidecarLockParserState, admission: SidecarAdmissionRunner, assertCurrent: () => void): ((raw: string) => unknown) | undefined;
|
|
18
|
+
/** Cleanup may outlive its reservation; never invoke user code after authority is lost. */
|
|
19
|
+
export declare function conditionalSidecarLockParser(state: SidecarLockParserState, admission: SidecarAdmissionRunner, isCurrent: () => boolean): ((raw: string) => unknown) | undefined;
|
|
20
|
+
export declare function parseSidecarLockSnapshotUnderAdmission(raw: Awaited<ReturnType<typeof readSidecarLockRawSnapshot>>, state: SidecarLockParserState, admission: SidecarAdmissionRunner, assertCurrent: () => void): SidecarLockSnapshot | null;
|
|
21
|
+
export type HeldSidecarParserObservation = {
|
|
22
|
+
kind: "observed";
|
|
23
|
+
} | {
|
|
24
|
+
kind: "holder-changed";
|
|
25
|
+
} | {
|
|
26
|
+
kind: "read-error";
|
|
27
|
+
error: unknown;
|
|
28
|
+
transientDenial: boolean;
|
|
29
|
+
};
|
|
30
|
+
/** Emulate the historical EEXIST read/parser boundary without opening another sidecar. */
|
|
31
|
+
export declare function observeHeldSidecarParser(params: {
|
|
32
|
+
admission: SidecarAdmissionRunner;
|
|
33
|
+
assertToken(): void;
|
|
34
|
+
currentHeld(): HeldSidecarLock | undefined;
|
|
35
|
+
held: HeldSidecarLock;
|
|
36
|
+
lockPath: string;
|
|
37
|
+
lockRoot?: Root;
|
|
38
|
+
parserState: SidecarLockParserState;
|
|
39
|
+
parserAccessor(): ((raw: string) => unknown) | undefined;
|
|
40
|
+
isTransientDenial(error: unknown): boolean;
|
|
41
|
+
}): Promise<HeldSidecarParserObservation>;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=sidecar-lock-admission-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecar-lock-admission-parser.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-admission-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { parseSidecarLockSnapshot, readSidecarLockRawSnapshot, } from "./sidecar-lock-reclaim.js";
|
|
2
|
+
export function runSidecarAdmissionBoundary(admission, assertCurrent, callback) {
|
|
3
|
+
assertCurrent();
|
|
4
|
+
try {
|
|
5
|
+
return admission.run(callback);
|
|
6
|
+
}
|
|
7
|
+
finally {
|
|
8
|
+
assertCurrent();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export async function awaitSidecarAdmissionBoundary(admission, assertCurrent, callback) {
|
|
12
|
+
assertCurrent();
|
|
13
|
+
try {
|
|
14
|
+
return await admission.run(async () => {
|
|
15
|
+
const boxed = Object.create(null);
|
|
16
|
+
Object.defineProperty(boxed, "value", {
|
|
17
|
+
value: undefined, enumerable: true, writable: true,
|
|
18
|
+
});
|
|
19
|
+
boxed.value = await callback();
|
|
20
|
+
return boxed;
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
assertCurrent();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function observeSidecarLockParser(state, admission, accessor, assertCurrent) {
|
|
28
|
+
assertCurrent();
|
|
29
|
+
if (state.observed)
|
|
30
|
+
return;
|
|
31
|
+
try {
|
|
32
|
+
state.parser = admission.run(accessor);
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
assertCurrent();
|
|
36
|
+
}
|
|
37
|
+
state.observed = true;
|
|
38
|
+
}
|
|
39
|
+
export function scopedSidecarLockParser(state, admission, assertCurrent) {
|
|
40
|
+
const parser = state.parser;
|
|
41
|
+
return parser && ((raw) => admission.run(() => {
|
|
42
|
+
assertCurrent();
|
|
43
|
+
try {
|
|
44
|
+
return Reflect.apply(parser, undefined, [raw]);
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
assertCurrent();
|
|
48
|
+
}
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
/** Cleanup may outlive its reservation; never invoke user code after authority is lost. */
|
|
52
|
+
export function conditionalSidecarLockParser(state, admission, isCurrent) {
|
|
53
|
+
const parser = state.parser;
|
|
54
|
+
return parser && ((raw) => {
|
|
55
|
+
if (!isCurrent())
|
|
56
|
+
return undefined;
|
|
57
|
+
return admission.run(() => {
|
|
58
|
+
if (!isCurrent())
|
|
59
|
+
return undefined;
|
|
60
|
+
let parsed;
|
|
61
|
+
try {
|
|
62
|
+
parsed = Reflect.apply(parser, undefined, [raw]);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
if (!isCurrent())
|
|
66
|
+
return undefined;
|
|
67
|
+
throw error;
|
|
68
|
+
}
|
|
69
|
+
return isCurrent() ? parsed : undefined;
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
export function parseSidecarLockSnapshotUnderAdmission(raw, state, admission, assertCurrent) {
|
|
74
|
+
return parseSidecarLockSnapshot(raw, scopedSidecarLockParser(state, admission, assertCurrent));
|
|
75
|
+
}
|
|
76
|
+
/** Emulate the historical EEXIST read/parser boundary without opening another sidecar. */
|
|
77
|
+
export async function observeHeldSidecarParser(params) {
|
|
78
|
+
const holderChanged = {};
|
|
79
|
+
const assertCurrentHolder = () => {
|
|
80
|
+
params.assertToken();
|
|
81
|
+
if (params.currentHeld() !== params.held || params.held.releasePromise) {
|
|
82
|
+
throw holderChanged;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
let transientDenial = false;
|
|
86
|
+
let raw;
|
|
87
|
+
try {
|
|
88
|
+
raw = await params.admission.run(async () => await readSidecarLockRawSnapshot(params.lockPath, {
|
|
89
|
+
lockRoot: params.lockRoot,
|
|
90
|
+
rejectNonFile: true,
|
|
91
|
+
discardObservation: "changed",
|
|
92
|
+
onOpenFailure: (error) => { transientDenial = params.isTransientDenial(error); },
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
return { kind: "read-error", error, transientDenial };
|
|
97
|
+
}
|
|
98
|
+
params.assertToken();
|
|
99
|
+
if (params.currentHeld() !== params.held || params.held.releasePromise) {
|
|
100
|
+
return { kind: "holder-changed" };
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
observeSidecarLockParser(params.parserState, params.admission, params.parserAccessor, assertCurrentHolder);
|
|
104
|
+
parseSidecarLockSnapshotUnderAdmission(raw, params.parserState, params.admission, assertCurrentHolder);
|
|
105
|
+
assertCurrentHolder();
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error === holderChanged)
|
|
109
|
+
return { kind: "holder-changed" };
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
return { kind: "observed" };
|
|
113
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { NativeFileHandle } from "./native-operations.js";
|
|
2
|
+
import type { Root } from "./root-impl.js";
|
|
3
|
+
import type { SidecarLockSnapshot } from "./sidecar-lock-reclaim.js";
|
|
4
|
+
import type { SidecarLockHandle } from "./sidecar-lock-types.js";
|
|
5
|
+
type SidecarFileHandle = Pick<NativeFileHandle, "fd" | "close" | "stat" | "writeFile">;
|
|
6
|
+
export type HeldSidecarLock = {
|
|
7
|
+
refCount: number;
|
|
8
|
+
reentrantOwner?: string;
|
|
9
|
+
handle: SidecarFileHandle;
|
|
10
|
+
lockPath: string;
|
|
11
|
+
snapshot: SidecarLockSnapshot;
|
|
12
|
+
acquiredAt: number;
|
|
13
|
+
metadata: Record<string, unknown>;
|
|
14
|
+
releasePromise?: Promise<void>;
|
|
15
|
+
lockRoot?: Root;
|
|
16
|
+
retainOnExit?: boolean;
|
|
17
|
+
parsePayload?: (raw: string) => unknown;
|
|
18
|
+
compromiseTimer?: NodeJS.Timeout;
|
|
19
|
+
};
|
|
20
|
+
export type SidecarLockAcquisitionContext = {
|
|
21
|
+
held: Map<string, HeldSidecarLock>;
|
|
22
|
+
admissions: Map<string, object>;
|
|
23
|
+
reclaimGuards: Set<string>;
|
|
24
|
+
ensureExitCleanupRegistered(): {
|
|
25
|
+
armed: boolean;
|
|
26
|
+
};
|
|
27
|
+
armExitCleanup(lifecycle: {
|
|
28
|
+
armed: boolean;
|
|
29
|
+
}): void;
|
|
30
|
+
assertRetainOnExitSupported(retainOnExit: boolean | undefined): void;
|
|
31
|
+
handleForHeldLock(normalizedTargetPath: string, held: HeldSidecarLock): SidecarLockHandle;
|
|
32
|
+
};
|
|
33
|
+
export declare function sidecarLockTimeout(lockPath: string, normalizedTargetPath: string): Error;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=sidecar-lock-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecar-lock-admission.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-admission.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,KAAK,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,WAAW,CAAC,CAAC;AAEvF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,cAAc,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACnC,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,2BAA2B,IAAI;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,CAAC;IAClD,cAAc,CAAC,SAAS,EAAE;QAAE,KAAK,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACpD,2BAA2B,CAAC,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;IACrE,iBAAiB,CAAC,oBAAoB,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAAC;CAC3F,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,GAAG,KAAK,CAMxF"}
|
|
@@ -38,7 +38,7 @@ export declare function readSidecarLockRawSnapshotSync(lockPath: string, options
|
|
|
38
38
|
rejectNonFile?: boolean;
|
|
39
39
|
onOpenFailure?: (error: unknown) => void;
|
|
40
40
|
}): SidecarLockRawSnapshot | null;
|
|
41
|
-
export declare function removeSidecarLockIfUnchangedSync(lockPath: string, observed: SidecarLockSnapshot): boolean;
|
|
41
|
+
export declare function removeSidecarLockIfUnchangedSync(lockPath: string, observed: SidecarLockSnapshot, assertAuthorized?: () => void): boolean;
|
|
42
42
|
export declare function sidecarLockSnapshotMatches(current: SidecarLockSnapshot, observed: SidecarLockSnapshot): boolean;
|
|
43
43
|
export declare function removeSidecarLockIfUnchanged(lockPath: string, observed: SidecarLockSnapshot | null, options?: {
|
|
44
44
|
lockRoot?: Root;
|
|
@@ -48,9 +48,12 @@ export declare function sidecarLockSnapshotStillPresent(lockPath: string, observ
|
|
|
48
48
|
lockRoot?: Root;
|
|
49
49
|
parsePayload?: (raw: string) => unknown;
|
|
50
50
|
}): Promise<boolean>;
|
|
51
|
-
export
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
export type SidecarReclaimGuard = {
|
|
52
|
+
assertHeld?(): Promise<void>;
|
|
53
|
+
release(): Promise<void>;
|
|
54
|
+
};
|
|
55
|
+
export declare function sidecarReclaimGuardExists(pathname: string, lockRoot?: Root): Promise<boolean>;
|
|
56
|
+
export declare function tryAcquireSidecarReclaimGuard(reclaimGuards: Set<string>, pathname: string, lockRoot?: Root): Promise<SidecarReclaimGuard | undefined>;
|
|
54
57
|
export declare function removeStaleSidecarLockIfAllowed(params: {
|
|
55
58
|
lockPath: string;
|
|
56
59
|
normalizedTargetPath: string;
|
|
@@ -58,6 +61,8 @@ export declare function removeStaleSidecarLockIfAllowed(params: {
|
|
|
58
61
|
shouldRemoveStaleLock?: (snapshot: SidecarLockStaleSnapshot) => boolean | Promise<boolean>;
|
|
59
62
|
lockRoot?: Root;
|
|
60
63
|
parsePayload?: (raw: string) => unknown;
|
|
64
|
+
assertAuthorized?: () => void;
|
|
65
|
+
assertGuardHeld?: () => Promise<void>;
|
|
61
66
|
}): Promise<"removed" | "changed" | "not-approved">;
|
|
62
67
|
export {};
|
|
63
68
|
//# sourceMappingURL=sidecar-lock-reclaim.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidecar-lock-reclaim.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-reclaim.ts"],"names":[],"mappings":"AACA,OAAe,EAAE,KAAK,KAAK,EAAE,MAAM,SAAS,CAAC;AAO7C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"sidecar-lock-reclaim.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-reclaim.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,10 +4,11 @@ import fs from "node:fs/promises";
|
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import { readFileDescriptorBoundedSync, readFileHandleBounded } from "./bounded-read.js";
|
|
6
6
|
import { FsSafeError } from "./errors.js";
|
|
7
|
-
import { sameFileIdentity } from "./file-identity.js";
|
|
7
|
+
import { sameFileIdentity, sameFileIdentityForCleanup } from "./file-identity.js";
|
|
8
8
|
import { resolveReadOpenFlags } from "./read-open-flags.js";
|
|
9
9
|
import { openSidecarRoot } from "./sidecar-lock-root.js";
|
|
10
10
|
import { getFsSafeTestHooks } from "./test-hooks.js";
|
|
11
|
+
import { sidecarExclusiveCreate } from "./root-create-input.js";
|
|
11
12
|
const MAX_LOCK_PAYLOAD_BYTES = 1024 * 1024;
|
|
12
13
|
const SIDECAR_LOCK_OWNERSHIP_TOKEN_BYTES = 16;
|
|
13
14
|
const SIDECAR_LOCK_OWNERSHIP_TOKEN_BITS = SIDECAR_LOCK_OWNERSHIP_TOKEN_BYTES * 8;
|
|
@@ -204,10 +205,13 @@ export function readSidecarLockRawSnapshotSync(lockPath, options = {}) {
|
|
|
204
205
|
fsSync.closeSync(fd);
|
|
205
206
|
}
|
|
206
207
|
}
|
|
207
|
-
export function removeSidecarLockIfUnchangedSync(lockPath, observed) {
|
|
208
|
+
export function removeSidecarLockIfUnchangedSync(lockPath, observed, assertAuthorized) {
|
|
209
|
+
assertAuthorized?.();
|
|
208
210
|
const current = readSidecarLockSnapshotSync(lockPath);
|
|
211
|
+
assertAuthorized?.();
|
|
209
212
|
if (!current || !sidecarLockSnapshotMatches(current, observed))
|
|
210
213
|
return false;
|
|
214
|
+
assertAuthorized?.();
|
|
211
215
|
fsSync.rmSync(lockPath);
|
|
212
216
|
return true;
|
|
213
217
|
}
|
|
@@ -220,7 +224,9 @@ export function sidecarLockSnapshotMatches(current, observed) {
|
|
|
220
224
|
readSidecarLockOwnershipToken(observed.raw) === observed.ownershipToken &&
|
|
221
225
|
current.raw === observed.raw);
|
|
222
226
|
}
|
|
223
|
-
if (observed.stat &&
|
|
227
|
+
if (observed.stat &&
|
|
228
|
+
current.stat &&
|
|
229
|
+
!sameFileIdentityForCleanup(observed.stat, current.stat)) {
|
|
224
230
|
return false;
|
|
225
231
|
}
|
|
226
232
|
if (observed.raw !== undefined) {
|
|
@@ -251,41 +257,84 @@ export async function sidecarLockSnapshotStillPresent(lockPath, observed, option
|
|
|
251
257
|
});
|
|
252
258
|
return !!current && !!observed && sidecarLockSnapshotMatches(current, observed);
|
|
253
259
|
}
|
|
254
|
-
export async function sidecarReclaimGuardExists(pathname) {
|
|
260
|
+
export async function sidecarReclaimGuardExists(pathname, lockRoot) {
|
|
255
261
|
try {
|
|
256
|
-
|
|
262
|
+
if (lockRoot)
|
|
263
|
+
await lockRoot.stat(relativeSidecarLockPath(lockRoot, pathname));
|
|
264
|
+
else
|
|
265
|
+
fsSync.lstatSync(pathname);
|
|
257
266
|
return true;
|
|
258
267
|
}
|
|
259
|
-
catch (
|
|
260
|
-
|
|
268
|
+
catch (error) {
|
|
269
|
+
const code = error?.code;
|
|
270
|
+
if (code === "ENOENT" || (lockRoot && code === "not-found"))
|
|
261
271
|
return false;
|
|
262
|
-
|
|
263
|
-
throw err;
|
|
272
|
+
throw error;
|
|
264
273
|
}
|
|
265
274
|
}
|
|
266
|
-
export async function tryAcquireSidecarReclaimGuard(reclaimGuards,
|
|
275
|
+
export async function tryAcquireSidecarReclaimGuard(reclaimGuards, pathname, lockRoot) {
|
|
276
|
+
if (lockRoot) {
|
|
277
|
+
const relative = relativeSidecarLockPath(lockRoot, pathname);
|
|
278
|
+
const payload = { pid: process.pid, createdAt: new Date().toISOString() };
|
|
279
|
+
const snapshot = { ...serializeSidecarLockPayload(payload), payload };
|
|
280
|
+
try {
|
|
281
|
+
await lockRoot.create(relative, snapshot.raw, { ...sidecarExclusiveCreate, mkdir: false, mode: 0o600, durable: false });
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
if (error instanceof FsSafeError && error.code === "already-exists")
|
|
285
|
+
return;
|
|
286
|
+
// A raw reclaimer can create its directory after our occupancy check.
|
|
287
|
+
if (error instanceof FsSafeError && error.code === "not-file") {
|
|
288
|
+
await sidecarReclaimGuardExists(pathname, lockRoot);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
throw error;
|
|
292
|
+
}
|
|
293
|
+
// This attempt owns only its minted token and exact bytes. Root guards
|
|
294
|
+
// never enter raw exit cleanup; interrupted/ambiguous operations preserve them.
|
|
295
|
+
let released = false;
|
|
296
|
+
const changed = () => new FsSafeError("path-mismatch", "sidecar reclaim guard ownership changed");
|
|
297
|
+
return {
|
|
298
|
+
async assertHeld() {
|
|
299
|
+
if (released || !await sidecarLockSnapshotStillPresent(pathname, snapshot, { lockRoot }))
|
|
300
|
+
throw changed();
|
|
301
|
+
},
|
|
302
|
+
async release() {
|
|
303
|
+
if (released)
|
|
304
|
+
return;
|
|
305
|
+
if (!await removeSidecarLockIfUnchanged(pathname, snapshot, { lockRoot }))
|
|
306
|
+
throw changed();
|
|
307
|
+
released = true;
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
}
|
|
267
311
|
try {
|
|
268
|
-
await fs.mkdir(
|
|
269
|
-
reclaimGuards.add(reclaimGuardPath);
|
|
270
|
-
return true;
|
|
312
|
+
await fs.mkdir(pathname);
|
|
271
313
|
}
|
|
272
|
-
catch (
|
|
273
|
-
if (
|
|
274
|
-
return
|
|
275
|
-
|
|
276
|
-
throw err;
|
|
314
|
+
catch (error) {
|
|
315
|
+
if (error?.code === "EEXIST")
|
|
316
|
+
return;
|
|
317
|
+
throw error;
|
|
277
318
|
}
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
319
|
+
reclaimGuards.add(pathname);
|
|
320
|
+
let released = false;
|
|
321
|
+
return { async release() {
|
|
322
|
+
if (released)
|
|
323
|
+
return;
|
|
324
|
+
await fs.rmdir(pathname);
|
|
325
|
+
reclaimGuards.delete(pathname);
|
|
326
|
+
released = true;
|
|
327
|
+
} };
|
|
282
328
|
}
|
|
283
329
|
export async function removeStaleSidecarLockIfAllowed(params) {
|
|
284
330
|
if (!params.shouldRemoveStaleLock || params.snapshot.raw === undefined) {
|
|
285
331
|
return "not-approved";
|
|
286
332
|
}
|
|
287
333
|
const ioOptions = { lockRoot: params.lockRoot, parsePayload: params.parsePayload };
|
|
288
|
-
|
|
334
|
+
params.assertAuthorized?.();
|
|
335
|
+
const presentBeforeApproval = await sidecarLockSnapshotStillPresent(params.lockPath, params.snapshot, ioOptions);
|
|
336
|
+
params.assertAuthorized?.();
|
|
337
|
+
if (!presentBeforeApproval) {
|
|
289
338
|
return "changed";
|
|
290
339
|
}
|
|
291
340
|
if (!(await params.shouldRemoveStaleLock({
|
|
@@ -296,12 +345,18 @@ export async function removeStaleSidecarLockIfAllowed(params) {
|
|
|
296
345
|
}))) {
|
|
297
346
|
return "not-approved";
|
|
298
347
|
}
|
|
299
|
-
|
|
348
|
+
params.assertAuthorized?.();
|
|
349
|
+
const presentBeforeRemoval = await sidecarLockSnapshotStillPresent(params.lockPath, params.snapshot, ioOptions);
|
|
350
|
+
params.assertAuthorized?.();
|
|
351
|
+
if (!presentBeforeRemoval) {
|
|
300
352
|
return "changed";
|
|
301
353
|
}
|
|
354
|
+
if (params.assertGuardHeld)
|
|
355
|
+
await params.assertGuardHeld();
|
|
356
|
+
params.assertAuthorized?.();
|
|
302
357
|
try {
|
|
303
358
|
if (params.lockRoot) {
|
|
304
|
-
await params.lockRoot.remove(relativeSidecarLockPath(params.lockRoot, params.lockPath));
|
|
359
|
+
await params.lockRoot.remove(relativeSidecarLockPath(params.lockRoot, params.lockPath), { assertBeforeMutation: params.assertAuthorized });
|
|
305
360
|
}
|
|
306
361
|
else {
|
|
307
362
|
await fs.rm(params.lockPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sidecar-lock-root.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-root.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAGvD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,UAAU,GAAG,SAAS,EAC3C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GACvC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"sidecar-lock-root.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-root.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAGvD,wBAAsB,eAAe,CACnC,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,MAAM,EAChB,kBAAkB,CAAC,EAAE,UAAU,GAAG,SAAS,EAC3C,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GACvC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CA0D5B"}
|
|
@@ -61,7 +61,8 @@ export async function openSidecarRoot(lockRoot, relative, discardObservation, on
|
|
|
61
61
|
}
|
|
62
62
|
catch (probeError) {
|
|
63
63
|
if (!(probeError instanceof FsSafeError && probeError.code === "not-found") &&
|
|
64
|
-
!probe.has(probeError, `stat-leaf-missing:${expectedRealPath}`)
|
|
64
|
+
!probe.has(probeError, `stat-leaf-missing:${expectedRealPath}`) &&
|
|
65
|
+
!probe.has(probeError, `stat-leaf-changed:${expectedRealPath}`))
|
|
65
66
|
throw probeError;
|
|
66
67
|
}
|
|
67
68
|
for (const { dir, stat } of parents)
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type SidecarReclaimGuard } from "./sidecar-lock-reclaim.js";
|
|
2
|
+
import { type SidecarLockParserState } from "./sidecar-lock-admission-parser.js";
|
|
3
|
+
import type { Root } from "./root-impl.js";
|
|
4
|
+
import type { SidecarLockAcquireOptions } from "./sidecar-lock-types.js";
|
|
5
|
+
type SidecarAdmissionRunner = {
|
|
6
|
+
hasToken(): boolean;
|
|
7
|
+
run<T>(callback: () => T): T;
|
|
8
|
+
};
|
|
9
|
+
type StaleOptions = Pick<SidecarLockAcquireOptions<Record<string, unknown>>, "shouldReclaim" | "shouldRemoveStaleLock" | "staleRecovery">;
|
|
10
|
+
export type SidecarLockStaleOptionsState = {
|
|
11
|
+
shouldReclaimObserved?: boolean;
|
|
12
|
+
shouldReclaim?: StaleOptions["shouldReclaim"];
|
|
13
|
+
shouldRemoveObserved?: boolean;
|
|
14
|
+
shouldRemove?: StaleOptions["shouldRemoveStaleLock"];
|
|
15
|
+
staleRecoveryObserved?: boolean;
|
|
16
|
+
staleRecovery?: StaleOptions["staleRecovery"];
|
|
17
|
+
};
|
|
18
|
+
/** Handle one historical EEXIST attempt while its canonical admission is held. */
|
|
19
|
+
export declare function handleStaleSidecarAdmission<TPayload extends Record<string, unknown>>(params: {
|
|
20
|
+
admission: SidecarAdmissionRunner;
|
|
21
|
+
assertToken(): void;
|
|
22
|
+
currentHeld(): unknown;
|
|
23
|
+
lockPath: string;
|
|
24
|
+
lockRoot?: Root;
|
|
25
|
+
normalizedTargetPath: string;
|
|
26
|
+
options: SidecarLockAcquireOptions<TPayload>;
|
|
27
|
+
parserState: SidecarLockParserState;
|
|
28
|
+
reclaimGuardPath: string;
|
|
29
|
+
reclaimGuards: Set<string>;
|
|
30
|
+
setReclaimGuard(guard: SidecarReclaimGuard): void;
|
|
31
|
+
releaseReclaimGuard(): Promise<void>;
|
|
32
|
+
staleOptionsState: SidecarLockStaleOptionsState;
|
|
33
|
+
staleMs: number;
|
|
34
|
+
withinDenialBudget(): boolean;
|
|
35
|
+
retryOrRethrowDenial(error: unknown): Promise<void>;
|
|
36
|
+
waitForRetry(): Promise<void>;
|
|
37
|
+
}): Promise<void>;
|
|
38
|
+
export {};
|
|
39
|
+
//# sourceMappingURL=sidecar-lock-stale-admission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidecar-lock-stale-admission.d.ts","sourceRoot":"","sources":["../src/sidecar-lock-stale-admission.ts"],"names":[],"mappings":"AACA,OAAO,EAKL,KAAK,mBAAmB,EACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAIL,KAAK,sBAAsB,EAC5B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,yBAAyB,CAAC;AAEzE,KAAK,sBAAsB,GAAG;IAC5B,QAAQ,IAAI,OAAO,CAAC;IACpB,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;CAC9B,CAAC;AAEF,KAAK,YAAY,GAAG,IAAI,CACtB,yBAAyB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAClD,eAAe,GAAG,uBAAuB,GAAG,eAAe,CAC5D,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;IAC9C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC,uBAAuB,CAAC,CAAC;IACrD,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;CAC/C,CAAC;AAEF,kFAAkF;AAClF,wBAAsB,2BAA2B,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxF,MAAM,EAAE;IACN,SAAS,EAAE,sBAAsB,CAAC;IAClC,WAAW,IAAI,IAAI,CAAC;IACpB,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,IAAI,CAAC;IAChB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,yBAAyB,CAAC,QAAQ,CAAC,CAAC;IAC7C,WAAW,EAAE,sBAAsB,CAAC;IACpC,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,eAAe,CAAC,KAAK,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAClD,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,iBAAiB,EAAE,4BAA4B,CAAC;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,kBAAkB,IAAI,OAAO,CAAC;IAC9B,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/B,GACA,OAAO,CAAC,IAAI,CAAC,CA0Nf"}
|