@sentropic/h2a-cli 0.75.0 → 0.78.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/dist/index.d.ts +1 -37
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -41
- package/dist/index.js.map +1 -1
- package/package.json +4 -15
- package/dist/bin.d.ts +0 -3
- package/dist/bin.d.ts.map +0 -1
- package/dist/bin.js +0 -83
- package/dist/bin.js.map +0 -1
- package/dist/cli-contract.d.ts +0 -62
- package/dist/cli-contract.d.ts.map +0 -1
- package/dist/cli-contract.js +0 -794
- package/dist/cli-contract.js.map +0 -1
- package/dist/cli.d.ts +0 -254
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -4672
- package/dist/cli.js.map +0 -1
- package/dist/hosts/agy.d.ts +0 -14
- package/dist/hosts/agy.d.ts.map +0 -1
- package/dist/hosts/agy.js +0 -47
- package/dist/hosts/agy.js.map +0 -1
- package/dist/hosts/claude.d.ts +0 -12
- package/dist/hosts/claude.d.ts.map +0 -1
- package/dist/hosts/claude.js +0 -46
- package/dist/hosts/claude.js.map +0 -1
- package/dist/hosts/codex.d.ts +0 -65
- package/dist/hosts/codex.d.ts.map +0 -1
- package/dist/hosts/codex.js +0 -45
- package/dist/hosts/codex.js.map +0 -1
- package/dist/hosts/gemini.d.ts +0 -12
- package/dist/hosts/gemini.d.ts.map +0 -1
- package/dist/hosts/gemini.js +0 -46
- package/dist/hosts/gemini.js.map +0 -1
- package/dist/hosts/plugin.d.ts +0 -151
- package/dist/hosts/plugin.d.ts.map +0 -1
- package/dist/hosts/plugin.js +0 -188
- package/dist/hosts/plugin.js.map +0 -1
- package/dist/mcp.d.ts +0 -2
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js +0 -32
- package/dist/mcp.js.map +0 -1
- package/dist/runtime/blockage/index.d.ts +0 -3
- package/dist/runtime/blockage/index.d.ts.map +0 -1
- package/dist/runtime/blockage/index.js +0 -3
- package/dist/runtime/blockage/index.js.map +0 -1
- package/dist/runtime/blockage/notifiers.d.ts +0 -52
- package/dist/runtime/blockage/notifiers.d.ts.map +0 -1
- package/dist/runtime/blockage/notifiers.js +0 -74
- package/dist/runtime/blockage/notifiers.js.map +0 -1
- package/dist/runtime/blockage/registry.d.ts +0 -30
- package/dist/runtime/blockage/registry.d.ts.map +0 -1
- package/dist/runtime/blockage/registry.js +0 -86
- package/dist/runtime/blockage/registry.js.map +0 -1
- package/dist/runtime/deploy/k8s-sidecar.d.ts +0 -92
- package/dist/runtime/deploy/k8s-sidecar.d.ts.map +0 -1
- package/dist/runtime/deploy/k8s-sidecar.js +0 -166
- package/dist/runtime/deploy/k8s-sidecar.js.map +0 -1
- package/dist/runtime/deploy/k8s-tenant.d.ts +0 -86
- package/dist/runtime/deploy/k8s-tenant.d.ts.map +0 -1
- package/dist/runtime/deploy/k8s-tenant.js +0 -255
- package/dist/runtime/deploy/k8s-tenant.js.map +0 -1
- package/dist/runtime/drive/inbox-wake.d.ts +0 -36
- package/dist/runtime/drive/inbox-wake.d.ts.map +0 -1
- package/dist/runtime/drive/inbox-wake.js +0 -50
- package/dist/runtime/drive/inbox-wake.js.map +0 -1
- package/dist/runtime/drive/index.d.ts +0 -173
- package/dist/runtime/drive/index.d.ts.map +0 -1
- package/dist/runtime/drive/index.js +0 -503
- package/dist/runtime/drive/index.js.map +0 -1
- package/dist/runtime/drumbeat/deciders.d.ts +0 -32
- package/dist/runtime/drumbeat/deciders.d.ts.map +0 -1
- package/dist/runtime/drumbeat/deciders.js +0 -65
- package/dist/runtime/drumbeat/deciders.js.map +0 -1
- package/dist/runtime/drumbeat/decisions.d.ts +0 -19
- package/dist/runtime/drumbeat/decisions.d.ts.map +0 -1
- package/dist/runtime/drumbeat/decisions.js +0 -34
- package/dist/runtime/drumbeat/decisions.js.map +0 -1
- package/dist/runtime/drumbeat/inbox-relance.d.ts +0 -29
- package/dist/runtime/drumbeat/inbox-relance.d.ts.map +0 -1
- package/dist/runtime/drumbeat/inbox-relance.js +0 -101
- package/dist/runtime/drumbeat/inbox-relance.js.map +0 -1
- package/dist/runtime/drumbeat/index.d.ts +0 -8
- package/dist/runtime/drumbeat/index.d.ts.map +0 -1
- package/dist/runtime/drumbeat/index.js +0 -8
- package/dist/runtime/drumbeat/index.js.map +0 -1
- package/dist/runtime/drumbeat/registry.d.ts +0 -60
- package/dist/runtime/drumbeat/registry.d.ts.map +0 -1
- package/dist/runtime/drumbeat/registry.js +0 -115
- package/dist/runtime/drumbeat/registry.js.map +0 -1
- package/dist/runtime/drumbeat/relaunchers.d.ts +0 -111
- package/dist/runtime/drumbeat/relaunchers.d.ts.map +0 -1
- package/dist/runtime/drumbeat/relaunchers.js +0 -260
- package/dist/runtime/drumbeat/relaunchers.js.map +0 -1
- package/dist/runtime/drumbeat/scan.d.ts +0 -36
- package/dist/runtime/drumbeat/scan.d.ts.map +0 -1
- package/dist/runtime/drumbeat/scan.js +0 -41
- package/dist/runtime/drumbeat/scan.js.map +0 -1
- package/dist/runtime/drumbeat/watch.d.ts +0 -74
- package/dist/runtime/drumbeat/watch.d.ts.map +0 -1
- package/dist/runtime/drumbeat/watch.js +0 -216
- package/dist/runtime/drumbeat/watch.js.map +0 -1
- package/dist/runtime/escalation/index.d.ts +0 -2
- package/dist/runtime/escalation/index.d.ts.map +0 -1
- package/dist/runtime/escalation/index.js +0 -2
- package/dist/runtime/escalation/index.js.map +0 -1
- package/dist/runtime/escalation/registry.d.ts +0 -44
- package/dist/runtime/escalation/registry.d.ts.map +0 -1
- package/dist/runtime/escalation/registry.js +0 -79
- package/dist/runtime/escalation/registry.js.map +0 -1
- package/dist/runtime/governance/claims.d.ts +0 -43
- package/dist/runtime/governance/claims.d.ts.map +0 -1
- package/dist/runtime/governance/claims.js +0 -93
- package/dist/runtime/governance/claims.js.map +0 -1
- package/dist/runtime/governance/conductor.d.ts +0 -79
- package/dist/runtime/governance/conductor.d.ts.map +0 -1
- package/dist/runtime/governance/conductor.js +0 -106
- package/dist/runtime/governance/conductor.js.map +0 -1
- package/dist/runtime/governance/index.d.ts +0 -5
- package/dist/runtime/governance/index.d.ts.map +0 -1
- package/dist/runtime/governance/index.js +0 -5
- package/dist/runtime/governance/index.js.map +0 -1
- package/dist/runtime/governance/launch-check.d.ts +0 -93
- package/dist/runtime/governance/launch-check.d.ts.map +0 -1
- package/dist/runtime/governance/launch-check.js +0 -113
- package/dist/runtime/governance/launch-check.js.map +0 -1
- package/dist/runtime/governance/spawns.d.ts +0 -50
- package/dist/runtime/governance/spawns.d.ts.map +0 -1
- package/dist/runtime/governance/spawns.js +0 -91
- package/dist/runtime/governance/spawns.js.map +0 -1
- package/dist/runtime/identity/bindings.d.ts +0 -84
- package/dist/runtime/identity/bindings.d.ts.map +0 -1
- package/dist/runtime/identity/bindings.js +0 -112
- package/dist/runtime/identity/bindings.js.map +0 -1
- package/dist/runtime/identity/index.d.ts +0 -11
- package/dist/runtime/identity/index.d.ts.map +0 -1
- package/dist/runtime/identity/index.js +0 -6
- package/dist/runtime/identity/index.js.map +0 -1
- package/dist/runtime/identity/live.d.ts +0 -26
- package/dist/runtime/identity/live.d.ts.map +0 -1
- package/dist/runtime/identity/live.js +0 -232
- package/dist/runtime/identity/live.js.map +0 -1
- package/dist/runtime/identity/migration.d.ts +0 -55
- package/dist/runtime/identity/migration.d.ts.map +0 -1
- package/dist/runtime/identity/migration.js +0 -100
- package/dist/runtime/identity/migration.js.map +0 -1
- package/dist/runtime/identity/readers.d.ts +0 -42
- package/dist/runtime/identity/readers.d.ts.map +0 -1
- package/dist/runtime/identity/readers.js +0 -248
- package/dist/runtime/identity/readers.js.map +0 -1
- package/dist/runtime/identity/resolver.d.ts +0 -50
- package/dist/runtime/identity/resolver.d.ts.map +0 -1
- package/dist/runtime/identity/resolver.js +0 -61
- package/dist/runtime/identity/resolver.js.map +0 -1
- package/dist/runtime/identity/workspace-id.d.ts +0 -43
- package/dist/runtime/identity/workspace-id.d.ts.map +0 -1
- package/dist/runtime/identity/workspace-id.js +0 -138
- package/dist/runtime/identity/workspace-id.js.map +0 -1
- package/dist/runtime/local-files/index.d.ts +0 -8
- package/dist/runtime/local-files/index.d.ts.map +0 -1
- package/dist/runtime/local-files/index.js +0 -8
- package/dist/runtime/local-files/index.js.map +0 -1
- package/dist/runtime/local-files/lease.d.ts +0 -62
- package/dist/runtime/local-files/lease.d.ts.map +0 -1
- package/dist/runtime/local-files/lease.js +0 -249
- package/dist/runtime/local-files/lease.js.map +0 -1
- package/dist/runtime/local-files/locks.d.ts +0 -43
- package/dist/runtime/local-files/locks.d.ts.map +0 -1
- package/dist/runtime/local-files/locks.js +0 -197
- package/dist/runtime/local-files/locks.js.map +0 -1
- package/dist/runtime/local-files/migrate.d.ts +0 -31
- package/dist/runtime/local-files/migrate.d.ts.map +0 -1
- package/dist/runtime/local-files/migrate.js +0 -104
- package/dist/runtime/local-files/migrate.js.map +0 -1
- package/dist/runtime/local-files/paths.d.ts +0 -146
- package/dist/runtime/local-files/paths.d.ts.map +0 -1
- package/dist/runtime/local-files/paths.js +0 -233
- package/dist/runtime/local-files/paths.js.map +0 -1
- package/dist/runtime/local-files/presence.d.ts +0 -80
- package/dist/runtime/local-files/presence.d.ts.map +0 -1
- package/dist/runtime/local-files/presence.js +0 -250
- package/dist/runtime/local-files/presence.js.map +0 -1
- package/dist/runtime/local-files/schema.d.ts +0 -47
- package/dist/runtime/local-files/schema.d.ts.map +0 -1
- package/dist/runtime/local-files/schema.js +0 -77
- package/dist/runtime/local-files/schema.js.map +0 -1
- package/dist/runtime/local-files/store.d.ts +0 -132
- package/dist/runtime/local-files/store.d.ts.map +0 -1
- package/dist/runtime/local-files/store.js +0 -997
- package/dist/runtime/local-files/store.js.map +0 -1
- package/dist/runtime/loop/index.d.ts +0 -73
- package/dist/runtime/loop/index.d.ts.map +0 -1
- package/dist/runtime/loop/index.js +0 -107
- package/dist/runtime/loop/index.js.map +0 -1
- package/dist/runtime/mcp/handlers.d.ts +0 -196
- package/dist/runtime/mcp/handlers.d.ts.map +0 -1
- package/dist/runtime/mcp/handlers.js +0 -1025
- package/dist/runtime/mcp/handlers.js.map +0 -1
- package/dist/runtime/mcp/index.d.ts +0 -7
- package/dist/runtime/mcp/index.d.ts.map +0 -1
- package/dist/runtime/mcp/index.js +0 -7
- package/dist/runtime/mcp/index.js.map +0 -1
- package/dist/runtime/mcp/notifications.d.ts +0 -47
- package/dist/runtime/mcp/notifications.d.ts.map +0 -1
- package/dist/runtime/mcp/notifications.js +0 -204
- package/dist/runtime/mcp/notifications.js.map +0 -1
- package/dist/runtime/mcp/server.d.ts +0 -45
- package/dist/runtime/mcp/server.d.ts.map +0 -1
- package/dist/runtime/mcp/server.js +0 -94
- package/dist/runtime/mcp/server.js.map +0 -1
- package/dist/runtime/mcp/sessions.d.ts +0 -68
- package/dist/runtime/mcp/sessions.d.ts.map +0 -1
- package/dist/runtime/mcp/sessions.js +0 -152
- package/dist/runtime/mcp/sessions.js.map +0 -1
- package/dist/runtime/mcp/stdio.d.ts +0 -72
- package/dist/runtime/mcp/stdio.d.ts.map +0 -1
- package/dist/runtime/mcp/stdio.js +0 -274
- package/dist/runtime/mcp/stdio.js.map +0 -1
- package/dist/runtime/mcp/tools.d.ts +0 -19
- package/dist/runtime/mcp/tools.d.ts.map +0 -1
- package/dist/runtime/mcp/tools.js +0 -525
- package/dist/runtime/mcp/tools.js.map +0 -1
- package/dist/runtime/mcp-http/app.d.ts +0 -33
- package/dist/runtime/mcp-http/app.d.ts.map +0 -1
- package/dist/runtime/mcp-http/app.js +0 -162
- package/dist/runtime/mcp-http/app.js.map +0 -1
- package/dist/runtime/mcp-http/hosted-mcp-server.d.ts +0 -14
- package/dist/runtime/mcp-http/hosted-mcp-server.d.ts.map +0 -1
- package/dist/runtime/mcp-http/hosted-mcp-server.js +0 -38
- package/dist/runtime/mcp-http/hosted-mcp-server.js.map +0 -1
- package/dist/runtime/mcp-http/index.d.ts +0 -18
- package/dist/runtime/mcp-http/index.d.ts.map +0 -1
- package/dist/runtime/mcp-http/index.js +0 -18
- package/dist/runtime/mcp-http/index.js.map +0 -1
- package/dist/runtime/mcp-http/main.d.ts +0 -2
- package/dist/runtime/mcp-http/main.d.ts.map +0 -1
- package/dist/runtime/mcp-http/main.js +0 -14
- package/dist/runtime/mcp-http/main.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/broker-login.d.ts +0 -50
- package/dist/runtime/mcp-http/oauth/broker-login.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/broker-login.js +0 -41
- package/dist/runtime/mcp-http/oauth/broker-login.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/broker-routes.d.ts +0 -45
- package/dist/runtime/mcp-http/oauth/broker-routes.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/broker-routes.js +0 -54
- package/dist/runtime/mcp-http/oauth/broker-routes.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/config.d.ts +0 -49
- package/dist/runtime/mcp-http/oauth/config.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/config.js +0 -69
- package/dist/runtime/mcp-http/oauth/config.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/crypto.d.ts +0 -14
- package/dist/runtime/mcp-http/oauth/crypto.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/crypto.js +0 -29
- package/dist/runtime/mcp-http/oauth/crypto.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/file-store.d.ts +0 -48
- package/dist/runtime/mcp-http/oauth/file-store.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/file-store.js +0 -101
- package/dist/runtime/mcp-http/oauth/file-store.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/hono-oauth-router.d.ts +0 -5
- package/dist/runtime/mcp-http/oauth/hono-oauth-router.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/hono-oauth-router.js +0 -92
- package/dist/runtime/mcp-http/oauth/hono-oauth-router.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/oidc-rp.d.ts +0 -56
- package/dist/runtime/mcp-http/oauth/oidc-rp.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/oidc-rp.js +0 -63
- package/dist/runtime/mcp-http/oauth/oidc-rp.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/redirect-uri.d.ts +0 -11
- package/dist/runtime/mcp-http/oauth/redirect-uri.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/redirect-uri.js +0 -29
- package/dist/runtime/mcp-http/oauth/redirect-uri.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/single-tenant-provider.d.ts +0 -70
- package/dist/runtime/mcp-http/oauth/single-tenant-provider.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/single-tenant-provider.js +0 -247
- package/dist/runtime/mcp-http/oauth/single-tenant-provider.js.map +0 -1
- package/dist/runtime/mcp-http/oauth/tenancy.d.ts +0 -3
- package/dist/runtime/mcp-http/oauth/tenancy.d.ts.map +0 -1
- package/dist/runtime/mcp-http/oauth/tenancy.js +0 -18
- package/dist/runtime/mcp-http/oauth/tenancy.js.map +0 -1
- package/dist/runtime/mcp-http/readonly-allowlist.d.ts +0 -24
- package/dist/runtime/mcp-http/readonly-allowlist.d.ts.map +0 -1
- package/dist/runtime/mcp-http/readonly-allowlist.js +0 -43
- package/dist/runtime/mcp-http/readonly-allowlist.js.map +0 -1
- package/dist/runtime/mcp-http/serve.d.ts +0 -39
- package/dist/runtime/mcp-http/serve.d.ts.map +0 -1
- package/dist/runtime/mcp-http/serve.js +0 -100
- package/dist/runtime/mcp-http/serve.js.map +0 -1
- package/dist/runtime/mirror/accept.d.ts +0 -57
- package/dist/runtime/mirror/accept.d.ts.map +0 -1
- package/dist/runtime/mirror/accept.js +0 -70
- package/dist/runtime/mirror/accept.js.map +0 -1
- package/dist/runtime/mirror/build.d.ts +0 -44
- package/dist/runtime/mirror/build.d.ts.map +0 -1
- package/dist/runtime/mirror/build.js +0 -37
- package/dist/runtime/mirror/build.js.map +0 -1
- package/dist/runtime/mirror/index.d.ts +0 -9
- package/dist/runtime/mirror/index.d.ts.map +0 -1
- package/dist/runtime/mirror/index.js +0 -9
- package/dist/runtime/mirror/index.js.map +0 -1
- package/dist/runtime/mirror/serve.d.ts +0 -21
- package/dist/runtime/mirror/serve.d.ts.map +0 -1
- package/dist/runtime/mirror/serve.js +0 -141
- package/dist/runtime/mirror/serve.js.map +0 -1
- package/dist/runtime/nhi.d.ts +0 -15
- package/dist/runtime/nhi.d.ts.map +0 -1
- package/dist/runtime/nhi.js +0 -26
- package/dist/runtime/nhi.js.map +0 -1
- package/dist/runtime/remote/accept.d.ts +0 -50
- package/dist/runtime/remote/accept.d.ts.map +0 -1
- package/dist/runtime/remote/accept.js +0 -54
- package/dist/runtime/remote/accept.js.map +0 -1
- package/dist/runtime/remote/client.d.ts +0 -27
- package/dist/runtime/remote/client.d.ts.map +0 -1
- package/dist/runtime/remote/client.js +0 -34
- package/dist/runtime/remote/client.js.map +0 -1
- package/dist/runtime/remote/index.d.ts +0 -5
- package/dist/runtime/remote/index.d.ts.map +0 -1
- package/dist/runtime/remote/index.js +0 -5
- package/dist/runtime/remote/index.js.map +0 -1
- package/dist/runtime/remote/serve.d.ts +0 -27
- package/dist/runtime/remote/serve.d.ts.map +0 -1
- package/dist/runtime/remote/serve.js +0 -26
- package/dist/runtime/remote/serve.js.map +0 -1
- package/dist/runtime/remote/server.d.ts +0 -36
- package/dist/runtime/remote/server.d.ts.map +0 -1
- package/dist/runtime/remote/server.js +0 -100
- package/dist/runtime/remote/server.js.map +0 -1
- package/dist/runtime/sysml/client.d.ts +0 -44
- package/dist/runtime/sysml/client.d.ts.map +0 -1
- package/dist/runtime/sysml/client.js +0 -52
- package/dist/runtime/sysml/client.js.map +0 -1
- package/dist/runtime/sysml/disclosure.d.ts +0 -23
- package/dist/runtime/sysml/disclosure.d.ts.map +0 -1
- package/dist/runtime/sysml/disclosure.js +0 -53
- package/dist/runtime/sysml/disclosure.js.map +0 -1
- package/dist/runtime/sysml/index.d.ts +0 -4
- package/dist/runtime/sysml/index.d.ts.map +0 -1
- package/dist/runtime/sysml/index.js +0 -4
- package/dist/runtime/sysml/index.js.map +0 -1
- package/dist/runtime/sysml/verify.d.ts +0 -32
- package/dist/runtime/sysml/verify.d.ts.map +0 -1
- package/dist/runtime/sysml/verify.js +0 -67
- package/dist/runtime/sysml/verify.js.map +0 -1
- package/dist/runtime/upgrade/index.d.ts +0 -96
- package/dist/runtime/upgrade/index.d.ts.map +0 -1
- package/dist/runtime/upgrade/index.js +0 -185
- package/dist/runtime/upgrade/index.js.map +0 -1
- package/dist/runtime/version/agent-version.d.ts +0 -15
- package/dist/runtime/version/agent-version.d.ts.map +0 -1
- package/dist/runtime/version/agent-version.js +0 -53
- package/dist/runtime/version/agent-version.js.map +0 -1
- package/skills/h2a/SKILL.md +0 -345
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-host lease lock for the local-files store (DEC-065).
|
|
3
|
-
*
|
|
4
|
-
* The advisory lock in `locks.ts` (DEC-036) recovers stale locks via
|
|
5
|
-
* `process.kill(pid, 0)` — which only works **same-machine**. A store shared
|
|
6
|
-
* across Pods on a ReadWriteMany volume (Scenario B of DEC-056) has holders on
|
|
7
|
-
* different nodes that cannot probe each other's PIDs, so the PID model is
|
|
8
|
-
* unsafe there.
|
|
9
|
-
*
|
|
10
|
-
* This module replaces PID-liveness with a **time-based lease**:
|
|
11
|
-
*
|
|
12
|
-
* - The lock file carries `{ holder, nonce, acquiredAt, renewedAt, leaseMs,
|
|
13
|
-
* fencingToken }`.
|
|
14
|
-
* - A lease is *expired* when `now - renewedAt > leaseMs`. Any contender may
|
|
15
|
-
* then steal it. Staleness is decided purely by wall-clock time, so it works
|
|
16
|
-
* regardless of which host or Pod held it.
|
|
17
|
-
* - The atomic gate is `openSync(path, "wx")` (`O_CREAT | O_EXCL`): only one
|
|
18
|
-
* contender wins the create, even across hosts on a POSIX-compliant shared
|
|
19
|
-
* filesystem.
|
|
20
|
-
* - `nonce` is a random per-acquisition id; release only unlinks the file if
|
|
21
|
-
* the on-disk nonce still matches ours (so a holder that overran its lease
|
|
22
|
-
* and was stolen from does not delete the new holder's lease).
|
|
23
|
-
* - `fencingToken` is incremented on every steal (best-effort monotonic) and
|
|
24
|
-
* returned to the caller for observability / downstream fencing.
|
|
25
|
-
*
|
|
26
|
-
* Clock-skew caveat: `leaseMs` must comfortably exceed (a) the longest
|
|
27
|
-
* critical section plus (b) the maximum clock skew between hosts. The store's
|
|
28
|
-
* read-then-write sections are sub-second, so the default 30s lease leaves a
|
|
29
|
-
* wide margin. This is documented in DEC-065.
|
|
30
|
-
*/
|
|
31
|
-
import { type WithLockOptions } from "./locks.js";
|
|
32
|
-
export interface LeaseRecord {
|
|
33
|
-
readonly holder: string;
|
|
34
|
-
readonly nonce: string;
|
|
35
|
-
readonly acquiredAt: string;
|
|
36
|
-
readonly renewedAt: string;
|
|
37
|
-
readonly leaseMs: number;
|
|
38
|
-
readonly fencingToken: number;
|
|
39
|
-
}
|
|
40
|
-
export interface WithLeaseOptions extends WithLockOptions {
|
|
41
|
-
/** Lease duration in ms. A lease older than this is stealable. Default 30000. */
|
|
42
|
-
readonly leaseMs?: number;
|
|
43
|
-
/** Holder label (host + pid by default). Informational. */
|
|
44
|
-
readonly holder?: string;
|
|
45
|
-
}
|
|
46
|
-
export interface LeaseHandle {
|
|
47
|
-
readonly nonce: string;
|
|
48
|
-
readonly fencingToken: number;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Synchronous lease-locked critical section. Mirrors `withLockSync` but uses
|
|
52
|
-
* the time-based lease above, so it is safe for cross-host (cross-Pod) shared
|
|
53
|
-
* stores. Returns `fn()`'s result. Throws `LockTimeoutError` if the lease
|
|
54
|
-
* cannot be acquired within `timeoutMs`.
|
|
55
|
-
*
|
|
56
|
-
* The handle (nonce + fencingToken) is exposed to `fn` so callers that need
|
|
57
|
-
* to fence a downstream side-effect can read the token.
|
|
58
|
-
*/
|
|
59
|
-
export declare function withLeaseSync<T>(lockPath: string, fn: (handle: LeaseHandle) => T, options?: WithLeaseOptions): T;
|
|
60
|
-
/** Async variant of {@link withLeaseSync}. */
|
|
61
|
-
export declare function withLease<T>(lockPath: string, fn: (handle: LeaseHandle) => T | Promise<T>, options?: WithLeaseOptions): Promise<T>;
|
|
62
|
-
//# sourceMappingURL=lease.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../../../src/runtime/local-files/lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAYH,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAEpE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAiB,SAAQ,eAAe;IACvD,iFAAiF;IACjF,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;CAC/B;AA2JD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,EAC9B,OAAO,GAAE,gBAAqB,GAC7B,CAAC,CAqCH;AAED,8CAA8C;AAC9C,wBAAsB,SAAS,CAAC,CAAC,EAC/B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EAC3C,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,CAAC,CAAC,CAiCZ"}
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-host lease lock for the local-files store (DEC-065).
|
|
3
|
-
*
|
|
4
|
-
* The advisory lock in `locks.ts` (DEC-036) recovers stale locks via
|
|
5
|
-
* `process.kill(pid, 0)` — which only works **same-machine**. A store shared
|
|
6
|
-
* across Pods on a ReadWriteMany volume (Scenario B of DEC-056) has holders on
|
|
7
|
-
* different nodes that cannot probe each other's PIDs, so the PID model is
|
|
8
|
-
* unsafe there.
|
|
9
|
-
*
|
|
10
|
-
* This module replaces PID-liveness with a **time-based lease**:
|
|
11
|
-
*
|
|
12
|
-
* - The lock file carries `{ holder, nonce, acquiredAt, renewedAt, leaseMs,
|
|
13
|
-
* fencingToken }`.
|
|
14
|
-
* - A lease is *expired* when `now - renewedAt > leaseMs`. Any contender may
|
|
15
|
-
* then steal it. Staleness is decided purely by wall-clock time, so it works
|
|
16
|
-
* regardless of which host or Pod held it.
|
|
17
|
-
* - The atomic gate is `openSync(path, "wx")` (`O_CREAT | O_EXCL`): only one
|
|
18
|
-
* contender wins the create, even across hosts on a POSIX-compliant shared
|
|
19
|
-
* filesystem.
|
|
20
|
-
* - `nonce` is a random per-acquisition id; release only unlinks the file if
|
|
21
|
-
* the on-disk nonce still matches ours (so a holder that overran its lease
|
|
22
|
-
* and was stolen from does not delete the new holder's lease).
|
|
23
|
-
* - `fencingToken` is incremented on every steal (best-effort monotonic) and
|
|
24
|
-
* returned to the caller for observability / downstream fencing.
|
|
25
|
-
*
|
|
26
|
-
* Clock-skew caveat: `leaseMs` must comfortably exceed (a) the longest
|
|
27
|
-
* critical section plus (b) the maximum clock skew between hosts. The store's
|
|
28
|
-
* read-then-write sections are sub-second, so the default 30s lease leaves a
|
|
29
|
-
* wide margin. This is documented in DEC-065.
|
|
30
|
-
*/
|
|
31
|
-
import { closeSync, openSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
32
|
-
import { hostname } from "node:os";
|
|
33
|
-
import { randomBytes } from "node:crypto";
|
|
34
|
-
import { LockTimeoutError } from "./locks.js";
|
|
35
|
-
const DEFAULT_LEASE_MS = 30000;
|
|
36
|
-
const DEFAULT_TIMEOUT_MS = 5000;
|
|
37
|
-
const DEFAULT_POLL_MS = 50;
|
|
38
|
-
function nowMs() {
|
|
39
|
-
return Date.now();
|
|
40
|
-
}
|
|
41
|
-
function parseLease(raw) {
|
|
42
|
-
try {
|
|
43
|
-
const p = JSON.parse(raw);
|
|
44
|
-
if (p &&
|
|
45
|
-
typeof p.holder === "string" &&
|
|
46
|
-
typeof p.nonce === "string" &&
|
|
47
|
-
typeof p.renewedAt === "string" &&
|
|
48
|
-
typeof p.leaseMs === "number" &&
|
|
49
|
-
typeof p.fencingToken === "number") {
|
|
50
|
-
return {
|
|
51
|
-
holder: p.holder,
|
|
52
|
-
nonce: p.nonce,
|
|
53
|
-
acquiredAt: typeof p.acquiredAt === "string" ? p.acquiredAt : p.renewedAt,
|
|
54
|
-
renewedAt: p.renewedAt,
|
|
55
|
-
leaseMs: p.leaseMs,
|
|
56
|
-
fencingToken: p.fencingToken
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
/* malformed — treat as absent */
|
|
62
|
-
}
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
function isExpired(lease, at) {
|
|
66
|
-
const renewed = Date.parse(lease.renewedAt);
|
|
67
|
-
if (Number.isNaN(renewed))
|
|
68
|
-
return true;
|
|
69
|
-
return at - renewed > lease.leaseMs;
|
|
70
|
-
}
|
|
71
|
-
function writeLease(lockPath, record) {
|
|
72
|
-
const fd = openSync(lockPath, "wx");
|
|
73
|
-
try {
|
|
74
|
-
writeFileSync(fd, JSON.stringify(record));
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
closeSync(fd);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
function attemptAcquire(lockPath, holder, leaseMs) {
|
|
81
|
-
const at = nowMs();
|
|
82
|
-
const iso = new Date(at).toISOString();
|
|
83
|
-
const nonce = randomBytes(8).toString("hex");
|
|
84
|
-
// Fresh create path — token starts at 1.
|
|
85
|
-
const fresh = {
|
|
86
|
-
holder,
|
|
87
|
-
nonce,
|
|
88
|
-
acquiredAt: iso,
|
|
89
|
-
renewedAt: iso,
|
|
90
|
-
leaseMs,
|
|
91
|
-
fencingToken: 1
|
|
92
|
-
};
|
|
93
|
-
try {
|
|
94
|
-
writeLease(lockPath, fresh);
|
|
95
|
-
return { ok: true, handle: { nonce, fencingToken: 1 } };
|
|
96
|
-
}
|
|
97
|
-
catch (err) {
|
|
98
|
-
if (err.code !== "EEXIST")
|
|
99
|
-
throw err;
|
|
100
|
-
}
|
|
101
|
-
// Lock exists — read and decide.
|
|
102
|
-
let raw;
|
|
103
|
-
try {
|
|
104
|
-
raw = readFileSync(lockPath, "utf8");
|
|
105
|
-
}
|
|
106
|
-
catch {
|
|
107
|
-
// Released between EEXIST and read — caller retries.
|
|
108
|
-
return { ok: false };
|
|
109
|
-
}
|
|
110
|
-
const existing = parseLease(raw);
|
|
111
|
-
if (existing && !isExpired(existing, at)) {
|
|
112
|
-
return { ok: false, lastSeen: existing };
|
|
113
|
-
}
|
|
114
|
-
// Expired (or malformed) — steal it. Unlink then re-create via O_EXCL so the
|
|
115
|
-
// create remains the atomic gate; the create-winner writes oldToken+1.
|
|
116
|
-
const nextToken = (existing?.fencingToken ?? 0) + 1;
|
|
117
|
-
try {
|
|
118
|
-
unlinkSync(lockPath);
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
/* someone else reclaimed first — fall through to retry */
|
|
122
|
-
}
|
|
123
|
-
const stolen = {
|
|
124
|
-
holder,
|
|
125
|
-
nonce,
|
|
126
|
-
acquiredAt: iso,
|
|
127
|
-
renewedAt: iso,
|
|
128
|
-
leaseMs,
|
|
129
|
-
fencingToken: nextToken
|
|
130
|
-
};
|
|
131
|
-
try {
|
|
132
|
-
writeLease(lockPath, stolen);
|
|
133
|
-
return { ok: true, handle: { nonce, fencingToken: nextToken } };
|
|
134
|
-
}
|
|
135
|
-
catch (err) {
|
|
136
|
-
if (err.code === "EEXIST") {
|
|
137
|
-
// Another contender won the steal — retry from the top next loop.
|
|
138
|
-
return { ok: false, lastSeen: existing };
|
|
139
|
-
}
|
|
140
|
-
throw err;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
function releaseLease(lockPath, handle) {
|
|
144
|
-
let raw;
|
|
145
|
-
try {
|
|
146
|
-
raw = readFileSync(lockPath, "utf8");
|
|
147
|
-
}
|
|
148
|
-
catch {
|
|
149
|
-
return; // already gone
|
|
150
|
-
}
|
|
151
|
-
const current = parseLease(raw);
|
|
152
|
-
// Only unlink if WE still hold it (nonce match). If a contender stole the
|
|
153
|
-
// lease after we overran it, leave their lease intact.
|
|
154
|
-
if (current && current.nonce === handle.nonce) {
|
|
155
|
-
try {
|
|
156
|
-
unlinkSync(lockPath);
|
|
157
|
-
}
|
|
158
|
-
catch {
|
|
159
|
-
/* concurrent release — fine */
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
function busyWaitSync(ms) {
|
|
164
|
-
const end = Date.now() + ms;
|
|
165
|
-
const sab = new SharedArrayBuffer(4);
|
|
166
|
-
const view = new Int32Array(sab);
|
|
167
|
-
while (Date.now() < end) {
|
|
168
|
-
const remaining = end - Date.now();
|
|
169
|
-
if (remaining <= 0)
|
|
170
|
-
break;
|
|
171
|
-
Atomics.wait(view, 0, 0, Math.min(remaining, 25));
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function defaultHolder() {
|
|
175
|
-
return `${hostname()}:${process.pid}`;
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Synchronous lease-locked critical section. Mirrors `withLockSync` but uses
|
|
179
|
-
* the time-based lease above, so it is safe for cross-host (cross-Pod) shared
|
|
180
|
-
* stores. Returns `fn()`'s result. Throws `LockTimeoutError` if the lease
|
|
181
|
-
* cannot be acquired within `timeoutMs`.
|
|
182
|
-
*
|
|
183
|
-
* The handle (nonce + fencingToken) is exposed to `fn` so callers that need
|
|
184
|
-
* to fence a downstream side-effect can read the token.
|
|
185
|
-
*/
|
|
186
|
-
export function withLeaseSync(lockPath, fn, options = {}) {
|
|
187
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
188
|
-
const pollMs = options.pollMs ?? DEFAULT_POLL_MS;
|
|
189
|
-
const leaseMs = options.leaseMs ?? DEFAULT_LEASE_MS;
|
|
190
|
-
const holder = options.holder ?? defaultHolder();
|
|
191
|
-
const deadline = Date.now() + timeoutMs;
|
|
192
|
-
let lastSeen;
|
|
193
|
-
let handle;
|
|
194
|
-
while (true) {
|
|
195
|
-
const attempt = attemptAcquire(lockPath, holder, leaseMs);
|
|
196
|
-
if (attempt.ok) {
|
|
197
|
-
handle = attempt.handle;
|
|
198
|
-
break;
|
|
199
|
-
}
|
|
200
|
-
lastSeen = attempt.lastSeen ?? lastSeen;
|
|
201
|
-
if (Date.now() >= deadline) {
|
|
202
|
-
throw new LockTimeoutError(lockPath, lastSeen
|
|
203
|
-
? {
|
|
204
|
-
pid: 0,
|
|
205
|
-
hostname: lastSeen.holder,
|
|
206
|
-
startedAt: lastSeen.acquiredAt
|
|
207
|
-
}
|
|
208
|
-
: undefined, timeoutMs);
|
|
209
|
-
}
|
|
210
|
-
busyWaitSync(pollMs);
|
|
211
|
-
}
|
|
212
|
-
try {
|
|
213
|
-
return fn(handle);
|
|
214
|
-
}
|
|
215
|
-
finally {
|
|
216
|
-
releaseLease(lockPath, handle);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
/** Async variant of {@link withLeaseSync}. */
|
|
220
|
-
export async function withLease(lockPath, fn, options = {}) {
|
|
221
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
222
|
-
const pollMs = options.pollMs ?? DEFAULT_POLL_MS;
|
|
223
|
-
const leaseMs = options.leaseMs ?? DEFAULT_LEASE_MS;
|
|
224
|
-
const holder = options.holder ?? defaultHolder();
|
|
225
|
-
const deadline = Date.now() + timeoutMs;
|
|
226
|
-
let lastSeen;
|
|
227
|
-
let handle;
|
|
228
|
-
while (true) {
|
|
229
|
-
const attempt = attemptAcquire(lockPath, holder, leaseMs);
|
|
230
|
-
if (attempt.ok) {
|
|
231
|
-
handle = attempt.handle;
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
lastSeen = attempt.lastSeen ?? lastSeen;
|
|
235
|
-
if (Date.now() >= deadline) {
|
|
236
|
-
throw new LockTimeoutError(lockPath, lastSeen
|
|
237
|
-
? { pid: 0, hostname: lastSeen.holder, startedAt: lastSeen.acquiredAt }
|
|
238
|
-
: undefined, timeoutMs);
|
|
239
|
-
}
|
|
240
|
-
await new Promise((r) => setTimeout(r, pollMs));
|
|
241
|
-
}
|
|
242
|
-
try {
|
|
243
|
-
return await fn(handle);
|
|
244
|
-
}
|
|
245
|
-
finally {
|
|
246
|
-
releaseLease(lockPath, handle);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
//# sourceMappingURL=lease.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"lease.js","sourceRoot":"","sources":["../../../src/runtime/local-files/lease.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,OAAO,EACL,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,aAAa,EACd,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EAAE,gBAAgB,EAAwB,MAAM,YAAY,CAAC;AAuBpE,MAAM,gBAAgB,GAAG,KAAK,CAAC;AAC/B,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAChC,MAAM,eAAe,GAAG,EAAE,CAAC;AAE3B,SAAS,KAAK;IACZ,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;AACpB,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QAClD,IACE,CAAC;YACD,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ;YAC5B,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ;YAC3B,OAAO,CAAC,CAAC,SAAS,KAAK,QAAQ;YAC/B,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;YAC7B,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,EAClC,CAAC;YACD,OAAO;gBACL,MAAM,EAAE,CAAC,CAAC,MAAM;gBAChB,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,UAAU,EAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS;gBACzE,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,OAAO,EAAE,CAAC,CAAC,OAAO;gBAClB,YAAY,EAAE,CAAC,CAAC,YAAY;aAC7B,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,iCAAiC;IACnC,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,SAAS,CAAC,KAAkB,EAAE,EAAU;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,EAAE,GAAG,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB,EAAE,MAAmB;IACvD,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;AACH,CAAC;AAMD,SAAS,cAAc,CACrB,QAAgB,EAChB,MAAc,EACd,OAAe;IAEf,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IACvC,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE7C,yCAAyC;IACzC,MAAM,KAAK,GAAgB;QACzB,MAAM;QACN,KAAK;QACL,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,GAAG;QACd,OAAO;QACP,YAAY,EAAE,CAAC;KAChB,CAAC;IACF,IAAI,CAAC;QACH,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC;IAC1D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,GAAG,CAAC;IAClE,CAAC;IAED,iCAAiC;IACjC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,qDAAqD;QACrD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC;QACzC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IAC3C,CAAC;IAED,6EAA6E;IAC7E,uEAAuE;IACvE,MAAM,SAAS,GAAG,CAAC,QAAQ,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,UAAU,CAAC,QAAQ,CAAC,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;IACD,MAAM,MAAM,GAAgB;QAC1B,MAAM;QACN,KAAK;QACL,UAAU,EAAE,GAAG;QACf,SAAS,EAAE,GAAG;QACd,OAAO;QACP,YAAY,EAAE,SAAS;KACxB,CAAC;IACF,IAAI,CAAC;QACH,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,CAAC;IAClE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,kEAAkE;YAClE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;QAC3C,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,QAAgB,EAAE,MAAmB;IACzD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,eAAe;IACzB,CAAC;IACD,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAChC,0EAA0E;IAC1E,uDAAuD;IACvD,IAAI,OAAO,IAAI,OAAO,CAAC,KAAK,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC;QAC9C,IAAI,CAAC;YACH,UAAU,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,EAAU;IAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAC5B,MAAM,GAAG,GAAG,IAAI,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;QACxB,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACnC,IAAI,SAAS,IAAI,CAAC;YAAE,MAAM;QAC1B,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED,SAAS,aAAa;IACpB,OAAO,GAAG,QAAQ,EAAE,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAC3B,QAAgB,EAChB,EAA8B,EAC9B,UAA4B,EAAE;IAE9B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;IACjD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IAEjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,IAAI,QAAiC,CAAC;IACtC,IAAI,MAA+B,CAAC;IACpC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YACxB,MAAM;QACR,CAAC;QACD,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;QACxC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,gBAAgB,CACxB,QAAQ,EACR,QAAQ;gBACN,CAAC,CAAC;oBACE,GAAG,EAAE,CAAC;oBACN,QAAQ,EAAE,QAAQ,CAAC,MAAM;oBACzB,SAAS,EAAE,QAAQ,CAAC,UAAU;iBAC/B;gBACH,CAAC,CAAC,SAAS,EACb,SAAS,CACV,CAAC;QACJ,CAAC;QACD,YAAY,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,8CAA8C;AAC9C,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,QAAgB,EAChB,EAA2C,EAC3C,UAA4B,EAAE;IAE9B,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,kBAAkB,CAAC;IAC1D,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,eAAe,CAAC;IACjD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,gBAAgB,CAAC;IACpD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;IAEjD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IACxC,IAAI,QAAiC,CAAC;IACtC,IAAI,MAA+B,CAAC;IACpC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YACxB,MAAM;QACR,CAAC;QACD,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,QAAQ,CAAC;QACxC,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,QAAQ,EAAE,CAAC;YAC3B,MAAM,IAAI,gBAAgB,CACxB,QAAQ,EACR,QAAQ;gBACN,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC,UAAU,EAAE;gBACvE,CAAC,CAAC,SAAS,EACb,SAAS,CACV,CAAC;QACJ,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACjC,CAAC;AACH,CAAC"}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Advisory file locking for the local-files store (DEC-036).
|
|
3
|
-
*
|
|
4
|
-
* The store layout (DEC-031) was originally written under the assumption that
|
|
5
|
-
* a single CLI/MCP process owned the `<root>/.h2a/` tree at any given time.
|
|
6
|
-
* In practice, multiple `h2a` invocations and an `h2a mcp-serve` process can
|
|
7
|
-
* race on the same root. Append-only JSONL files (`registry/instances.jsonl`,
|
|
8
|
-
* `negotiations/<id>/journal.jsonl`) survive this via the `PIPE_BUF`
|
|
9
|
-
* atomicity of `appendFileSync` for sub-4KB lines, but every read-then-write
|
|
10
|
-
* critical section (dup detection on `registerInstance`, hash-chain link on
|
|
11
|
-
* `appendNegotiationEvent`, the whole `stabilizeNegotiation` transaction)
|
|
12
|
-
* remains a race.
|
|
13
|
-
*
|
|
14
|
-
* This module implements **advisory** file locking via exclusive-create
|
|
15
|
-
* sentinel files (`O_CREAT | O_EXCL` semantics through `openSync(path, "wx")`).
|
|
16
|
-
* It is intentionally limited to **same-machine** coordination: a lock file
|
|
17
|
-
* holding a foreign-host PID would be treated as live (we cannot
|
|
18
|
-
* `process.kill(pid, 0)` across hosts). Cross-machine sharing of a store
|
|
19
|
-
* remains out of scope (V2).
|
|
20
|
-
*
|
|
21
|
-
* Stale-lock recovery: if the lock file already exists, we parse its JSON
|
|
22
|
-
* payload `{pid, hostname, startedAt}`. If `hostname` matches and the PID is
|
|
23
|
-
* gone (`process.kill(pid, 0)` throws `ESRCH`), we reclaim the lock by
|
|
24
|
-
* unlinking and retrying. Otherwise we poll up to `timeoutMs` and throw
|
|
25
|
-
* `LockTimeoutError`.
|
|
26
|
-
*/
|
|
27
|
-
export interface LockOwner {
|
|
28
|
-
readonly pid: number;
|
|
29
|
-
readonly hostname: string;
|
|
30
|
-
readonly startedAt: string;
|
|
31
|
-
}
|
|
32
|
-
export interface WithLockOptions {
|
|
33
|
-
readonly timeoutMs?: number;
|
|
34
|
-
readonly pollMs?: number;
|
|
35
|
-
}
|
|
36
|
-
export declare class LockTimeoutError extends Error {
|
|
37
|
-
readonly lockPath: string;
|
|
38
|
-
readonly lastSeenOwner?: LockOwner;
|
|
39
|
-
constructor(lockPath: string, lastSeenOwner: LockOwner | undefined, timeoutMs: number);
|
|
40
|
-
}
|
|
41
|
-
export declare function withLock<T>(lockPath: string, fn: () => T | Promise<T>, options?: WithLockOptions): Promise<T>;
|
|
42
|
-
export declare function withLockSync<T>(lockPath: string, fn: () => T, options?: WithLockOptions): T;
|
|
43
|
-
//# sourceMappingURL=locks.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"locks.d.ts","sourceRoot":"","sources":["../../../src/runtime/local-files/locks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAKH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,aAAa,CAAC,EAAE,SAAS,CAAC;gBAEvB,QAAQ,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM;CAWtF;AAqGD,wBAAsB,QAAQ,CAAC,CAAC,EAC9B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,EACxB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,CAAC,CAAC,CA0BZ;AAED,wBAAgB,YAAY,CAAC,CAAC,EAC5B,QAAQ,EAAE,MAAM,EAChB,EAAE,EAAE,MAAM,CAAC,EACX,OAAO,GAAE,eAAoB,GAC5B,CAAC,CA0BH"}
|
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Advisory file locking for the local-files store (DEC-036).
|
|
3
|
-
*
|
|
4
|
-
* The store layout (DEC-031) was originally written under the assumption that
|
|
5
|
-
* a single CLI/MCP process owned the `<root>/.h2a/` tree at any given time.
|
|
6
|
-
* In practice, multiple `h2a` invocations and an `h2a mcp-serve` process can
|
|
7
|
-
* race on the same root. Append-only JSONL files (`registry/instances.jsonl`,
|
|
8
|
-
* `negotiations/<id>/journal.jsonl`) survive this via the `PIPE_BUF`
|
|
9
|
-
* atomicity of `appendFileSync` for sub-4KB lines, but every read-then-write
|
|
10
|
-
* critical section (dup detection on `registerInstance`, hash-chain link on
|
|
11
|
-
* `appendNegotiationEvent`, the whole `stabilizeNegotiation` transaction)
|
|
12
|
-
* remains a race.
|
|
13
|
-
*
|
|
14
|
-
* This module implements **advisory** file locking via exclusive-create
|
|
15
|
-
* sentinel files (`O_CREAT | O_EXCL` semantics through `openSync(path, "wx")`).
|
|
16
|
-
* It is intentionally limited to **same-machine** coordination: a lock file
|
|
17
|
-
* holding a foreign-host PID would be treated as live (we cannot
|
|
18
|
-
* `process.kill(pid, 0)` across hosts). Cross-machine sharing of a store
|
|
19
|
-
* remains out of scope (V2).
|
|
20
|
-
*
|
|
21
|
-
* Stale-lock recovery: if the lock file already exists, we parse its JSON
|
|
22
|
-
* payload `{pid, hostname, startedAt}`. If `hostname` matches and the PID is
|
|
23
|
-
* gone (`process.kill(pid, 0)` throws `ESRCH`), we reclaim the lock by
|
|
24
|
-
* unlinking and retrying. Otherwise we poll up to `timeoutMs` and throw
|
|
25
|
-
* `LockTimeoutError`.
|
|
26
|
-
*/
|
|
27
|
-
import { closeSync, openSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
28
|
-
import { hostname } from "node:os";
|
|
29
|
-
export class LockTimeoutError extends Error {
|
|
30
|
-
lockPath;
|
|
31
|
-
lastSeenOwner;
|
|
32
|
-
constructor(lockPath, lastSeenOwner, timeoutMs) {
|
|
33
|
-
const ownerSuffix = lastSeenOwner
|
|
34
|
-
? ` held by ${JSON.stringify(lastSeenOwner)}`
|
|
35
|
-
: "";
|
|
36
|
-
super(`LockTimeoutError: could not acquire ${lockPath} within ${timeoutMs}ms${ownerSuffix}`);
|
|
37
|
-
this.name = "LockTimeoutError";
|
|
38
|
-
this.lockPath = lockPath;
|
|
39
|
-
this.lastSeenOwner = lastSeenOwner;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
const DEFAULT_TIMEOUT_MS = 5000;
|
|
43
|
-
const DEFAULT_POLL_MS = 50;
|
|
44
|
-
function tryParseOwner(raw) {
|
|
45
|
-
try {
|
|
46
|
-
const parsed = JSON.parse(raw);
|
|
47
|
-
if (parsed &&
|
|
48
|
-
typeof parsed.pid === "number" &&
|
|
49
|
-
typeof parsed.hostname === "string" &&
|
|
50
|
-
typeof parsed.startedAt === "string") {
|
|
51
|
-
return { pid: parsed.pid, hostname: parsed.hostname, startedAt: parsed.startedAt };
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
catch {
|
|
55
|
-
/* malformed — fall through */
|
|
56
|
-
}
|
|
57
|
-
return undefined;
|
|
58
|
-
}
|
|
59
|
-
function pidIsAliveOnSameHost(owner, selfHostname) {
|
|
60
|
-
if (owner.hostname !== selfHostname) {
|
|
61
|
-
// Cross-host owner: we cannot probe its liveness. Treat as live to err on
|
|
62
|
-
// the side of safety (the caller will then time out, which is the
|
|
63
|
-
// expected behaviour — cross-machine store sharing is out of scope V1).
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
try {
|
|
67
|
-
process.kill(owner.pid, 0);
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
const code = err.code;
|
|
72
|
-
if (code === "ESRCH")
|
|
73
|
-
return false;
|
|
74
|
-
// EPERM means the process exists but is owned by another user — still
|
|
75
|
-
// live for our purposes.
|
|
76
|
-
return true;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
function acquire(lockPath, selfHostname) {
|
|
80
|
-
const ownerPayload = {
|
|
81
|
-
pid: process.pid,
|
|
82
|
-
hostname: selfHostname,
|
|
83
|
-
startedAt: new Date().toISOString()
|
|
84
|
-
};
|
|
85
|
-
try {
|
|
86
|
-
const fd = openSync(lockPath, "wx");
|
|
87
|
-
try {
|
|
88
|
-
writeFileSync(fd, JSON.stringify(ownerPayload));
|
|
89
|
-
}
|
|
90
|
-
finally {
|
|
91
|
-
closeSync(fd);
|
|
92
|
-
}
|
|
93
|
-
return { ok: true };
|
|
94
|
-
}
|
|
95
|
-
catch (err) {
|
|
96
|
-
const code = err.code;
|
|
97
|
-
if (code !== "EEXIST")
|
|
98
|
-
throw err;
|
|
99
|
-
}
|
|
100
|
-
// Lock exists — inspect the owner record for staleness.
|
|
101
|
-
let raw;
|
|
102
|
-
try {
|
|
103
|
-
raw = readFileSync(lockPath, "utf8");
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
// The lock was released between EEXIST and our read. Caller should retry.
|
|
107
|
-
return { ok: false };
|
|
108
|
-
}
|
|
109
|
-
const owner = tryParseOwner(raw);
|
|
110
|
-
if (owner && !pidIsAliveOnSameHost(owner, selfHostname)) {
|
|
111
|
-
// Stale: reclaim by unlinking. The next loop iteration retries the create.
|
|
112
|
-
try {
|
|
113
|
-
unlinkSync(lockPath);
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
/* concurrent reclaim — fine */
|
|
117
|
-
}
|
|
118
|
-
return { ok: false };
|
|
119
|
-
}
|
|
120
|
-
return { ok: false, lastSeen: owner };
|
|
121
|
-
}
|
|
122
|
-
function delay(ms) {
|
|
123
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
124
|
-
}
|
|
125
|
-
function busyWaitSync(ms) {
|
|
126
|
-
// Synchronous wait without blocking event-loop indefinitely. Used by
|
|
127
|
-
// `withLockSync` only — most store methods are sync today and we don't
|
|
128
|
-
// want to ripple `async` through them just for locking (DEC-036).
|
|
129
|
-
const end = Date.now() + ms;
|
|
130
|
-
// `Atomics.wait` on a private SharedArrayBuffer is the standard
|
|
131
|
-
// "sleep without spinning" primitive in modern Node.
|
|
132
|
-
const sab = new SharedArrayBuffer(4);
|
|
133
|
-
const view = new Int32Array(sab);
|
|
134
|
-
while (Date.now() < end) {
|
|
135
|
-
const remaining = end - Date.now();
|
|
136
|
-
if (remaining <= 0)
|
|
137
|
-
break;
|
|
138
|
-
Atomics.wait(view, 0, 0, Math.min(remaining, 25));
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
export async function withLock(lockPath, fn, options = {}) {
|
|
142
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
143
|
-
const pollMs = options.pollMs ?? DEFAULT_POLL_MS;
|
|
144
|
-
const selfHostname = hostname();
|
|
145
|
-
const deadline = Date.now() + timeoutMs;
|
|
146
|
-
let lastSeen;
|
|
147
|
-
while (true) {
|
|
148
|
-
const attempt = acquire(lockPath, selfHostname);
|
|
149
|
-
if (attempt.ok)
|
|
150
|
-
break;
|
|
151
|
-
lastSeen = attempt.lastSeen ?? lastSeen;
|
|
152
|
-
if (Date.now() >= deadline) {
|
|
153
|
-
throw new LockTimeoutError(lockPath, lastSeen, timeoutMs);
|
|
154
|
-
}
|
|
155
|
-
await delay(pollMs);
|
|
156
|
-
}
|
|
157
|
-
try {
|
|
158
|
-
return await fn();
|
|
159
|
-
}
|
|
160
|
-
finally {
|
|
161
|
-
try {
|
|
162
|
-
unlinkSync(lockPath);
|
|
163
|
-
}
|
|
164
|
-
catch {
|
|
165
|
-
/* lock file already gone — fine */
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
export function withLockSync(lockPath, fn, options = {}) {
|
|
170
|
-
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
171
|
-
const pollMs = options.pollMs ?? DEFAULT_POLL_MS;
|
|
172
|
-
const selfHostname = hostname();
|
|
173
|
-
const deadline = Date.now() + timeoutMs;
|
|
174
|
-
let lastSeen;
|
|
175
|
-
while (true) {
|
|
176
|
-
const attempt = acquire(lockPath, selfHostname);
|
|
177
|
-
if (attempt.ok)
|
|
178
|
-
break;
|
|
179
|
-
lastSeen = attempt.lastSeen ?? lastSeen;
|
|
180
|
-
if (Date.now() >= deadline) {
|
|
181
|
-
throw new LockTimeoutError(lockPath, lastSeen, timeoutMs);
|
|
182
|
-
}
|
|
183
|
-
busyWaitSync(pollMs);
|
|
184
|
-
}
|
|
185
|
-
try {
|
|
186
|
-
return fn();
|
|
187
|
-
}
|
|
188
|
-
finally {
|
|
189
|
-
try {
|
|
190
|
-
unlinkSync(lockPath);
|
|
191
|
-
}
|
|
192
|
-
catch {
|
|
193
|
-
/* lock file already gone — fine */
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
//# sourceMappingURL=locks.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"locks.js","sourceRoot":"","sources":["../../../src/runtime/local-files/locks.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export interface SanitizeRenameEntry {
|
|
2
|
-
readonly from: string;
|
|
3
|
-
readonly to: string;
|
|
4
|
-
readonly status: "renamed" | "would-rename" | "conflict" | "skipped";
|
|
5
|
-
}
|
|
6
|
-
export interface SanitizePathsResult {
|
|
7
|
-
readonly ok: boolean;
|
|
8
|
-
readonly root: string;
|
|
9
|
-
readonly dryRun: boolean;
|
|
10
|
-
readonly renamed: readonly SanitizeRenameEntry[];
|
|
11
|
-
readonly conflicts: readonly SanitizeRenameEntry[];
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* DEC-064: rename pre-DEC-062 store entries whose names contain `:` (or other
|
|
15
|
-
* Windows-forbidden characters) to their `safePathSegment` form. This makes a
|
|
16
|
-
* store created by `@sentropic/h2a-cli@<=0.1.23` usable on Windows and
|
|
17
|
-
* consistent with the current layout on every OS.
|
|
18
|
-
*
|
|
19
|
-
* The pass is conservative:
|
|
20
|
-
* - It only renames entries whose sanitized name differs from the original.
|
|
21
|
-
* - If the sanitized target already exists, it records a `conflict` and does
|
|
22
|
-
* NOT overwrite (the caller decides what to do).
|
|
23
|
-
* - With `dryRun`, nothing is written; entries are reported as `would-rename`.
|
|
24
|
-
*
|
|
25
|
-
* Pure-ish: only filesystem renames, no schema sentinel change (the layout
|
|
26
|
-
* version stays "1"; this is a within-version cleanup, not a schema bump).
|
|
27
|
-
*/
|
|
28
|
-
export declare function sanitizeStorePaths(root: string, options?: {
|
|
29
|
-
dryRun?: boolean;
|
|
30
|
-
}): SanitizePathsResult;
|
|
31
|
-
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../../src/runtime/local-files/migrate.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,cAAc,GAAG,UAAU,GAAG,SAAS,CAAC;CACtE;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,QAAQ,CAAC,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAC;CACpD;AA4BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GACjC,mBAAmB,CAyDrB"}
|