velocious 1.0.709 → 1.0.710

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.
Files changed (32) hide show
  1. package/README.md +1 -1
  2. package/build/configuration-types.js +17 -1
  3. package/build/configuration.js +74 -2
  4. package/build/database/advisory-lock-errors.js +59 -0
  5. package/build/database/advisory-lock-lock-server-backend.js +557 -0
  6. package/build/database/advisory-lock-runner.js +175 -2
  7. package/build/database/record/index.js +16 -2
  8. package/build/src/configuration-types.d.ts +73 -2
  9. package/build/src/configuration-types.d.ts.map +1 -1
  10. package/build/src/configuration-types.js +17 -2
  11. package/build/src/configuration.d.ts +32 -2
  12. package/build/src/configuration.d.ts.map +1 -1
  13. package/build/src/configuration.js +72 -3
  14. package/build/src/database/advisory-lock-errors.d.ts +54 -0
  15. package/build/src/database/advisory-lock-errors.d.ts.map +1 -0
  16. package/build/src/database/advisory-lock-errors.js +52 -0
  17. package/build/src/database/advisory-lock-lock-server-backend.d.ts +279 -0
  18. package/build/src/database/advisory-lock-lock-server-backend.d.ts.map +1 -0
  19. package/build/src/database/advisory-lock-lock-server-backend.js +474 -0
  20. package/build/src/database/advisory-lock-runner.d.ts +69 -1
  21. package/build/src/database/advisory-lock-runner.d.ts.map +1 -1
  22. package/build/src/database/advisory-lock-runner.js +150 -3
  23. package/build/src/database/record/index.d.ts +2 -2
  24. package/build/src/database/record/index.d.ts.map +1 -1
  25. package/build/src/database/record/index.js +3 -3
  26. package/package.json +1 -1
  27. package/src/configuration-types.js +17 -1
  28. package/src/configuration.js +74 -2
  29. package/src/database/advisory-lock-errors.js +59 -0
  30. package/src/database/advisory-lock-lock-server-backend.js +557 -0
  31. package/src/database/advisory-lock-runner.js +175 -2
  32. package/src/database/record/index.js +16 -2
@@ -0,0 +1,54 @@
1
+ import { AdvisoryLockBackendUnavailableError } from "./advisory-lock-backend-policy.js";
2
+ /**
3
+ * Thrown when a lock-server acquisition could not be attempted because the
4
+ * lock server is unreachable. Distinct from `AdvisoryLockTimeoutError` ("the
5
+ * server was reachable, the holder never released") so a caller can react to
6
+ * an infrastructure outage without guessing.
7
+ */
8
+ export declare class AdvisoryLockServiceUnavailableError extends Error {
9
+ lockName: string;
10
+ reason: string;
11
+ /**
12
+ * Runs constructor.
13
+ * @param {string} message - Error message.
14
+ * @param {{lockName: string, reason: string}} args - Lock name and failure reason.
15
+ */
16
+ constructor(message: string, { lockName, reason }: {
17
+ lockName: string;
18
+ reason: string;
19
+ });
20
+ }
21
+ /**
22
+ * Thrown after a critical section ran on the lock-server tier while its lease
23
+ * was fenced or lost (design §7/§8): the section may have overlapped another
24
+ * holder, so its result must not be trusted as exclusive.
25
+ */
26
+ export declare class AdvisoryLockLostError extends Error {
27
+ lockName: string;
28
+ epoch: number | null;
29
+ currentEpoch: number | null;
30
+ cause: Error | undefined;
31
+ /**
32
+ * Runs constructor.
33
+ * @param {string} message - Error message.
34
+ * @param {{cause?: Error, currentEpoch: number | null, epoch: number | null, lockName: string}} args - Fencing details.
35
+ */
36
+ constructor(message: string, { cause, currentEpoch, epoch, lockName }: {
37
+ cause?: Error;
38
+ currentEpoch: number | null;
39
+ epoch: number | null;
40
+ lockName: string;
41
+ });
42
+ }
43
+ /**
44
+ * Builds the error thrown when a lock name's minimum tier cannot be served and
45
+ * no eligible tier is available (design §9, fail-closed).
46
+ * @param {{lockName: string, minTier: import("./advisory-lock-backend-policy.js").AdvisoryLockTier, reasons: string[]}} args - Unavailability details.
47
+ * @returns {AdvisoryLockBackendUnavailableError} - Error to throw.
48
+ */
49
+ export declare function advisoryLockBackendUnavailable(args: {
50
+ lockName: string;
51
+ minTier: import("./advisory-lock-backend-policy.js").AdvisoryLockTier;
52
+ reasons: string[];
53
+ }): AdvisoryLockBackendUnavailableError;
54
+ //# sourceMappingURL=advisory-lock-errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advisory-lock-errors.d.ts","sourceRoot":"","sources":["../../../src/database/advisory-lock-errors.js"],"names":[],"mappings":"AAEA,OAAO,EAAC,mCAAmC,EAAC,MAAM,mCAAmC,CAAA;AAErF;;;;;GAKG;AACH,qBAAa,mCAAoC,SAAQ,KAAK;IASrD,QAAQ;IACR,MAAM;IATb;;;;OAIG;IACH,YAAY,OAAO,EAHR,MAGQ,EAAE,EAAC,QAAQ,EAAE,MAAM,EAAC,EAF5B;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAEL,EAKtC;CACF;AAED;;;;GAIG;AACH,qBAAa,qBAAsB,SAAQ,KAAK;IASvC,QAAQ;IACR,KAAK;IACL,YAAY;IACZ,KAAK;IAXZ;;;;OAIG;IACH,YAAY,OAAO,EAHR,MAGQ,EAAE,EAAC,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAC,EAFhD;QAAC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAEnC,EAO1D;CACF;AAED;;;;;GAKG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,EAHxC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,mCAAmC,EAAE,gBAAgB,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAGnE,GAFtC,mCAAmC,CAS/C"}
@@ -0,0 +1,52 @@
1
+ // @ts-check
2
+ import { AdvisoryLockBackendUnavailableError } from "./advisory-lock-backend-policy.js";
3
+ /**
4
+ * Thrown when a lock-server acquisition could not be attempted because the
5
+ * lock server is unreachable. Distinct from `AdvisoryLockTimeoutError` ("the
6
+ * server was reachable, the holder never released") so a caller can react to
7
+ * an infrastructure outage without guessing.
8
+ */
9
+ export class AdvisoryLockServiceUnavailableError extends Error {
10
+ /**
11
+ * Runs constructor.
12
+ * @param {string} message - Error message.
13
+ * @param {{lockName: string, reason: string}} args - Lock name and failure reason.
14
+ */
15
+ constructor(message, { lockName, reason }) {
16
+ super(message);
17
+ this.name = "AdvisoryLockServiceUnavailableError";
18
+ this.lockName = lockName;
19
+ this.reason = reason;
20
+ }
21
+ }
22
+ /**
23
+ * Thrown after a critical section ran on the lock-server tier while its lease
24
+ * was fenced or lost (design §7/§8): the section may have overlapped another
25
+ * holder, so its result must not be trusted as exclusive.
26
+ */
27
+ export class AdvisoryLockLostError extends Error {
28
+ /**
29
+ * Runs constructor.
30
+ * @param {string} message - Error message.
31
+ * @param {{cause?: Error, currentEpoch: number | null, epoch: number | null, lockName: string}} args - Fencing details.
32
+ */
33
+ constructor(message, { cause, currentEpoch, epoch, lockName }) {
34
+ super(message);
35
+ this.name = "AdvisoryLockLostError";
36
+ this.lockName = lockName;
37
+ this.epoch = epoch;
38
+ this.currentEpoch = currentEpoch;
39
+ this.cause = cause;
40
+ }
41
+ }
42
+ /**
43
+ * Builds the error thrown when a lock name's minimum tier cannot be served and
44
+ * no eligible tier is available (design §9, fail-closed).
45
+ * @param {{lockName: string, minTier: import("./advisory-lock-backend-policy.js").AdvisoryLockTier, reasons: string[]}} args - Unavailability details.
46
+ * @returns {AdvisoryLockBackendUnavailableError} - Error to throw.
47
+ */
48
+ export function advisoryLockBackendUnavailable(args) {
49
+ const { lockName, minTier, reasons } = args;
50
+ return new AdvisoryLockBackendUnavailableError(`No eligible advisory-lock backend is available for ${JSON.stringify(lockName)} (minimum tier ${JSON.stringify(minTier)}): ${reasons.join("; ")}`, { lockName, minTier, reasons });
51
+ }
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWR2aXNvcnktbG9jay1lcnJvcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGF0YWJhc2UvYWR2aXNvcnktbG9jay1lcnJvcnMuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sRUFBQyxtQ0FBbUMsRUFBQyxNQUFNLG1DQUFtQyxDQUFBO0FBRXJGOzs7OztHQUtHO0FBQ0gsTUFBTSxPQUFPLG1DQUFvQyxTQUFRLEtBQUs7SUFDNUQ7Ozs7T0FJRztJQUNILFlBQVksT0FBTyxFQUFFLEVBQUMsUUFBUSxFQUFFLE1BQU0sRUFBQztRQUNyQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDZCxJQUFJLENBQUMsSUFBSSxHQUFHLHFDQUFxQyxDQUFBO1FBQ2pELElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBQ3hCLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0lBQ3RCLENBQUM7Q0FDRjtBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8scUJBQXNCLFNBQVEsS0FBSztJQUM5Qzs7OztPQUlHO0lBQ0gsWUFBWSxPQUFPLEVBQUUsRUFBQyxLQUFLLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUM7UUFDekQsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ2QsSUFBSSxDQUFDLElBQUksR0FBRyx1QkFBdUIsQ0FBQTtRQUNuQyxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtRQUN4QixJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQTtRQUNsQixJQUFJLENBQUMsWUFBWSxHQUFHLFlBQVksQ0FBQTtRQUNoQyxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQTtJQUNwQixDQUFDO0NBQ0Y7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSw4QkFBOEIsQ0FBQyxJQUFJO0lBQ2pELE1BQU0sRUFBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBQyxHQUFHLElBQUksQ0FBQTtJQUV6QyxPQUFPLElBQUksbUNBQW1DLENBQzVDLHNEQUFzRCxJQUFJLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxrQkFBa0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQ2pKLEVBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUMsQ0FDN0IsQ0FBQTtBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHtBZHZpc29yeUxvY2tCYWNrZW5kVW5hdmFpbGFibGVFcnJvcn0gZnJvbSBcIi4vYWR2aXNvcnktbG9jay1iYWNrZW5kLXBvbGljeS5qc1wiXG5cbi8qKlxuICogVGhyb3duIHdoZW4gYSBsb2NrLXNlcnZlciBhY3F1aXNpdGlvbiBjb3VsZCBub3QgYmUgYXR0ZW1wdGVkIGJlY2F1c2UgdGhlXG4gKiBsb2NrIHNlcnZlciBpcyB1bnJlYWNoYWJsZS4gRGlzdGluY3QgZnJvbSBgQWR2aXNvcnlMb2NrVGltZW91dEVycm9yYCAoXCJ0aGVcbiAqIHNlcnZlciB3YXMgcmVhY2hhYmxlLCB0aGUgaG9sZGVyIG5ldmVyIHJlbGVhc2VkXCIpIHNvIGEgY2FsbGVyIGNhbiByZWFjdCB0b1xuICogYW4gaW5mcmFzdHJ1Y3R1cmUgb3V0YWdlIHdpdGhvdXQgZ3Vlc3NpbmcuXG4gKi9cbmV4cG9ydCBjbGFzcyBBZHZpc29yeUxvY2tTZXJ2aWNlVW5hdmFpbGFibGVFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRXJyb3IgbWVzc2FnZS5cbiAgICogQHBhcmFtIHt7bG9ja05hbWU6IHN0cmluZywgcmVhc29uOiBzdHJpbmd9fSBhcmdzIC0gTG9jayBuYW1lIGFuZCBmYWlsdXJlIHJlYXNvbi5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHtsb2NrTmFtZSwgcmVhc29ufSkge1xuICAgIHN1cGVyKG1lc3NhZ2UpXG4gICAgdGhpcy5uYW1lID0gXCJBZHZpc29yeUxvY2tTZXJ2aWNlVW5hdmFpbGFibGVFcnJvclwiXG4gICAgdGhpcy5sb2NrTmFtZSA9IGxvY2tOYW1lXG4gICAgdGhpcy5yZWFzb24gPSByZWFzb25cbiAgfVxufVxuXG4vKipcbiAqIFRocm93biBhZnRlciBhIGNyaXRpY2FsIHNlY3Rpb24gcmFuIG9uIHRoZSBsb2NrLXNlcnZlciB0aWVyIHdoaWxlIGl0cyBsZWFzZVxuICogd2FzIGZlbmNlZCBvciBsb3N0IChkZXNpZ24gwqc3L8KnOCk6IHRoZSBzZWN0aW9uIG1heSBoYXZlIG92ZXJsYXBwZWQgYW5vdGhlclxuICogaG9sZGVyLCBzbyBpdHMgcmVzdWx0IG11c3Qgbm90IGJlIHRydXN0ZWQgYXMgZXhjbHVzaXZlLlxuICovXG5leHBvcnQgY2xhc3MgQWR2aXNvcnlMb2NrTG9zdEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAvKipcbiAgICogUnVucyBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBFcnJvciBtZXNzYWdlLlxuICAgKiBAcGFyYW0ge3tjYXVzZT86IEVycm9yLCBjdXJyZW50RXBvY2g6IG51bWJlciB8IG51bGwsIGVwb2NoOiBudW1iZXIgfCBudWxsLCBsb2NrTmFtZTogc3RyaW5nfX0gYXJncyAtIEZlbmNpbmcgZGV0YWlscy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKG1lc3NhZ2UsIHtjYXVzZSwgY3VycmVudEVwb2NoLCBlcG9jaCwgbG9ja05hbWV9KSB7XG4gICAgc3VwZXIobWVzc2FnZSlcbiAgICB0aGlzLm5hbWUgPSBcIkFkdmlzb3J5TG9ja0xvc3RFcnJvclwiXG4gICAgdGhpcy5sb2NrTmFtZSA9IGxvY2tOYW1lXG4gICAgdGhpcy5lcG9jaCA9IGVwb2NoXG4gICAgdGhpcy5jdXJyZW50RXBvY2ggPSBjdXJyZW50RXBvY2hcbiAgICB0aGlzLmNhdXNlID0gY2F1c2VcbiAgfVxufVxuXG4vKipcbiAqIEJ1aWxkcyB0aGUgZXJyb3IgdGhyb3duIHdoZW4gYSBsb2NrIG5hbWUncyBtaW5pbXVtIHRpZXIgY2Fubm90IGJlIHNlcnZlZCBhbmRcbiAqIG5vIGVsaWdpYmxlIHRpZXIgaXMgYXZhaWxhYmxlIChkZXNpZ24gwqc5LCBmYWlsLWNsb3NlZCkuXG4gKiBAcGFyYW0ge3tsb2NrTmFtZTogc3RyaW5nLCBtaW5UaWVyOiBpbXBvcnQoXCIuL2Fkdmlzb3J5LWxvY2stYmFja2VuZC1wb2xpY3kuanNcIikuQWR2aXNvcnlMb2NrVGllciwgcmVhc29uczogc3RyaW5nW119fSBhcmdzIC0gVW5hdmFpbGFiaWxpdHkgZGV0YWlscy5cbiAqIEByZXR1cm5zIHtBZHZpc29yeUxvY2tCYWNrZW5kVW5hdmFpbGFibGVFcnJvcn0gLSBFcnJvciB0byB0aHJvdy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkdmlzb3J5TG9ja0JhY2tlbmRVbmF2YWlsYWJsZShhcmdzKSB7XG4gIGNvbnN0IHtsb2NrTmFtZSwgbWluVGllciwgcmVhc29uc30gPSBhcmdzXG5cbiAgcmV0dXJuIG5ldyBBZHZpc29yeUxvY2tCYWNrZW5kVW5hdmFpbGFibGVFcnJvcihcbiAgICBgTm8gZWxpZ2libGUgYWR2aXNvcnktbG9jayBiYWNrZW5kIGlzIGF2YWlsYWJsZSBmb3IgJHtKU09OLnN0cmluZ2lmeShsb2NrTmFtZSl9IChtaW5pbXVtIHRpZXIgJHtKU09OLnN0cmluZ2lmeShtaW5UaWVyKX0pOiAke3JlYXNvbnMuam9pbihcIjsgXCIpfWAsXG4gICAge2xvY2tOYW1lLCBtaW5UaWVyLCByZWFzb25zfVxuICApXG59XG4iXX0=
@@ -0,0 +1,279 @@
1
+ export type LockServerConnectionLike = {
2
+ /**
3
+ * - Resolves when the server accepted the 1:1 connection.
4
+ */
5
+ ready: Promise<void>;
6
+ /**
7
+ * - Sends one connection message.
8
+ */
9
+ sendMessage: (body: Record<string, unknown>) => void;
10
+ /**
11
+ * - Closes the connection.
12
+ */
13
+ close?: () => void;
14
+ };
15
+ export type LockServerClientLike = {
16
+ /**
17
+ * - Opens the transport.
18
+ */
19
+ connect: () => Promise<void>;
20
+ /**
21
+ * - Opens the 1:1 connection.
22
+ */
23
+ openConnection: (type: string, args: {
24
+ onMessage: (body: Record<string, unknown>) => void;
25
+ params: Record<string, unknown>;
26
+ timeoutMs: number;
27
+ }) => LockServerConnectionLike;
28
+ /**
29
+ * - Closes the transport.
30
+ */
31
+ close?: () => Promise<void> | void;
32
+ };
33
+ export type LockServerHold = {
34
+ epoch: number;
35
+ name: string;
36
+ timer: ReturnType<typeof setInterval>;
37
+ leaseExpiresAt: number;
38
+ };
39
+ export type LockServerAcquireResult = {
40
+ status: "acquired";
41
+ epoch: number;
42
+ leaseExpiresAt: number;
43
+ } | {
44
+ status: "busy";
45
+ } | {
46
+ status: "timeout";
47
+ };
48
+ /**
49
+ * @typedef {object} LockServerConnectionLike
50
+ * @property {Promise<void>} ready - Resolves when the server accepted the 1:1 connection.
51
+ * @property {(body: Record<string, unknown>) => void} sendMessage - Sends one connection message.
52
+ * @property {() => void} [close] - Closes the connection.
53
+ * @typedef {object} LockServerClientLike
54
+ * @property {() => Promise<void>} connect - Opens the transport.
55
+ * @property {(type: string, args: {onMessage: (body: Record<string, unknown>) => void, params: Record<string, unknown>, timeoutMs: number}) => LockServerConnectionLike} openConnection - Opens the 1:1 connection.
56
+ * @property {() => Promise<void> | void} [close] - Closes the transport.
57
+ * @typedef {{epoch: number, name: string, timer: ReturnType<typeof setInterval>, leaseExpiresAt: number}} LockServerHold
58
+ * @typedef {{status: "acquired", epoch: number, leaseExpiresAt: number} | {status: "busy"} | {status: "timeout"}} LockServerAcquireResult
59
+ */
60
+ /** Protocol version spoken by the centralized lock server (consens-lock v2). */
61
+ export declare const LOCK_SERVER_PROTOCOL_VERSION = 2;
62
+ /**
63
+ * Tier (b) backend: the centralized lock server (`consens-lock`, protocol v2).
64
+ *
65
+ * The server holds every lock in its own process memory, so a held lock never
66
+ * pins a database connection — that is the whole point of this tier. Ownership
67
+ * is bound to this process's connection: the server mints the `holderId`, so a
68
+ * client can only renew or release its own leases, and a dropped connection
69
+ * releases all of them immediately.
70
+ *
71
+ * Holds are leases renewed every third of the lease window. A fenced lease
72
+ * (the server granted the name to another holder after an expiry or partition)
73
+ * is recorded per lock name and surfaced by the runner as
74
+ * `AdvisoryLockLostError` after the critical section settles.
75
+ *
76
+ * Unavailability is cached for `reprobeCooldownMs` so a flapping server cannot
77
+ * turn every waiting caller into a connection attempt (design §2).
78
+ */
79
+ export default class AdvisoryLockLockServerBackend {
80
+ url: string;
81
+ authToken: string;
82
+ clientFactory: (args: {
83
+ authToken: string;
84
+ url: string;
85
+ }) => LockServerClientLike;
86
+ connectTimeoutMs: number;
87
+ leaseMs: number;
88
+ onError: ((error: Error) => void) | undefined;
89
+ reprobeCooldownMs: number;
90
+ /** @type {LockServerClientLike | null} */
91
+ client: LockServerClientLike | null;
92
+ /** @type {LockServerConnectionLike | null} */
93
+ connection: LockServerConnectionLike | null;
94
+ /** @type {Promise<void> | null} */
95
+ connectPromise: Promise<void> | null;
96
+ /** @type {{reject: (error: Error) => void, resolve: () => void, timer: ReturnType<typeof setTimeout> | null} | null} */
97
+ helloWaiter: {
98
+ reject: (error: Error) => void;
99
+ resolve: () => void;
100
+ timer: ReturnType<typeof setTimeout> | null;
101
+ } | null;
102
+ /** @type {Map<string, {epoch: number, name: string, timer: ReturnType<typeof setInterval>, leaseExpiresAt: number}>} */
103
+ holds: Map<string, {
104
+ epoch: number;
105
+ name: string;
106
+ timer: ReturnType<typeof setInterval>;
107
+ leaseExpiresAt: number;
108
+ }>;
109
+ /** @type {Map<string, {currentEpoch: number | null, epoch: number | null}>} */
110
+ fencedHolds: Map<string, {
111
+ currentEpoch: number | null;
112
+ epoch: number | null;
113
+ }>;
114
+ /** @type {Map<string, {reject: (error: Error) => void, resolve: (message: Record<string, unknown>) => void, timer: ReturnType<typeof setTimeout> | null}>} */
115
+ pending: Map<string, {
116
+ reject: (error: Error) => void;
117
+ resolve: (message: Record<string, unknown>) => void;
118
+ timer: ReturnType<typeof setTimeout> | null;
119
+ }>;
120
+ /** @type {{lastError: string | null, lastProbeAt: string | null, unavailableUntil: number}} */
121
+ status: {
122
+ lastError: string | null;
123
+ lastProbeAt: string | null;
124
+ unavailableUntil: number;
125
+ };
126
+ requestCounter: number;
127
+ closed: boolean;
128
+ /**
129
+ * Creates the lock-server backend. The transport is created on first use, so
130
+ * constructing this object never performs I/O.
131
+ * @param {object} args - Backend options.
132
+ * @param {string} [args.authToken] - Shared secret; the server fails closed without a matching token.
133
+ * @param {(args: {authToken: string, url: string}) => LockServerClientLike} [args.clientFactory] - Transport factory (tests inject a fake).
134
+ * @param {number} [args.connectTimeoutMs] - Handshake timeout.
135
+ * @param {number} [args.leaseMs] - Lease duration used until the server advertises its own.
136
+ * @param {(error: Error) => void} [args.onError] - Async error reporter.
137
+ * @param {number} [args.reprobeCooldownMs] - How long an unavailable server is not re-probed.
138
+ * @param {string} args.url - Lock-server websocket URL.
139
+ */
140
+ constructor({ authToken, clientFactory, connectTimeoutMs, leaseMs, onError, reprobeCooldownMs, url }: {
141
+ authToken?: string;
142
+ clientFactory?: (args: {
143
+ authToken: string;
144
+ url: string;
145
+ }) => LockServerClientLike;
146
+ connectTimeoutMs?: number;
147
+ leaseMs?: number;
148
+ onError?: (error: Error) => void;
149
+ reprobeCooldownMs?: number;
150
+ url: string;
151
+ });
152
+ /**
153
+ * Opens the connection if needed, honoring the re-probe cooldown.
154
+ * @param {string} lockName - Lock name, for error messages.
155
+ * @returns {Promise<void>} - Resolves when connected.
156
+ */
157
+ ensureConnected(lockName: string): Promise<void>;
158
+ /**
159
+ * Opens the transport and completes the hello handshake.
160
+ * @param {string} lockName - Lock name, for error messages.
161
+ * @returns {Promise<void>} - Resolves when the handshake completed.
162
+ */
163
+ openConnection(lockName: string): Promise<void>;
164
+ /**
165
+ * Waits for a lock through the server's FIFO queue.
166
+ * @param {string} name - Lock name.
167
+ * @param {{timeoutMs?: number | null}} [args] - Bounded wait; the server defaults to 30s.
168
+ * @returns {Promise<boolean>} - True when the lease was granted, false on timeout.
169
+ */
170
+ acquire(name: string, { timeoutMs }?: {
171
+ timeoutMs?: number | null;
172
+ }): Promise<boolean>;
173
+ /**
174
+ * Takes a lock only if the server grants it immediately.
175
+ * @param {string} name - Lock name.
176
+ * @returns {Promise<boolean>} - True when granted.
177
+ */
178
+ tryAcquire(name: string): Promise<boolean>;
179
+ /**
180
+ * Releases a held lease and stops its renewal.
181
+ * @param {string} name - Lock name.
182
+ * @returns {Promise<void>} - Resolves when released (or when the transport is gone).
183
+ */
184
+ release(name: string): Promise<void>;
185
+ /**
186
+ * Releases every lease this process holds (shutdown path).
187
+ * @returns {Promise<void>} - Resolves when every lease was released.
188
+ */
189
+ releaseAllHeld(): Promise<void>;
190
+ /**
191
+ * Runs the server's live holder list (diagnostics).
192
+ * @returns {Promise<Record<string, unknown>[]>} - Live holders.
193
+ */
194
+ list(): Promise<Record<string, unknown>[]>;
195
+ /**
196
+ * Runs who-holds for one name (diagnostics).
197
+ * @param {string} name - Lock name.
198
+ * @returns {Promise<Record<string, unknown> | null>} - Holder, or null.
199
+ */
200
+ whoHolds(name: string): Promise<Record<string, unknown> | null>;
201
+ /**
202
+ * Runs the fencing epoch granted for one held lease.
203
+ * @param {string} name - Lock name.
204
+ * @returns {number | null} - Granted epoch, or null when the lease is not (or no longer) held.
205
+ */
206
+ getHoldEpoch(name: string): number | null;
207
+ /**
208
+ * Whether this hold was fenced or lost during its critical section.
209
+ * @param {string} name - Lock name.
210
+ * @param {number | null} epoch - Epoch the hold was granted.
211
+ * @returns {{currentEpoch: number | null, epoch: number | null} | null} - Fencing details when lost.
212
+ */
213
+ takeLoss(name: string, epoch: number | null): {
214
+ currentEpoch: number | null;
215
+ epoch: number | null;
216
+ } | null;
217
+ /**
218
+ * Reports connection state and the names currently leased through this
219
+ * process, for `getAdvisoryLockBackendStatus()`.
220
+ * @returns {{connected: boolean, lastError: string | null, lastProbeAt: string | null, leasedNames: string[]}} - Backend status for diagnostics.
221
+ */
222
+ getStatus(): {
223
+ connected: boolean;
224
+ lastError: string | null;
225
+ lastProbeAt: string | null;
226
+ leasedNames: string[];
227
+ };
228
+ /**
229
+ * Closes the backend: explicit release first, then the transport.
230
+ * @returns {Promise<void>} - Resolves when closed.
231
+ */
232
+ close(): Promise<void>;
233
+ /**
234
+ * Dispatches one server message.
235
+ * @param {Record<string, unknown>} body - Server message.
236
+ * @returns {void}
237
+ */
238
+ handleMessage(body: Record<string, unknown>): void;
239
+ /**
240
+ * Sends one request and awaits its correlated response.
241
+ * @param {string} type - Request type.
242
+ * @param {Record<string, unknown>} payload - Request fields.
243
+ * @param {number | null} [timeoutMs] - Response timeout; null waits for the server.
244
+ * @returns {Promise<Record<string, unknown>>} - Response body.
245
+ */
246
+ request(type: string, payload: Record<string, unknown>, timeoutMs?: number | null): Promise<Record<string, unknown>>;
247
+ /**
248
+ * Starts lease renewal for a granted lock.
249
+ * @param {string} name - Lock name.
250
+ * @param {number} epoch - Granted epoch.
251
+ * @returns {void}
252
+ */
253
+ startRenewal(name: string, epoch: number): void;
254
+ /**
255
+ * Renews one lease; a fenced lease is recorded for the runner to surface.
256
+ * @param {string} name - Lock name.
257
+ * @param {number} epoch - Epoch the hold believes it owns.
258
+ * @returns {Promise<void>} - Resolves after the renewal round-trip.
259
+ */
260
+ renew(name: string, epoch: number): Promise<void>;
261
+ /**
262
+ * Records that the lock server is unreachable and starts the re-probe cooldown.
263
+ * @param {Error} error - Failure.
264
+ * @returns {void}
265
+ */
266
+ markUnavailable(error: Error): void;
267
+ /**
268
+ * Drops transport state and marks every outstanding hold lost.
269
+ * @returns {void}
270
+ */
271
+ teardown(): void;
272
+ /**
273
+ * Reports a transport-side failure without breaking lock handling.
274
+ * @param {unknown} error - Failure to report.
275
+ * @returns {void}
276
+ */
277
+ reportError(error: unknown): void;
278
+ }
279
+ //# sourceMappingURL=advisory-lock-lock-server-backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advisory-lock-lock-server-backend.d.ts","sourceRoot":"","sources":["../../../src/database/advisory-lock-lock-server-backend.js"],"names":[],"mappings":"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"}