velocious 1.0.698 → 1.0.700
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/README.md +2 -2
- package/build/configuration-types.js +23 -0
- package/build/configuration.js +136 -1
- package/build/database/advisory-lock-backend-policy.js +204 -0
- package/build/database/advisory-lock-file-backend.js +348 -0
- package/build/database/advisory-lock-runner.js +239 -16
- package/build/database/drivers/base.js +318 -15
- package/build/database/drivers/mssql/index.js +1 -1
- package/build/database/drivers/mysql/index.js +4 -2
- package/build/database/drivers/pgsql/index.js +4 -2
- package/build/database/drivers/sqlite/base.js +13 -129
- package/build/database/drivers/sqlite/index.js +41 -62
- package/build/database/migrator.js +120 -50
- package/build/database/record/attachments/store.js +84 -1
- package/build/environment-handlers/base.js +13 -0
- package/build/environment-handlers/node.js +11 -0
- package/build/http-server/server-lock.js +21 -115
- package/build/src/configuration-types.d.ts +68 -0
- package/build/src/configuration-types.d.ts.map +1 -1
- package/build/src/configuration-types.js +21 -1
- package/build/src/configuration.d.ts +100 -1
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +124 -2
- package/build/src/database/advisory-lock-backend-policy.d.ts +145 -0
- package/build/src/database/advisory-lock-backend-policy.d.ts.map +1 -0
- package/build/src/database/advisory-lock-backend-policy.js +184 -0
- package/build/src/database/advisory-lock-file-backend.d.ts +194 -0
- package/build/src/database/advisory-lock-file-backend.d.ts.map +1 -0
- package/build/src/database/advisory-lock-file-backend.js +313 -0
- package/build/src/database/advisory-lock-runner.d.ts +116 -15
- package/build/src/database/advisory-lock-runner.d.ts.map +1 -1
- package/build/src/database/advisory-lock-runner.js +190 -17
- package/build/src/database/drivers/base.d.ts +125 -4
- package/build/src/database/drivers/base.d.ts.map +1 -1
- package/build/src/database/drivers/base.js +282 -17
- package/build/src/database/drivers/mssql/index.d.ts +1 -1
- package/build/src/database/drivers/mssql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mssql/index.js +2 -2
- package/build/src/database/drivers/mysql/index.d.ts +4 -2
- package/build/src/database/drivers/mysql/index.d.ts.map +1 -1
- package/build/src/database/drivers/mysql/index.js +5 -3
- package/build/src/database/drivers/pgsql/index.d.ts +4 -2
- package/build/src/database/drivers/pgsql/index.d.ts.map +1 -1
- package/build/src/database/drivers/pgsql/index.js +5 -3
- package/build/src/database/drivers/sqlite/base.d.ts +11 -49
- package/build/src/database/drivers/sqlite/base.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/base.js +14 -114
- package/build/src/database/drivers/sqlite/index.d.ts +28 -19
- package/build/src/database/drivers/sqlite/index.d.ts.map +1 -1
- package/build/src/database/drivers/sqlite/index.js +41 -59
- package/build/src/database/migrator.d.ts.map +1 -1
- package/build/src/database/migrator.js +110 -56
- package/build/src/database/record/attachments/store.d.ts +0 -3
- package/build/src/database/record/attachments/store.d.ts.map +1 -1
- package/build/src/database/record/attachments/store.js +71 -2
- package/build/src/environment-handlers/base.d.ts +14 -0
- package/build/src/environment-handlers/base.d.ts.map +1 -1
- package/build/src/environment-handlers/base.js +13 -1
- package/build/src/environment-handlers/node.d.ts +11 -0
- package/build/src/environment-handlers/node.d.ts.map +1 -1
- package/build/src/environment-handlers/node.js +11 -1
- package/build/src/http-server/server-lock.d.ts +13 -37
- package/build/src/http-server/server-lock.d.ts.map +1 -1
- package/build/src/http-server/server-lock.js +22 -109
- package/build/src/testing/test-runner.d.ts +74 -0
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +140 -1
- package/build/src/testing/test-tenant-database-pool.d.ts +183 -0
- package/build/src/testing/test-tenant-database-pool.d.ts.map +1 -0
- package/build/src/testing/test-tenant-database-pool.js +388 -0
- package/build/src/testing/velocious-attempt-executor.d.ts.map +1 -1
- package/build/src/testing/velocious-attempt-executor.js +43 -1
- package/build/testing/test-runner.js +152 -0
- package/build/testing/test-tenant-database-pool.js +438 -0
- package/build/testing/velocious-attempt-executor.js +44 -0
- package/package.json +1 -1
- package/src/configuration-types.js +23 -0
- package/src/configuration.js +136 -1
- package/src/database/advisory-lock-backend-policy.js +204 -0
- package/src/database/advisory-lock-file-backend.js +348 -0
- package/src/database/advisory-lock-runner.js +239 -16
- package/src/database/drivers/base.js +318 -15
- package/src/database/drivers/mssql/index.js +1 -1
- package/src/database/drivers/mysql/index.js +4 -2
- package/src/database/drivers/pgsql/index.js +4 -2
- package/src/database/drivers/sqlite/base.js +13 -129
- package/src/database/drivers/sqlite/index.js +41 -62
- package/src/database/migrator.js +120 -50
- package/src/database/record/attachments/store.js +84 -1
- package/src/environment-handlers/base.js +13 -0
- package/src/environment-handlers/node.js +11 -0
- package/src/http-server/server-lock.js +21 -115
- package/src/testing/test-runner.js +152 -0
- package/src/testing/test-tenant-database-pool.js +438 -0
- package/src/testing/velocious-attempt-executor.js +44 -0
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
import timeout, { TimeoutError } from "awaitery/build/timeout.js";
|
|
3
|
+
import { DEFAULT_ADVISORY_LOCK_ACQUIRE_TIMEOUT_MS } from "./advisory-lock-bound.js";
|
|
4
|
+
import { AdvisoryLockBackendUnavailableError, resolveAdvisoryLockBackendPolicy, refuseAdvisoryLockTierBelowMinimum } from "./advisory-lock-backend-policy.js";
|
|
5
|
+
/**
|
|
6
|
+
* Provenance of one advisory-lock acquisition (STC-210 design §3): every
|
|
7
|
+
* held lock reports the tier that actually served it, so a fallback is
|
|
8
|
+
* visible to the callback, in logs, and in `getAdvisoryLockBackendStatus()`.
|
|
9
|
+
* @typedef {object} AdvisoryLockBackendProvenance
|
|
10
|
+
* @property {import("./advisory-lock-backend-policy.js").AdvisoryLockTier} backend - Tier that served the acquisition.
|
|
11
|
+
* @property {string} [driverType] - Database driver type when the driver tier served it.
|
|
12
|
+
* @property {boolean} fencingSupported - Whether this tier carries fencing tokens (design §8); the file tier reports false rather than pretending.
|
|
13
|
+
* @property {string} [holderId] - Backend holder id for the file tier.
|
|
14
|
+
* @property {string} [lockName] - Lock name this provenance belongs to.
|
|
15
|
+
*/
|
|
3
16
|
/**
|
|
4
17
|
* Thrown when an advisory lock could not be acquired before `timeoutMs` elapsed.
|
|
5
18
|
*/
|
|
@@ -71,17 +84,30 @@ export default class AdvisoryLockRunner {
|
|
|
71
84
|
* cleanup can release the lock even if callback database work is stuck.
|
|
72
85
|
* @template T
|
|
73
86
|
* @param {string} name - Lock name.
|
|
74
|
-
* @param {(args?: {control
|
|
87
|
+
* @param {(args?: {control?: import("awaitery/build/timeout.js").TimeoutControl, lockBackend: AdvisoryLockBackendProvenance}) => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
75
88
|
* @param {{timeoutMs?: number | null, holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - Lock and hold timeout options.
|
|
76
89
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
77
90
|
*/
|
|
78
91
|
async withAdvisoryLock(name, callback, args = {}) {
|
|
92
|
+
const fileBackend = await this.fileBackendForName(name);
|
|
93
|
+
if (fileBackend) {
|
|
94
|
+
const acquired = await fileBackend.acquire(name, { timeoutMs: this.fileAcquireTimeoutMs(args) });
|
|
95
|
+
if (!acquired) {
|
|
96
|
+
throw new AdvisoryLockTimeoutError(`Timed out waiting for advisory lock ${JSON.stringify(name)} on the file tier`, { name });
|
|
97
|
+
}
|
|
98
|
+
const lockBackend = this.fileProvenance(fileBackend, name);
|
|
99
|
+
this.configuration.recordAdvisoryLockAcquisition({ backend: lockBackend.backend, fencingSupported: lockBackend.fencingSupported, lockName: name });
|
|
100
|
+
return await this.runLockedCallback({ callback, holdTimeoutMs: args.holdTimeoutMs, lockBackend, name, release: async () => await fileBackend.release(name) });
|
|
101
|
+
}
|
|
79
102
|
return await this.withLockConnection(args, async (connection) => {
|
|
103
|
+
const lockBackend = this.driverProvenance(connection);
|
|
104
|
+
this.assertDriverTierEligible(name, lockBackend);
|
|
80
105
|
const acquired = await connection.acquireAdvisoryLock(name, args);
|
|
81
106
|
if (!acquired) {
|
|
82
107
|
throw new AdvisoryLockTimeoutError(`Timed out waiting for advisory lock ${JSON.stringify(name)}`, { name });
|
|
83
108
|
}
|
|
84
|
-
|
|
109
|
+
this.configuration.recordAdvisoryLockAcquisition({ backend: lockBackend.backend, fencingSupported: lockBackend.fencingSupported, lockName: name });
|
|
110
|
+
return await this.runLockedCallback({ callback, holdTimeoutMs: args.holdTimeoutMs, lockBackend, name, release: async () => await connection.releaseAdvisoryLock(name) });
|
|
85
111
|
});
|
|
86
112
|
}
|
|
87
113
|
/**
|
|
@@ -93,19 +119,33 @@ export default class AdvisoryLockRunner {
|
|
|
93
119
|
* cancellation.
|
|
94
120
|
* @template T
|
|
95
121
|
* @param {string} name - Lock name.
|
|
96
|
-
* @param {(args?: {control
|
|
122
|
+
* @param {(args?: {control?: import("awaitery/build/timeout.js").TimeoutControl, lockBackend: AdvisoryLockBackendProvenance}) => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
97
123
|
* @param {{holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - Hold timeout options.
|
|
98
124
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
99
125
|
*/
|
|
100
126
|
async withAdvisoryLockOrFail(name, callback, args = {}) {
|
|
127
|
+
const fileBackend = await this.fileBackendForName(name);
|
|
128
|
+
if (fileBackend) {
|
|
129
|
+
const acquired = await fileBackend.tryAcquire(name);
|
|
130
|
+
if (!acquired) {
|
|
131
|
+
throw new AdvisoryLockBusyError(`Advisory lock ${JSON.stringify(name)} is already held on the file tier`, { name });
|
|
132
|
+
}
|
|
133
|
+
const lockBackend = this.fileProvenance(fileBackend, name);
|
|
134
|
+
this.configuration.recordAdvisoryLockAcquisition({ backend: lockBackend.backend, fencingSupported: lockBackend.fencingSupported, lockName: name });
|
|
135
|
+
return await this.runLockedCallback({ callback, holdTimeoutMs: args.holdTimeoutMs, lockBackend, name, release: async () => await fileBackend.release(name) });
|
|
136
|
+
}
|
|
101
137
|
return await this.withLockConnection(args, async (connection) => {
|
|
138
|
+
const lockBackend = this.driverProvenance(connection);
|
|
139
|
+
this.assertDriverTierEligible(name, lockBackend);
|
|
102
140
|
const acquired = await connection.tryAcquireAdvisoryLock(name);
|
|
103
141
|
if (!acquired) {
|
|
104
142
|
throw new AdvisoryLockBusyError(`Advisory lock ${JSON.stringify(name)} is already held`, { name });
|
|
105
143
|
}
|
|
106
|
-
|
|
144
|
+
this.configuration.recordAdvisoryLockAcquisition({ backend: lockBackend.backend, fencingSupported: lockBackend.fencingSupported, lockName: name });
|
|
145
|
+
return await this.runLockedCallback({ callback, holdTimeoutMs: args.holdTimeoutMs, lockBackend, name, release: async () => await connection.releaseAdvisoryLock(name) });
|
|
107
146
|
});
|
|
108
147
|
}
|
|
148
|
+
/**
|
|
109
149
|
/**
|
|
110
150
|
* Runs a callback if the advisory lock can be acquired without waiting;
|
|
111
151
|
* otherwise returns a `{acquired: false}` defer result instead of throwing.
|
|
@@ -121,32 +161,146 @@ export default class AdvisoryLockRunner {
|
|
|
121
161
|
* file lock), so a caller never branches on the backend.
|
|
122
162
|
* @template T
|
|
123
163
|
* @param {string} name - Lock name.
|
|
124
|
-
* @param {(args?: {control
|
|
164
|
+
* @param {(args?: {control?: import("awaitery/build/timeout.js").TimeoutControl, lockBackend: AdvisoryLockBackendProvenance}) => Promise<T>} callback - Callback to invoke while the lock is held.
|
|
125
165
|
* @param {{holdTimeoutMs?: number | null, dedicatedConnection?: boolean}} [args] - Hold timeout options.
|
|
126
166
|
* @returns {Promise<{acquired: true, result: T} | {acquired: false, reason: "contended", lockName: string}>} - Either the held-callback result or the defer outcome.
|
|
127
167
|
*/
|
|
128
168
|
async withAdvisoryLockOrDefer(name, callback, args = {}) {
|
|
169
|
+
const fileBackend = await this.fileBackendForName(name);
|
|
170
|
+
if (fileBackend) {
|
|
171
|
+
const acquired = await fileBackend.acquire(name, { timeoutMs: 0 });
|
|
172
|
+
if (!acquired)
|
|
173
|
+
return { acquired: false, reason: "contended", lockName: name };
|
|
174
|
+
const lockBackend = this.fileProvenance(fileBackend, name);
|
|
175
|
+
this.configuration.recordAdvisoryLockAcquisition({ backend: lockBackend.backend, fencingSupported: lockBackend.fencingSupported, lockName: name });
|
|
176
|
+
const result = await this.runLockedCallback({ callback, holdTimeoutMs: args.holdTimeoutMs, lockBackend, name, release: async () => await fileBackend.release(name) });
|
|
177
|
+
return { acquired: true, result };
|
|
178
|
+
}
|
|
129
179
|
return await this.withLockConnection(args, async (connection) => {
|
|
130
180
|
const acquired = await connection.tryAcquireAdvisoryLock(name);
|
|
131
181
|
if (!acquired)
|
|
132
182
|
return { acquired: false, reason: "contended", lockName: name };
|
|
133
|
-
const
|
|
183
|
+
const lockBackend = this.driverProvenance(connection);
|
|
184
|
+
this.assertDriverTierEligible(name, lockBackend);
|
|
185
|
+
this.configuration.recordAdvisoryLockAcquisition({ backend: lockBackend.backend, fencingSupported: lockBackend.fencingSupported, lockName: name });
|
|
186
|
+
const result = await this.runLockedCallback({ callback, holdTimeoutMs: args.holdTimeoutMs, lockBackend, name, release: async () => await connection.releaseAdvisoryLock(name) });
|
|
134
187
|
return { acquired: true, result };
|
|
135
188
|
});
|
|
136
189
|
}
|
|
137
190
|
/**
|
|
138
|
-
* Runs the lock holder callback and releases the lock from its owning
|
|
191
|
+
* Runs the lock holder callback and releases the lock from its owning backend.
|
|
139
192
|
* @template T
|
|
140
|
-
* @param {{callback: (args?: {control
|
|
193
|
+
* @param {{callback: (args?: {control?: import("awaitery/build/timeout.js").TimeoutControl, lockBackend: AdvisoryLockBackendProvenance}) => Promise<T>, holdTimeoutMs?: number | null, lockBackend: AdvisoryLockBackendProvenance, name: string, release: () => Promise<unknown>}} args - Locked callback args.
|
|
141
194
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
142
195
|
*/
|
|
143
|
-
async runLockedCallback({ callback,
|
|
196
|
+
async runLockedCallback({ callback, holdTimeoutMs, lockBackend, name, release }) {
|
|
144
197
|
try {
|
|
145
|
-
return await AdvisoryLockRunner.runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs);
|
|
198
|
+
return await AdvisoryLockRunner.runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs, lockBackend);
|
|
146
199
|
}
|
|
147
200
|
finally {
|
|
148
|
-
await
|
|
201
|
+
await release();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Resolves the backend policy for one lock name and returns the file
|
|
206
|
+
* backend when the name explicitly opts into the file tier
|
|
207
|
+
* (`preferredTier: "file"` plus `advisoryLocks.backends.file.enabled: true`).
|
|
208
|
+
* A name whose declared minimum tier is cross-host is refused loudly
|
|
209
|
+
* (`AdvisoryLockMinTierRefusedError`) before any contact with the file
|
|
210
|
+
* tier. A name that prefers the file tier while the backend is disabled
|
|
211
|
+
* moves to the driver path (a stronger-or-equal tier), never the other way
|
|
212
|
+
* around. Nothing here ever auto-enables the file tier.
|
|
213
|
+
* @param {string} name - Lock name.
|
|
214
|
+
* @returns {Promise<import("./advisory-lock-file-backend.js").default | null>} - Resolves with the file backend serving this name, or null for the driver path.
|
|
215
|
+
*/
|
|
216
|
+
async fileBackendForName(name) {
|
|
217
|
+
const policy = resolveAdvisoryLockBackendPolicy(name, this.configuration.getAdvisoryLockPolicy());
|
|
218
|
+
if (policy.preferredTier !== "file")
|
|
219
|
+
return null;
|
|
220
|
+
if (!advisoryLockPolicyAllowsFileTier(policy)) {
|
|
221
|
+
refuseAdvisoryLockTierBelowMinimum({
|
|
222
|
+
configuration: this.configuration,
|
|
223
|
+
lockName: name,
|
|
224
|
+
minTier: policy.minTier,
|
|
225
|
+
requestedBackend: "file"
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
const backend = await this.configuration.getAdvisoryLockFileBackend();
|
|
229
|
+
if (!backend) {
|
|
230
|
+
// Preferred tier unavailable: fail *upward* to the driver path (a
|
|
231
|
+
// stronger-or-equal tier), never downward. If the driver cannot satisfy
|
|
232
|
+
// the minimum either, `assertDriverTierEligible` throws
|
|
233
|
+
// `AdvisoryLockBackendUnavailableError` on the driver path.
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
return backend;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Fail-closed check on the driver path (design §9): an undeclared lock name
|
|
240
|
+
* keeps today's behavior (any driver serves it — full backward
|
|
241
|
+
* compatibility), but a name with an explicit policy entry is refused with
|
|
242
|
+
* `AdvisoryLockBackendUnavailableError` when the configured driver cannot
|
|
243
|
+
* satisfy its minimum tier (e.g. `minTier: "driver-native"` on a SQLite
|
|
244
|
+
* driver, which has no native advisory-lock primitive).
|
|
245
|
+
* @param {string} name - Lock name.
|
|
246
|
+
* @param {AdvisoryLockBackendProvenance} lockBackend - Tier the driver path would serve with.
|
|
247
|
+
* @returns {void}
|
|
248
|
+
*/
|
|
249
|
+
assertDriverTierEligible(name, lockBackend) {
|
|
250
|
+
const policy = resolveAdvisoryLockBackendPolicy(name, this.configuration.getAdvisoryLockPolicy());
|
|
251
|
+
if (!policy.entry)
|
|
252
|
+
return;
|
|
253
|
+
const tier = lockBackend.backend;
|
|
254
|
+
if (tier === "process-local" && !policy.allowedTiers.includes("process-local")) {
|
|
255
|
+
throw new AdvisoryLockBackendUnavailableError(`Advisory lock ${JSON.stringify(name)} requires minimum tier ${JSON.stringify(policy.minTier)} but the configured driver (${String(lockBackend.driverType)}) only offers the process-local tier`, { lockName: name, minTier: policy.minTier, reasons: [`driver tier ${tier} below minTier ${policy.minTier}`] });
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Resolves the wait bound for a file-tier acquisition: an explicit caller
|
|
260
|
+
* `timeoutMs` (including an explicit `null` opt-out) wins, otherwise the
|
|
261
|
+
* same framework default that bounds driver acquisitions applies.
|
|
262
|
+
* @param {{timeoutMs?: number | null}} args - Lock options.
|
|
263
|
+
* @returns {number | null} - Wait bound in milliseconds, or `null` for an indefinite wait.
|
|
264
|
+
*/
|
|
265
|
+
fileAcquireTimeoutMs(args) {
|
|
266
|
+
if (args.timeoutMs !== undefined)
|
|
267
|
+
return args.timeoutMs;
|
|
268
|
+
return DEFAULT_ADVISORY_LOCK_ACQUIRE_TIMEOUT_MS;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Builds the acquisition provenance for a file-tier hold. The file tier
|
|
272
|
+
* cannot carry fencing tokens, so the limitation is reported on every
|
|
273
|
+
* acquisition rather than silently pretended away (design §8).
|
|
274
|
+
* @param {import("./advisory-lock-file-backend.js").default} backend - Backend that served the acquisition.
|
|
275
|
+
* @param {string} name - Lock name.
|
|
276
|
+
* @returns {AdvisoryLockBackendProvenance} - Acquisition provenance.
|
|
277
|
+
*/
|
|
278
|
+
fileProvenance(backend, name) {
|
|
279
|
+
return { backend: "file", fencingSupported: false, holderId: backend.holderId, lockName: name };
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Builds the acquisition provenance for a driver-served hold. SQLite has no
|
|
283
|
+
* native advisory-lock primitive, so its emulation tier is reported as
|
|
284
|
+
* `process-local` rather than pretending to be database-native.
|
|
285
|
+
* @param {import("./drivers/base.js").default} connection - Connection that served the acquisition.
|
|
286
|
+
* @returns {AdvisoryLockBackendProvenance} - Acquisition provenance.
|
|
287
|
+
*/
|
|
288
|
+
driverProvenance(connection) {
|
|
289
|
+
let driverType = null;
|
|
290
|
+
try {
|
|
291
|
+
driverType = connection.getType();
|
|
292
|
+
}
|
|
293
|
+
catch {
|
|
294
|
+
// Test stub drivers may not implement getType(); the tier alone identifies the backend.
|
|
149
295
|
}
|
|
296
|
+
const tier = typeof connection.advisoryLockBackendTier === "function"
|
|
297
|
+
? connection.advisoryLockBackendTier()
|
|
298
|
+
: (driverType === "sqlite" ? "process-local" : "driver-native");
|
|
299
|
+
return {
|
|
300
|
+
backend: /** @type {import("./advisory-lock-backend-policy.js").AdvisoryLockTier} */ (tier),
|
|
301
|
+
driverType: driverType ?? undefined,
|
|
302
|
+
fencingSupported: tier === "driver-native"
|
|
303
|
+
};
|
|
150
304
|
}
|
|
151
305
|
/**
|
|
152
306
|
* Runs lock work on the caller connection unless `dedicatedConnection` is
|
|
@@ -199,22 +353,24 @@ export default class AdvisoryLockRunner {
|
|
|
199
353
|
*
|
|
200
354
|
* The callback receives a `TimeoutControl` from awaitery, enabling cooperative
|
|
201
355
|
* cancellation via `control.check()`, `control.signal`, `control.timedOut`,
|
|
202
|
-
* and `control.remaining()
|
|
356
|
+
* and `control.remaining()`, plus `lockBackend` provenance for the tier that
|
|
357
|
+
* served the acquisition.
|
|
203
358
|
* @template T
|
|
204
359
|
* @param {string} name - Lock name (for the error message).
|
|
205
|
-
* @param {(args?: {control
|
|
360
|
+
* @param {(args?: {control?: import("awaitery/build/timeout.js").TimeoutControl, lockBackend: AdvisoryLockBackendProvenance}) => Promise<T>} callback - Callback holding the lock.
|
|
206
361
|
* @param {number | null} [holdTimeoutMs] - Max hold time; falsy disables the timeout.
|
|
362
|
+
* @param {AdvisoryLockBackendProvenance} [lockBackend] - Provenance of the acquisition serving this hold.
|
|
207
363
|
* @returns {Promise<T>} - Resolves with the callback result.
|
|
208
364
|
*/
|
|
209
|
-
static async runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs) {
|
|
365
|
+
static async runWithAdvisoryLockHoldTimeout(name, callback, holdTimeoutMs, lockBackend) {
|
|
210
366
|
if (!holdTimeoutMs || holdTimeoutMs <= 0) {
|
|
211
|
-
return await callback();
|
|
367
|
+
return await callback({ lockBackend: lockBackend ?? AdvisoryLockRunner.unknownBackendProvenance() });
|
|
212
368
|
}
|
|
213
369
|
let callbackSettled = false;
|
|
214
370
|
try {
|
|
215
371
|
return await timeout({ timeout: holdTimeoutMs }, async ({ control }) => {
|
|
216
372
|
try {
|
|
217
|
-
return await callback({ control });
|
|
373
|
+
return await callback({ control, lockBackend: lockBackend ?? AdvisoryLockRunner.unknownBackendProvenance() });
|
|
218
374
|
}
|
|
219
375
|
finally {
|
|
220
376
|
callbackSettled = true;
|
|
@@ -228,6 +384,23 @@ export default class AdvisoryLockRunner {
|
|
|
228
384
|
throw error;
|
|
229
385
|
}
|
|
230
386
|
}
|
|
387
|
+
/**
|
|
388
|
+
* Neutral provenance for direct `runWithAdvisoryLockHoldTimeout` callers that
|
|
389
|
+
* hold a lock acquired outside this runner.
|
|
390
|
+
* @returns {AdvisoryLockBackendProvenance} - Provenance with an unknown tier.
|
|
391
|
+
*/
|
|
392
|
+
static unknownBackendProvenance() {
|
|
393
|
+
return { backend: "process-local", fencingSupported: false };
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Runs advisory lock policy allows file tier.
|
|
398
|
+
* @param {import("./advisory-lock-backend-policy.js").ResolvedAdvisoryLockBackendPolicy} policy - Resolved policy.
|
|
399
|
+
* @returns {boolean} - Whether the file tier may serve this name.
|
|
400
|
+
*/
|
|
401
|
+
function advisoryLockPolicyAllowsFileTier(policy) {
|
|
402
|
+
return policy.allowedTiers.includes("file");
|
|
231
403
|
}
|
|
232
404
|
export { AdvisoryLockBusyError, AdvisoryLockHoldTimeoutError, AdvisoryLockTimeoutError };
|
|
233
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWR2aXNvcnktbG9jay1ydW5uZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGF0YWJhc2UvYWR2aXNvcnktbG9jay1ydW5uZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sT0FBTyxFQUFFLEVBQUMsWUFBWSxFQUFDLE1BQU0sMkJBQTJCLENBQUE7QUFFL0Q7O0dBRUc7QUFDSCxNQUFNLHdCQUF5QixTQUFRLEtBQUs7SUFDMUM7Ozs7T0FJRztJQUNILFlBQVksT0FBTyxFQUFFLEVBQUMsSUFBSSxFQUFDO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUNkLElBQUksQ0FBQyxJQUFJLEdBQUcsMEJBQTBCLENBQUE7UUFDdEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUE7SUFDdEIsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLHFCQUFzQixTQUFRLEtBQUs7SUFDdkM7Ozs7T0FJRztJQUNILFlBQVksT0FBTyxFQUFFLEVBQUMsSUFBSSxFQUFDO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUNkLElBQUksQ0FBQyxJQUFJLEdBQUcsdUJBQXVCLENBQUE7UUFDbkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUE7SUFDdEIsQ0FBQztDQUNGO0FBRUQ7O0dBRUc7QUFDSCxNQUFNLDRCQUE2QixTQUFRLEtBQUs7SUFDOUM7Ozs7T0FJRztJQUNILFlBQVksT0FBTyxFQUFFLEVBQUMsSUFBSSxFQUFDO1FBQ3pCLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUNkLElBQUksQ0FBQyxJQUFJLEdBQUcsOEJBQThCLENBQUE7UUFDMUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUE7SUFDdEIsQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxPQUFPLE9BQU8sa0JBQWtCO0lBQ3JDOzs7T0FHRztJQUNILFlBQVksRUFB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Q0FBQztJQUNILENBQUM7Q0FDRjtBQUVELE9BQU8sRUFBQyxxQkFBcUIsRUFBRSw0QkFBNEIsRUFBRSx3QkFBd0IsRUFBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB0aW1lb3V0LCB7VGltZW91dEVycm9yfSBmcm9tIFwiYXdhaXRlcnkvYnVpbGQvdGltZW91dC5qc1wiXG5cbi8qKlxuICogVGhyb3duIHdoZW4gYW4gYWR2aXNvcnkgbG9jayBjb3VsZCBub3QgYmUgYWNxdWlyZWQgYmVmb3JlIGB0aW1lb3V0TXNgIGVsYXBzZWQuXG4gKi9cbmNsYXNzIEFkdmlzb3J5TG9ja1RpbWVvdXRFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRXJyb3IgbWVzc2FnZS5cbiAgICogQHBhcmFtIHt7bmFtZTogc3RyaW5nfX0gYXJncyAtIFRoZSBhZHZpc29yeSBsb2NrIG5hbWUgdGhhdCB0aW1lZCBvdXQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlLCB7bmFtZX0pIHtcbiAgICBzdXBlcihtZXNzYWdlKVxuICAgIHRoaXMubmFtZSA9IFwiQWR2aXNvcnlMb2NrVGltZW91dEVycm9yXCJcbiAgICB0aGlzLmxvY2tOYW1lID0gbmFtZVxuICB9XG59XG5cbi8qKlxuICogVGhyb3duIHdoZW4gYHdpdGhBZHZpc29yeUxvY2tPckZhaWxgIGZpbmRzIHRoZSBsb2NrIGFscmVhZHkgaGVsZC5cbiAqL1xuY2xhc3MgQWR2aXNvcnlMb2NrQnVzeUVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICAvKipcbiAgICogUnVucyBjb25zdHJ1Y3Rvci5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2UgLSBFcnJvciBtZXNzYWdlLlxuICAgKiBAcGFyYW0ge3tuYW1lOiBzdHJpbmd9fSBhcmdzIC0gVGhlIGFkdmlzb3J5IGxvY2sgbmFtZSB0aGF0IHdhcyBhbHJlYWR5IGhlbGQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlLCB7bmFtZX0pIHtcbiAgICBzdXBlcihtZXNzYWdlKVxuICAgIHRoaXMubmFtZSA9IFwiQWR2aXNvcnlMb2NrQnVzeUVycm9yXCJcbiAgICB0aGlzLmxvY2tOYW1lID0gbmFtZVxuICB9XG59XG5cbi8qKlxuICogVGhyb3duIHdoZW4gYSBjYWxsYmFjayBob2xkcyBhbiBhZHZpc29yeSBsb2NrIGxvbmdlciB0aGFuIGBob2xkVGltZW91dE1zYC5cbiAqL1xuY2xhc3MgQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXRFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRXJyb3IgbWVzc2FnZS5cbiAgICogQHBhcmFtIHt7bmFtZTogc3RyaW5nfX0gYXJncyAtIFRoZSBhZHZpc29yeSBsb2NrIG5hbWUgd2hvc2UgaG9sZCB0aW1lZCBvdXQuXG4gICAqL1xuICBjb25zdHJ1Y3RvcihtZXNzYWdlLCB7bmFtZX0pIHtcbiAgICBzdXBlcihtZXNzYWdlKVxuICAgIHRoaXMubmFtZSA9IFwiQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXRFcnJvclwiXG4gICAgdGhpcy5sb2NrTmFtZSA9IG5hbWVcbiAgfVxufVxuXG4vKipcbiAqIFJ1bnMgYWR2aXNvcnkgbG9ja3Mgb24gdGhlIGNhbGxlciBjb25uZWN0aW9uIGJ5IGRlZmF1bHQsIHVzaW5nIGEgZGVkaWNhdGVkXG4gKiBsb2NrIGNvbm5lY3Rpb24gd2hlbiBgZGVkaWNhdGVkQ29ubmVjdGlvbmAgaXMgcmVxdWVzdGVkIG9yIHdoZW4gYSBwb3NpdGl2ZVxuICogaG9sZCB0aW1lb3V0IG5lZWRzIHNlcGFyYXRlIG93bmVyc2hpcC5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgQWR2aXNvcnlMb2NrUnVubmVyIHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gYWR2aXNvcnktbG9jayBydW5uZXIgZm9yIG9uZSBtb2RlbCBkYXRhYmFzZSBpZGVudGlmaWVyLlxuICAgKiBAcGFyYW0ge3tjb25maWd1cmF0aW9uOiBpbXBvcnQoXCIuLi9jb25maWd1cmF0aW9uLmpzXCIpLmRlZmF1bHQsIGNvbm5lY3Rpb25Qcm92aWRlcjogKCkgPT4gaW1wb3J0KFwiLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCwgZGF0YWJhc2VJZGVudGlmaWVyOiBzdHJpbmd9fSBhcmdzIC0gUnVubmVyIGRlcGVuZGVuY2llcy5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHtjb25maWd1cmF0aW9uLCBjb25uZWN0aW9uUHJvdmlkZXIsIGRhdGFiYXNlSWRlbnRpZmllcn0pIHtcbiAgICB0aGlzLmNvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uXG4gICAgdGhpcy5jb25uZWN0aW9uUHJvdmlkZXIgPSBjb25uZWN0aW9uUHJvdmlkZXJcbiAgICB0aGlzLmRhdGFiYXNlSWRlbnRpZmllciA9IGRhdGFiYXNlSWRlbnRpZmllclxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYSBjYWxsYmFjayBhZnRlciBhY3F1aXJpbmcgdGhlIGFkdmlzb3J5IGxvY2ssIHdhaXRpbmcgdXAgdG8gYHRpbWVvdXRNc2AuXG4gICAqIFdoZW4gYGRlZGljYXRlZENvbm5lY3Rpb25gIGlzIHRydWUgdGhlIGxvY2sgaXMgYWNxdWlyZWQgb24gYSBzcGF3bmVkXG4gICAqIGNvbm5lY3Rpb24gdGhhdCBpcyByZWxlYXNlZCBhZnRlciB0aGUgY2FsbGJhY2sgZmluaXNoZXMsIHdoaWxlIHRoZSBjYWxsYmFja1xuICAgKiBpdHNlbGYgc3RpbGwgcnVucyBhZ2FpbnN0IHRoZSBjYWxsZXIvbW9kZWwgY29ubmVjdGlvbi4gV2hlbiBhIGBob2xkVGltZW91dE1zYFxuICAgKiBpcyBzZXQgdGhlIGNhbGxiYWNrIHJlY2VpdmVzIGEgYFRpbWVvdXRDb250cm9sYCBmcm9tIGF3YWl0ZXJ5IGZvciBjb29wZXJhdGl2ZVxuICAgKiBjYW5jZWxsYXRpb24gKGBjb250cm9sLmNoZWNrKClgLCBgY29udHJvbC5zaWduYWxgLCBgY29udHJvbC50aW1lZE91dGAsXG4gICAqIGBjb250cm9sLnJlbWFpbmluZygpYCk7IGEgZGVkaWNhdGVkIGNvbm5lY3Rpb24gaXMgYWxzbyB1c2VkIHNvIHRpbWVvdXRcbiAgICogY2xlYW51cCBjYW4gcmVsZWFzZSB0aGUgbG9jayBldmVuIGlmIGNhbGxiYWNrIGRhdGFiYXNlIHdvcmsgaXMgc3R1Y2suXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTG9jayBuYW1lLlxuICAgKiBAcGFyYW0geyhhcmdzPzoge2NvbnRyb2w6IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2x9KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFjayAtIENhbGxiYWNrIHRvIGludm9rZSB3aGlsZSB0aGUgbG9jayBpcyBoZWxkLlxuICAgKiBAcGFyYW0ge3t0aW1lb3V0TXM/OiBudW1iZXIgfCBudWxsLCBob2xkVGltZW91dE1zPzogbnVtYmVyIHwgbnVsbCwgZGVkaWNhdGVkQ29ubmVjdGlvbj86IGJvb2xlYW59fSBbYXJnc10gLSBMb2NrIGFuZCBob2xkIHRpbWVvdXQgb3B0aW9ucy5cbiAgICogQHJldHVybnMge1Byb21pc2U8VD59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgY2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgd2l0aEFkdmlzb3J5TG9jayhuYW1lLCBjYWxsYmFjaywgYXJncyA9IHt9KSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMud2l0aExvY2tDb25uZWN0aW9uKGFyZ3MsIGFzeW5jIChjb25uZWN0aW9uKSA9PiB7XG4gICAgICBjb25zdCBhY3F1aXJlZCA9IGF3YWl0IGNvbm5lY3Rpb24uYWNxdWlyZUFkdmlzb3J5TG9jayhuYW1lLCBhcmdzKVxuXG4gICAgICBpZiAoIWFjcXVpcmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBBZHZpc29yeUxvY2tUaW1lb3V0RXJyb3IoYFRpbWVkIG91dCB3YWl0aW5nIGZvciBhZHZpc29yeSBsb2NrICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9YCwge25hbWV9KVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5Mb2NrZWRDYWxsYmFjayh7Y2FsbGJhY2ssIGNvbm5lY3Rpb24sIGhvbGRUaW1lb3V0TXM6IGFyZ3MuaG9sZFRpbWVvdXRNcywgbmFtZX0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgY2FsbGJhY2sgb25seSBpZiB0aGUgYWR2aXNvcnkgbG9jayBjYW4gYmUgYWNxdWlyZWQgaW1tZWRpYXRlbHkuXG4gICAqIFdoZW4gYGRlZGljYXRlZENvbm5lY3Rpb25gIGlzIHRydWUgdGhlIGxvY2sgaXMgYWNxdWlyZWQgb24gYSBzcGF3bmVkXG4gICAqIGNvbm5lY3Rpb24gdGhhdCBpcyByZWxlYXNlZCBhZnRlciB0aGUgY2FsbGJhY2sgZmluaXNoZXMsIHdoaWxlIHRoZSBjYWxsYmFja1xuICAgKiBpdHNlbGYgc3RpbGwgcnVucyBhZ2FpbnN0IHRoZSBjYWxsZXIvbW9kZWwgY29ubmVjdGlvbi4gV2hlbiBhIGBob2xkVGltZW91dE1zYFxuICAgKiBpcyBzZXQgdGhlIGNhbGxiYWNrIHJlY2VpdmVzIGEgYFRpbWVvdXRDb250cm9sYCBmcm9tIGF3YWl0ZXJ5IGZvciBjb29wZXJhdGl2ZVxuICAgKiBjYW5jZWxsYXRpb24uXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTG9jayBuYW1lLlxuICAgKiBAcGFyYW0geyhhcmdzPzoge2NvbnRyb2w6IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2x9KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFjayAtIENhbGxiYWNrIHRvIGludm9rZSB3aGlsZSB0aGUgbG9jayBpcyBoZWxkLlxuICAgKiBAcGFyYW0ge3tob2xkVGltZW91dE1zPzogbnVtYmVyIHwgbnVsbCwgZGVkaWNhdGVkQ29ubmVjdGlvbj86IGJvb2xlYW59fSBbYXJnc10gLSBIb2xkIHRpbWVvdXQgb3B0aW9ucy5cbiAgICogQHJldHVybnMge1Byb21pc2U8VD59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgY2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgd2l0aEFkdmlzb3J5TG9ja09yRmFpbChuYW1lLCBjYWxsYmFjaywgYXJncyA9IHt9KSB7XG4gICAgcmV0dXJuIGF3YWl0IHRoaXMud2l0aExvY2tDb25uZWN0aW9uKGFyZ3MsIGFzeW5jIChjb25uZWN0aW9uKSA9PiB7XG4gICAgICBjb25zdCBhY3F1aXJlZCA9IGF3YWl0IGNvbm5lY3Rpb24udHJ5QWNxdWlyZUFkdmlzb3J5TG9jayhuYW1lKVxuXG4gICAgICBpZiAoIWFjcXVpcmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBBZHZpc29yeUxvY2tCdXN5RXJyb3IoYEFkdmlzb3J5IGxvY2sgJHtKU09OLnN0cmluZ2lmeShuYW1lKX0gaXMgYWxyZWFkeSBoZWxkYCwge25hbWV9KVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5ydW5Mb2NrZWRDYWxsYmFjayh7Y2FsbGJhY2ssIGNvbm5lY3Rpb24sIGhvbGRUaW1lb3V0TXM6IGFyZ3MuaG9sZFRpbWVvdXRNcywgbmFtZX0pXG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgY2FsbGJhY2sgaWYgdGhlIGFkdmlzb3J5IGxvY2sgY2FuIGJlIGFjcXVpcmVkIHdpdGhvdXQgd2FpdGluZztcbiAgICogb3RoZXJ3aXNlIHJldHVybnMgYSBge2FjcXVpcmVkOiBmYWxzZX1gIGRlZmVyIHJlc3VsdCBpbnN0ZWFkIG9mIHRocm93aW5nLlxuICAgKlxuICAgKiBUaGlzIGlzIHRoZSBub24tdGhyb3dpbmcgY291bnRlcnBhcnQgb2YgYHdpdGhBZHZpc29yeUxvY2tPckZhaWxgIGZvciBob3RcbiAgICogcGF0aHM6IFwiaG9sZGVyIGJ1c3ksIGRlZmVyIG1lXCIgaXMgYSBmaXJzdC1jbGFzcyBvdXRjb21lLCBzbyBhIGNvbnRlbmRlZFxuICAgKiBsb2NrIHByb2R1Y2VzIHplcm8gZXhjZXB0aW9uIHRyYWZmaWMgYW5kIOKAlCBiZWNhdXNlIHRoZSBwcm9iZSBpcyBhIHNpbmdsZVxuICAgKiBpbW1lZGlhdGUgdHJ5LWFjcXVpcmUg4oCUIHplcm8gcGlubmVkIGNvbm5lY3Rpb25zLiBDYWxsZXJzIHJlc2NoZWR1bGUgdmlhXG4gICAqIHRoZWlyIG93biBldmVudC1kcml2ZW4gcmV0cnkgbWFjaGluZXJ5LiBUaGUgcmVzdWx0IGZvcm0gaXMgaWRlbnRpY2FsXG4gICAqIGFjcm9zcyB0aWVyczogdGhlIGRyaXZlcidzIGB0cnlBY3F1aXJlQWR2aXNvcnlMb2NrYCBtYXBzIHBlci10aWVyIChNeVNRTFxuICAgKiBgR0VUX0xPQ0sobmFtZSwgMClgLCBQb3N0Z3JlU1FMIGBwZ190cnlfYWR2aXNvcnlfbG9ja2AsIFNRTCBTZXJ2ZXJcbiAgICogYHNwX2dldGFwcGxvY2sgQExvY2tUaW1lb3V0ID0gMGAsIFNRTGl0ZSBwcm9jZXNzLWxvY2FsIHF1ZXVlLCBTUUxpdGUgTm9kZVxuICAgKiBmaWxlIGxvY2spLCBzbyBhIGNhbGxlciBuZXZlciBicmFuY2hlcyBvbiB0aGUgYmFja2VuZC5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBMb2NrIG5hbWUuXG4gICAqIEBwYXJhbSB7KGFyZ3M/OiB7Y29udHJvbDogaW1wb3J0KFwiYXdhaXRlcnkvYnVpbGQvdGltZW91dC5qc1wiKS5UaW1lb3V0Q29udHJvbH0pID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2sgdG8gaW52b2tlIHdoaWxlIHRoZSBsb2NrIGlzIGhlbGQuXG4gICAqIEBwYXJhbSB7e2hvbGRUaW1lb3V0TXM/OiBudW1iZXIgfCBudWxsLCBkZWRpY2F0ZWRDb25uZWN0aW9uPzogYm9vbGVhbn19IFthcmdzXSAtIEhvbGQgdGltZW91dCBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx7YWNxdWlyZWQ6IHRydWUsIHJlc3VsdDogVH0gfCB7YWNxdWlyZWQ6IGZhbHNlLCByZWFzb246IFwiY29udGVuZGVkXCIsIGxvY2tOYW1lOiBzdHJpbmd9Pn0gLSBFaXRoZXIgdGhlIGhlbGQtY2FsbGJhY2sgcmVzdWx0IG9yIHRoZSBkZWZlciBvdXRjb21lLlxuICAgKi9cbiAgYXN5bmMgd2l0aEFkdmlzb3J5TG9ja09yRGVmZXIobmFtZSwgY2FsbGJhY2ssIGFyZ3MgPSB7fSkge1xuICAgIHJldHVybiBhd2FpdCB0aGlzLndpdGhMb2NrQ29ubmVjdGlvbihhcmdzLCBhc3luYyAoY29ubmVjdGlvbikgPT4ge1xuICAgICAgY29uc3QgYWNxdWlyZWQgPSBhd2FpdCBjb25uZWN0aW9uLnRyeUFjcXVpcmVBZHZpc29yeUxvY2sobmFtZSlcblxuICAgICAgaWYgKCFhY3F1aXJlZCkgcmV0dXJuIHthY3F1aXJlZDogZmFsc2UsIHJlYXNvbjogXCJjb250ZW5kZWRcIiwgbG9ja05hbWU6IG5hbWV9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMucnVuTG9ja2VkQ2FsbGJhY2soe2NhbGxiYWNrLCBjb25uZWN0aW9uLCBob2xkVGltZW91dE1zOiBhcmdzLmhvbGRUaW1lb3V0TXMsIG5hbWV9KVxuXG4gICAgICByZXR1cm4ge2FjcXVpcmVkOiB0cnVlLCByZXN1bHR9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIHRoZSBsb2NrIGhvbGRlciBjYWxsYmFjayBhbmQgcmVsZWFzZXMgdGhlIGxvY2sgZnJvbSBpdHMgb3duaW5nIGNvbm5lY3Rpb24uXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqIEBwYXJhbSB7e2NhbGxiYWNrOiAoYXJncz86IHtjb250cm9sOiBpbXBvcnQoXCJhd2FpdGVyeS9idWlsZC90aW1lb3V0LmpzXCIpLlRpbWVvdXRDb250cm9sfSkgPT4gUHJvbWlzZTxUPiwgY29ubmVjdGlvbjogaW1wb3J0KFwiLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCwgaG9sZFRpbWVvdXRNcz86IG51bWJlciB8IG51bGwsIG5hbWU6IHN0cmluZ319IGFyZ3MgLSBMb2NrZWQgY2FsbGJhY2sgYXJncy5cbiAgICogQHJldHVybnMge1Byb21pc2U8VD59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgY2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgcnVuTG9ja2VkQ2FsbGJhY2soe2NhbGxiYWNrLCBjb25uZWN0aW9uLCBob2xkVGltZW91dE1zLCBuYW1lfSkge1xuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgQWR2aXNvcnlMb2NrUnVubmVyLnJ1bldpdGhBZHZpc29yeUxvY2tIb2xkVGltZW91dChuYW1lLCBjYWxsYmFjaywgaG9sZFRpbWVvdXRNcylcbiAgICB9IGZpbmFsbHkge1xuICAgICAgYXdhaXQgY29ubmVjdGlvbi5yZWxlYXNlQWR2aXNvcnlMb2NrKG5hbWUpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgbG9jayB3b3JrIG9uIHRoZSBjYWxsZXIgY29ubmVjdGlvbiB1bmxlc3MgYGRlZGljYXRlZENvbm5lY3Rpb25gIGlzXG4gICAqIHJlcXVlc3RlZCBvciBhIHBvc2l0aXZlIGhvbGQgdGltZW91dCBuZWVkcyBpdHMgb3duIGxvY2sgY29ubmVjdGlvbi5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHt7ZGVkaWNhdGVkQ29ubmVjdGlvbj86IGJvb2xlYW4sIGhvbGRUaW1lb3V0TXM/OiBudW1iZXIgfCBudWxsfX0gYXJncyAtIExvY2sgY29ubmVjdGlvbiBvcHRpb25zLlxuICAgKiBAcGFyYW0geyhjb25uZWN0aW9uOiBpbXBvcnQoXCIuL2RyaXZlcnMvYmFzZS5qc1wiKS5kZWZhdWx0KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFjayAtIENhbGxiYWNrIHJlY2VpdmluZyB0aGUgY29ubmVjdGlvbiB0aGF0IG93bnMgdGhlIGFkdmlzb3J5IGxvY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFQ+fSAtIFJlc29sdmVzIHdpdGggdGhlIGNhbGxiYWNrIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIHdpdGhMb2NrQ29ubmVjdGlvbihhcmdzLCBjYWxsYmFjaykge1xuICAgIGNvbnN0IGhvbGRUaW1lb3V0TXMgPSBhcmdzLmhvbGRUaW1lb3V0TXNcblxuICAgIGlmIChhcmdzLmRlZGljYXRlZENvbm5lY3Rpb24gfHwgKGhvbGRUaW1lb3V0TXMgJiYgaG9sZFRpbWVvdXRNcyA+IDApKSB7XG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy53aXRoRGVkaWNhdGVkQ29ubmVjdGlvbihjYWxsYmFjaylcbiAgICB9XG5cbiAgICByZXR1cm4gYXdhaXQgY2FsbGJhY2sodGhpcy5jb25uZWN0aW9uUHJvdmlkZXIoKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGF3bnMgYSBkZWRpY2F0ZWQgbG9jayBjb25uZWN0aW9uIGFuZCBjbG9zZXMgaXQgYWZ0ZXIgbG9jayB3b3JrIGNvbXBsZXRlc1xuICAgKiB3aGVuIHRoZSBzcGF3bmVkIGRyaXZlciBvd25zIHRoZSB1bmRlcmx5aW5nIHBoeXNpY2FsIGNvbm5lY3Rpb24uXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqIEBwYXJhbSB7KGNvbm5lY3Rpb246IGltcG9ydChcIi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQpID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2sgdGhhdCByZWNlaXZlcyB0aGUgZGVkaWNhdGVkIGxvY2sgY29ubmVjdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8VD59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgY2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgd2l0aERlZGljYXRlZENvbm5lY3Rpb24oY2FsbGJhY2spIHtcbiAgICBjb25zdCBjb25uZWN0aW9uID0gYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmdldERhdGFiYXNlUG9vbCh0aGlzLmRhdGFiYXNlSWRlbnRpZmllcikuc3Bhd25Db25uZWN0aW9uKClcblxuICAgIC8vIFRoZSBzcGF3bmVkIGRyaXZlciBvd25zIGl0cyBwaHlzaWNhbCBjb25uZWN0aW9uIHVubGVzcyBpdCBib3Jyb3dzIGEgc2hhcmVkIG9uZVxuICAgIC8vIHZpYSBgZ2V0Q29ubmVjdGlvbmAuIEFuIG93bmVkIGNvbm5lY3Rpb24gbGl2ZXMgb3V0c2lkZSB0aGUgcG9vbHMnIHRyYWNrZWQgc2V0cyxcbiAgICAvLyBzbyByZWdpc3RlciBpdCB3aGlsZSB0aGUgbG9jayBpcyBoZWxkOiBhIHNodXRkb3duIHRoZW4gY2xvc2VzIGl0IChyZWxlYXNpbmcgdGhlXG4gICAgLy8gbG9jaykgaW5zdGVhZCBvZiBvcnBoYW5pbmcgYSBoYWxmLW9wZW4gc2Vzc2lvbiB1bnRpbCB0aGUgREIgYHdhaXRfdGltZW91dGAuXG4gICAgY29uc3Qgb3duc0Nvbm5lY3Rpb24gPSAhY29ubmVjdGlvbi5nZXRBcmdzKCkuZ2V0Q29ubmVjdGlvblxuXG4gICAgaWYgKG93bnNDb25uZWN0aW9uKSB0aGlzLmNvbmZpZ3VyYXRpb24ucmVnaXN0ZXJBZHZpc29yeUxvY2tDb25uZWN0aW9uKGNvbm5lY3Rpb24pXG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGNhbGxiYWNrKGNvbm5lY3Rpb24pXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIGlmIChvd25zQ29ubmVjdGlvbikge1xuICAgICAgICB0aGlzLmNvbmZpZ3VyYXRpb24udW5yZWdpc3RlckFkdmlzb3J5TG9ja0Nvbm5lY3Rpb24oY29ubmVjdGlvbilcbiAgICAgICAgYXdhaXQgY29ubmVjdGlvbi5jbG9zZSgpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhd2FpdCBjb25uZWN0aW9uLnJlbGVhc2VIZWxkQWR2aXNvcnlMb2NrcygpXG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYGNhbGxiYWNrYCwgcmVqZWN0aW5nIHdpdGggYEFkdmlzb3J5TG9ja0hvbGRUaW1lb3V0RXJyb3JgIGlmIGl0IGhhc1xuICAgKiBub3Qgc2V0dGxlZCB3aXRoaW4gYGhvbGRUaW1lb3V0TXNgLiBUaGUgY2FsbGJhY2sgaXMgbm90IGNhbmNlbGxlZDsgY2FsbGVyc1xuICAgKiB1c2UgYSBkZWRpY2F0ZWQgYWR2aXNvcnktbG9jayBjb25uZWN0aW9uIHNvIHRoZSBsb2NrIGNhbiBzdGlsbCBiZSByZWxlYXNlZC5cbiAgICpcbiAgICogVGhlIGNhbGxiYWNrIHJlY2VpdmVzIGEgYFRpbWVvdXRDb250cm9sYCBmcm9tIGF3YWl0ZXJ5LCBlbmFibGluZyBjb29wZXJhdGl2ZVxuICAgKiBjYW5jZWxsYXRpb24gdmlhIGBjb250cm9sLmNoZWNrKClgLCBgY29udHJvbC5zaWduYWxgLCBgY29udHJvbC50aW1lZE91dGAsXG4gICAqIGFuZCBgY29udHJvbC5yZW1haW5pbmcoKWAuXG4gICAqIEB0ZW1wbGF0ZSBUXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTG9jayBuYW1lIChmb3IgdGhlIGVycm9yIG1lc3NhZ2UpLlxuICAgKiBAcGFyYW0geyhhcmdzPzoge2NvbnRyb2w6IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2x9KSA9PiBQcm9taXNlPFQ+fSBjYWxsYmFjayAtIENhbGxiYWNrIGhvbGRpbmcgdGhlIGxvY2suXG4gICAqIEBwYXJhbSB7bnVtYmVyIHwgbnVsbH0gW2hvbGRUaW1lb3V0TXNdIC0gTWF4IGhvbGQgdGltZTsgZmFsc3kgZGlzYWJsZXMgdGhlIHRpbWVvdXQuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFQ+fSAtIFJlc29sdmVzIHdpdGggdGhlIGNhbGxiYWNrIHJlc3VsdC5cbiAgICovXG4gIHN0YXRpYyBhc3luYyBydW5XaXRoQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXQobmFtZSwgY2FsbGJhY2ssIGhvbGRUaW1lb3V0TXMpIHtcbiAgICBpZiAoIWhvbGRUaW1lb3V0TXMgfHwgaG9sZFRpbWVvdXRNcyA8PSAwKSB7XG4gICAgICByZXR1cm4gYXdhaXQgY2FsbGJhY2soKVxuICAgIH1cblxuICAgIGxldCBjYWxsYmFja1NldHRsZWQgPSBmYWxzZVxuXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCB0aW1lb3V0KHt0aW1lb3V0OiBob2xkVGltZW91dE1zfSwgYXN5bmMgKHtjb250cm9sfSkgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBhd2FpdCBjYWxsYmFjayh7Y29udHJvbH0pXG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgY2FsbGJhY2tTZXR0bGVkID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBpZiAoIWNhbGxiYWNrU2V0dGxlZCB8fCBlcnJvciBpbnN0YW5jZW9mIFRpbWVvdXRFcnJvcikge1xuICAgICAgICB0aHJvdyBuZXcgQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXRFcnJvcihgQWR2aXNvcnkgbG9jayAke0pTT04uc3RyaW5naWZ5KG5hbWUpfSBoZWxkIGxvbmdlciB0aGFuICR7aG9sZFRpbWVvdXRNc31tc2AsIHtuYW1lfSlcbiAgICAgIH1cblxuICAgICAgdGhyb3cgZXJyb3JcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IHtBZHZpc29yeUxvY2tCdXN5RXJyb3IsIEFkdmlzb3J5TG9ja0hvbGRUaW1lb3V0RXJyb3IsIEFkdmlzb3J5TG9ja1RpbWVvdXRFcnJvcn1cbiJdfQ==
|
|
405
|
+
export { AdvisoryLockBackendUnavailableError, AdvisoryLockMinTierRefusedError } from "./advisory-lock-backend-policy.js";
|
|
406
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWR2aXNvcnktbG9jay1ydW5uZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGF0YWJhc2UvYWR2aXNvcnktbG9jay1ydW5uZXIuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sT0FBTyxFQUFFLEVBQUMsWUFBWSxFQUFDLE1BQU0sMkJBQTJCLENBQUE7QUFDL0QsT0FBTyxFQUFDLHdDQUF3QyxFQUFDLE1BQU0sMEJBQTBCLENBQUE7QUFDakYsT0FBTyxFQUNMLG1DQUFtQyxFQUNuQyxnQ0FBZ0MsRUFDaEMsa0NBQWtDLEVBQ25DLE1BQU0sbUNBQW1DLENBQUE7QUFFMUM7Ozs7Ozs7Ozs7R0FVRztBQUVIOztHQUVHO0FBQ0gsTUFBTSx3QkFBeUIsU0FBUSxLQUFLO0lBQzFDOzs7O09BSUc7SUFDSCxZQUFZLE9BQU8sRUFBRSxFQUFDLElBQUksRUFBQztRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDZCxJQUFJLENBQUMsSUFBSSxHQUFHLDBCQUEwQixDQUFBO1FBQ3RDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFBO0lBQ3RCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSxxQkFBc0IsU0FBUSxLQUFLO0lBQ3ZDOzs7O09BSUc7SUFDSCxZQUFZLE9BQU8sRUFBRSxFQUFDLElBQUksRUFBQztRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDZCxJQUFJLENBQUMsSUFBSSxHQUFHLHVCQUF1QixDQUFBO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFBO0lBQ3RCLENBQUM7Q0FDRjtBQUVEOztHQUVHO0FBQ0gsTUFBTSw0QkFBNkIsU0FBUSxLQUFLO0lBQzlDOzs7O09BSUc7SUFDSCxZQUFZLE9BQU8sRUFBRSxFQUFDLElBQUksRUFBQztRQUN6QixLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDZCxJQUFJLENBQUMsSUFBSSxHQUFH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QUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyx3QkFBd0I7UUFDN0IsT0FBTyxFQUFDLE9BQU8sRUFBRSxlQUFlLEVBQUUsZ0JBQWdCLEVBQUUsS0FBSyxFQUFDLENBQUE7SUFDNUQsQ0FBQztDQUNGO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsZ0NBQWdDLENBQUMsTUFBTTtJQUM5QyxPQUFPLE1BQU0sQ0FBQyxZQUFZLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0FBQzdDLENBQUM7QUFFRCxPQUFPLEVBQUMscUJBQXFCLEVBQUUsNEJBQTRCLEVBQUUsd0JBQXdCLEVBQUMsQ0FBQTtBQUN0RixPQUFPLEVBQUMsbUNBQW1DLEVBQUUsK0JBQStCLEVBQUMsTUFBTSxtQ0FBbUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgdGltZW91dCwge1RpbWVvdXRFcnJvcn0gZnJvbSBcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIlxuaW1wb3J0IHtERUZBVUxUX0FEVklTT1JZX0xPQ0tfQUNRVUlSRV9USU1FT1VUX01TfSBmcm9tIFwiLi9hZHZpc29yeS1sb2NrLWJvdW5kLmpzXCJcbmltcG9ydCB7XG4gIEFkdmlzb3J5TG9ja0JhY2tlbmRVbmF2YWlsYWJsZUVycm9yLFxuICByZXNvbHZlQWR2aXNvcnlMb2NrQmFja2VuZFBvbGljeSxcbiAgcmVmdXNlQWR2aXNvcnlMb2NrVGllckJlbG93TWluaW11bVxufSBmcm9tIFwiLi9hZHZpc29yeS1sb2NrLWJhY2tlbmQtcG9saWN5LmpzXCJcblxuLyoqXG4gKiBQcm92ZW5hbmNlIG9mIG9uZSBhZHZpc29yeS1sb2NrIGFjcXVpc2l0aW9uIChTVEMtMjEwIGRlc2lnbiDCpzMpOiBldmVyeVxuICogaGVsZCBsb2NrIHJlcG9ydHMgdGhlIHRpZXIgdGhhdCBhY3R1YWxseSBzZXJ2ZWQgaXQsIHNvIGEgZmFsbGJhY2sgaXNcbiAqIHZpc2libGUgdG8gdGhlIGNhbGxiYWNrLCBpbiBsb2dzLCBhbmQgaW4gYGdldEFkdmlzb3J5TG9ja0JhY2tlbmRTdGF0dXMoKWAuXG4gKiBAdHlwZWRlZiB7b2JqZWN0fSBBZHZpc29yeUxvY2tCYWNrZW5kUHJvdmVuYW5jZVxuICogQHByb3BlcnR5IHtpbXBvcnQoXCIuL2Fkdmlzb3J5LWxvY2stYmFja2VuZC1wb2xpY3kuanNcIikuQWR2aXNvcnlMb2NrVGllcn0gYmFja2VuZCAtIFRpZXIgdGhhdCBzZXJ2ZWQgdGhlIGFjcXVpc2l0aW9uLlxuICogQHByb3BlcnR5IHtzdHJpbmd9IFtkcml2ZXJUeXBlXSAtIERhdGFiYXNlIGRyaXZlciB0eXBlIHdoZW4gdGhlIGRyaXZlciB0aWVyIHNlcnZlZCBpdC5cbiAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gZmVuY2luZ1N1cHBvcnRlZCAtIFdoZXRoZXIgdGhpcyB0aWVyIGNhcnJpZXMgZmVuY2luZyB0b2tlbnMgKGRlc2lnbiDCpzgpOyB0aGUgZmlsZSB0aWVyIHJlcG9ydHMgZmFsc2UgcmF0aGVyIHRoYW4gcHJldGVuZGluZy5cbiAqIEBwcm9wZXJ0eSB7c3RyaW5nfSBbaG9sZGVySWRdIC0gQmFja2VuZCBob2xkZXIgaWQgZm9yIHRoZSBmaWxlIHRpZXIuXG4gKiBAcHJvcGVydHkge3N0cmluZ30gW2xvY2tOYW1lXSAtIExvY2sgbmFtZSB0aGlzIHByb3ZlbmFuY2UgYmVsb25ncyB0by5cbiAqL1xuXG4vKipcbiAqIFRocm93biB3aGVuIGFuIGFkdmlzb3J5IGxvY2sgY291bGQgbm90IGJlIGFjcXVpcmVkIGJlZm9yZSBgdGltZW91dE1zYCBlbGFwc2VkLlxuICovXG5jbGFzcyBBZHZpc29yeUxvY2tUaW1lb3V0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIC8qKlxuICAgKiBSdW5zIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIEVycm9yIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSB7e25hbWU6IHN0cmluZ319IGFyZ3MgLSBUaGUgYWR2aXNvcnkgbG9jayBuYW1lIHRoYXQgdGltZWQgb3V0LlxuICAgKi9cbiAgY29uc3RydWN0b3IobWVzc2FnZSwge25hbWV9KSB7XG4gICAgc3VwZXIobWVzc2FnZSlcbiAgICB0aGlzLm5hbWUgPSBcIkFkdmlzb3J5TG9ja1RpbWVvdXRFcnJvclwiXG4gICAgdGhpcy5sb2NrTmFtZSA9IG5hbWVcbiAgfVxufVxuXG4vKipcbiAqIFRocm93biB3aGVuIGB3aXRoQWR2aXNvcnlMb2NrT3JGYWlsYCBmaW5kcyB0aGUgbG9jayBhbHJlYWR5IGhlbGQuXG4gKi9cbmNsYXNzIEFkdmlzb3J5TG9ja0J1c3lFcnJvciBleHRlbmRzIEVycm9yIHtcbiAgLyoqXG4gICAqIFJ1bnMgY29uc3RydWN0b3IuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlIC0gRXJyb3IgbWVzc2FnZS5cbiAgICogQHBhcmFtIHt7bmFtZTogc3RyaW5nfX0gYXJncyAtIFRoZSBhZHZpc29yeSBsb2NrIG5hbWUgdGhhdCB3YXMgYWxyZWFkeSBoZWxkLlxuICAgKi9cbiAgY29uc3RydWN0b3IobWVzc2FnZSwge25hbWV9KSB7XG4gICAgc3VwZXIobWVzc2FnZSlcbiAgICB0aGlzLm5hbWUgPSBcIkFkdmlzb3J5TG9ja0J1c3lFcnJvclwiXG4gICAgdGhpcy5sb2NrTmFtZSA9IG5hbWVcbiAgfVxufVxuXG4vKipcbiAqIFRocm93biB3aGVuIGEgY2FsbGJhY2sgaG9sZHMgYW4gYWR2aXNvcnkgbG9jayBsb25nZXIgdGhhbiBgaG9sZFRpbWVvdXRNc2AuXG4gKi9cbmNsYXNzIEFkdmlzb3J5TG9ja0hvbGRUaW1lb3V0RXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIC8qKlxuICAgKiBSdW5zIGNvbnN0cnVjdG9yLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZSAtIEVycm9yIG1lc3NhZ2UuXG4gICAqIEBwYXJhbSB7e25hbWU6IHN0cmluZ319IGFyZ3MgLSBUaGUgYWR2aXNvcnkgbG9jayBuYW1lIHdob3NlIGhvbGQgdGltZWQgb3V0LlxuICAgKi9cbiAgY29uc3RydWN0b3IobWVzc2FnZSwge25hbWV9KSB7XG4gICAgc3VwZXIobWVzc2FnZSlcbiAgICB0aGlzLm5hbWUgPSBcIkFkdmlzb3J5TG9ja0hvbGRUaW1lb3V0RXJyb3JcIlxuICAgIHRoaXMubG9ja05hbWUgPSBuYW1lXG4gIH1cbn1cblxuLyoqXG4gKiBSdW5zIGFkdmlzb3J5IGxvY2tzIG9uIHRoZSBjYWxsZXIgY29ubmVjdGlvbiBieSBkZWZhdWx0LCB1c2luZyBhIGRlZGljYXRlZFxuICogbG9jayBjb25uZWN0aW9uIHdoZW4gYGRlZGljYXRlZENvbm5lY3Rpb25gIGlzIHJlcXVlc3RlZCBvciB3aGVuIGEgcG9zaXRpdmVcbiAqIGhvbGQgdGltZW91dCBuZWVkcyBzZXBhcmF0ZSBvd25lcnNoaXAuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEFkdmlzb3J5TG9ja1J1bm5lciB7XG4gIC8qKlxuICAgKiBDcmVhdGVzIGFuIGFkdmlzb3J5LWxvY2sgcnVubmVyIGZvciBvbmUgbW9kZWwgZGF0YWJhc2UgaWRlbnRpZmllci5cbiAgICogQHBhcmFtIHt7Y29uZmlndXJhdGlvbjogaW1wb3J0KFwiLi4vY29uZmlndXJhdGlvbi5qc1wiKS5kZWZhdWx0LCBjb25uZWN0aW9uUHJvdmlkZXI6ICgpID0+IGltcG9ydChcIi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQsIGRhdGFiYXNlSWRlbnRpZmllcjogc3RyaW5nfX0gYXJncyAtIFJ1bm5lciBkZXBlbmRlbmNpZXMuXG4gICAqL1xuICBjb25zdHJ1Y3Rvcih7Y29uZmlndXJhdGlvbiwgY29ubmVjdGlvblByb3ZpZGVyLCBkYXRhYmFzZUlkZW50aWZpZXJ9KSB7XG4gICAgdGhpcy5jb25maWd1cmF0aW9uID0gY29uZmlndXJhdGlvblxuICAgIHRoaXMuY29ubmVjdGlvblByb3ZpZGVyID0gY29ubmVjdGlvblByb3ZpZGVyXG4gICAgdGhpcy5kYXRhYmFzZUlkZW50aWZpZXIgPSBkYXRhYmFzZUlkZW50aWZpZXJcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW5zIGEgY2FsbGJhY2sgYWZ0ZXIgYWNxdWlyaW5nIHRoZSBhZHZpc29yeSBsb2NrLCB3YWl0aW5nIHVwIHRvIGB0aW1lb3V0TXNgLlxuICAgKiBXaGVuIGBkZWRpY2F0ZWRDb25uZWN0aW9uYCBpcyB0cnVlIHRoZSBsb2NrIGlzIGFjcXVpcmVkIG9uIGEgc3Bhd25lZFxuICAgKiBjb25uZWN0aW9uIHRoYXQgaXMgcmVsZWFzZWQgYWZ0ZXIgdGhlIGNhbGxiYWNrIGZpbmlzaGVzLCB3aGlsZSB0aGUgY2FsbGJhY2tcbiAgICogaXRzZWxmIHN0aWxsIHJ1bnMgYWdhaW5zdCB0aGUgY2FsbGVyL21vZGVsIGNvbm5lY3Rpb24uIFdoZW4gYSBgaG9sZFRpbWVvdXRNc2BcbiAgICogaXMgc2V0IHRoZSBjYWxsYmFjayByZWNlaXZlcyBhIGBUaW1lb3V0Q29udHJvbGAgZnJvbSBhd2FpdGVyeSBmb3IgY29vcGVyYXRpdmVcbiAgICogY2FuY2VsbGF0aW9uIChgY29udHJvbC5jaGVjaygpYCwgYGNvbnRyb2wuc2lnbmFsYCwgYGNvbnRyb2wudGltZWRPdXRgLFxuICAgKiBgY29udHJvbC5yZW1haW5pbmcoKWApOyBhIGRlZGljYXRlZCBjb25uZWN0aW9uIGlzIGFsc28gdXNlZCBzbyB0aW1lb3V0XG4gICAqIGNsZWFudXAgY2FuIHJlbGVhc2UgdGhlIGxvY2sgZXZlbiBpZiBjYWxsYmFjayBkYXRhYmFzZSB3b3JrIGlzIHN0dWNrLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIExvY2sgbmFtZS5cbiAgICogQHBhcmFtIHsoYXJncz86IHtjb250cm9sPzogaW1wb3J0KFwiYXdhaXRlcnkvYnVpbGQvdGltZW91dC5qc1wiKS5UaW1lb3V0Q29udHJvbCwgbG9ja0JhY2tlbmQ6IEFkdmlzb3J5TG9ja0JhY2tlbmRQcm92ZW5hbmNlfSkgPT4gUHJvbWlzZTxUPn0gY2FsbGJhY2sgLSBDYWxsYmFjayB0byBpbnZva2Ugd2hpbGUgdGhlIGxvY2sgaXMgaGVsZC5cbiAgICogQHBhcmFtIHt7dGltZW91dE1zPzogbnVtYmVyIHwgbnVsbCwgaG9sZFRpbWVvdXRNcz86IG51bWJlciB8IG51bGwsIGRlZGljYXRlZENvbm5lY3Rpb24/OiBib29sZWFufX0gW2FyZ3NdIC0gTG9jayBhbmQgaG9sZCB0aW1lb3V0IG9wdGlvbnMuXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFQ+fSAtIFJlc29sdmVzIHdpdGggdGhlIGNhbGxiYWNrIHJlc3VsdC5cbiAgICovXG4gIGFzeW5jIHdpdGhBZHZpc29yeUxvY2sobmFtZSwgY2FsbGJhY2ssIGFyZ3MgPSB7fSkge1xuICAgIGNvbnN0IGZpbGVCYWNrZW5kID0gYXdhaXQgdGhpcy5maWxlQmFja2VuZEZvck5hbWUobmFtZSlcblxuICAgIGlmIChmaWxlQmFja2VuZCkge1xuICAgICAgY29uc3QgYWNxdWlyZWQgPSBhd2FpdCBmaWxlQmFja2VuZC5hY3F1aXJlKG5hbWUsIHt0aW1lb3V0TXM6IHRoaXMuZmlsZUFjcXVpcmVUaW1lb3V0TXMoYXJncyl9KVxuXG4gICAgICBpZiAoIWFjcXVpcmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBBZHZpc29yeUxvY2tUaW1lb3V0RXJyb3IoYFRpbWVkIG91dCB3YWl0aW5nIGZvciBhZHZpc29yeSBsb2NrICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IG9uIHRoZSBmaWxlIHRpZXJgLCB7bmFtZX0pXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxvY2tCYWNrZW5kID0gdGhpcy5maWxlUHJvdmVuYW5jZShmaWxlQmFja2VuZCwgbmFtZSlcblxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnJlY29yZEFkdmlzb3J5TG9ja0FjcXVpc2l0aW9uKHtiYWNrZW5kOiBsb2NrQmFja2VuZC5iYWNrZW5kLCBmZW5jaW5nU3VwcG9ydGVkOiBsb2NrQmFja2VuZC5mZW5jaW5nU3VwcG9ydGVkLCBsb2NrTmFtZTogbmFtZX0pXG5cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJ1bkxvY2tlZENhbGxiYWNrKHtjYWxsYmFjaywgaG9sZFRpbWVvdXRNczogYXJncy5ob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCwgbmFtZSwgcmVsZWFzZTogYXN5bmMgKCkgPT4gYXdhaXQgZmlsZUJhY2tlbmQucmVsZWFzZShuYW1lKX0pXG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMud2l0aExvY2tDb25uZWN0aW9uKGFyZ3MsIGFzeW5jIChjb25uZWN0aW9uKSA9PiB7XG4gICAgICBjb25zdCBsb2NrQmFja2VuZCA9IHRoaXMuZHJpdmVyUHJvdmVuYW5jZShjb25uZWN0aW9uKVxuXG4gICAgICB0aGlzLmFzc2VydERyaXZlclRpZXJFbGlnaWJsZShuYW1lLCBsb2NrQmFja2VuZClcblxuICAgICAgY29uc3QgYWNxdWlyZWQgPSBhd2FpdCBjb25uZWN0aW9uLmFjcXVpcmVBZHZpc29yeUxvY2sobmFtZSwgYXJncylcblxuICAgICAgaWYgKCFhY3F1aXJlZCkge1xuICAgICAgICB0aHJvdyBuZXcgQWR2aXNvcnlMb2NrVGltZW91dEVycm9yKGBUaW1lZCBvdXQgd2FpdGluZyBmb3IgYWR2aXNvcnkgbG9jayAke0pTT04uc3RyaW5naWZ5KG5hbWUpfWAsIHtuYW1lfSlcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnJlY29yZEFkdmlzb3J5TG9ja0FjcXVpc2l0aW9uKHtiYWNrZW5kOiBsb2NrQmFja2VuZC5iYWNrZW5kLCBmZW5jaW5nU3VwcG9ydGVkOiBsb2NrQmFja2VuZC5mZW5jaW5nU3VwcG9ydGVkLCBsb2NrTmFtZTogbmFtZX0pXG5cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJ1bkxvY2tlZENhbGxiYWNrKHtjYWxsYmFjaywgaG9sZFRpbWVvdXRNczogYXJncy5ob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCwgbmFtZSwgcmVsZWFzZTogYXN5bmMgKCkgPT4gYXdhaXQgY29ubmVjdGlvbi5yZWxlYXNlQWR2aXNvcnlMb2NrKG5hbWUpfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgYSBjYWxsYmFjayBvbmx5IGlmIHRoZSBhZHZpc29yeSBsb2NrIGNhbiBiZSBhY3F1aXJlZCBpbW1lZGlhdGVseS5cbiAgICogV2hlbiBgZGVkaWNhdGVkQ29ubmVjdGlvbmAgaXMgdHJ1ZSB0aGUgbG9jayBpcyBhY3F1aXJlZCBvbiBhIHNwYXduZWRcbiAgICogY29ubmVjdGlvbiB0aGF0IGlzIHJlbGVhc2VkIGFmdGVyIHRoZSBjYWxsYmFjayBmaW5pc2hlcywgd2hpbGUgdGhlIGNhbGxiYWNrXG4gICAqIGl0c2VsZiBzdGlsbCBydW5zIGFnYWluc3QgdGhlIGNhbGxlci9tb2RlbCBjb25uZWN0aW9uLiBXaGVuIGEgYGhvbGRUaW1lb3V0TXNgXG4gICAqIGlzIHNldCB0aGUgY2FsbGJhY2sgcmVjZWl2ZXMgYSBgVGltZW91dENvbnRyb2xgIGZyb20gYXdhaXRlcnkgZm9yIGNvb3BlcmF0aXZlXG4gICAqIGNhbmNlbGxhdGlvbi5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBMb2NrIG5hbWUuXG4gICAqIEBwYXJhbSB7KGFyZ3M/OiB7Y29udHJvbD86IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2wsIGxvY2tCYWNrZW5kOiBBZHZpc29yeUxvY2tCYWNrZW5kUHJvdmVuYW5jZX0pID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2sgdG8gaW52b2tlIHdoaWxlIHRoZSBsb2NrIGlzIGhlbGQuXG4gICAqIEBwYXJhbSB7e2hvbGRUaW1lb3V0TXM/OiBudW1iZXIgfCBudWxsLCBkZWRpY2F0ZWRDb25uZWN0aW9uPzogYm9vbGVhbn19IFthcmdzXSAtIEhvbGQgdGltZW91dCBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUPn0gLSBSZXNvbHZlcyB3aXRoIHRoZSBjYWxsYmFjayByZXN1bHQuXG4gICAqL1xuICBhc3luYyB3aXRoQWR2aXNvcnlMb2NrT3JGYWlsKG5hbWUsIGNhbGxiYWNrLCBhcmdzID0ge30pIHtcbiAgICBjb25zdCBmaWxlQmFja2VuZCA9IGF3YWl0IHRoaXMuZmlsZUJhY2tlbmRGb3JOYW1lKG5hbWUpXG5cbiAgICBpZiAoZmlsZUJhY2tlbmQpIHtcbiAgICAgIGNvbnN0IGFjcXVpcmVkID0gYXdhaXQgZmlsZUJhY2tlbmQudHJ5QWNxdWlyZShuYW1lKVxuXG4gICAgICBpZiAoIWFjcXVpcmVkKSB7XG4gICAgICAgIHRocm93IG5ldyBBZHZpc29yeUxvY2tCdXN5RXJyb3IoYEFkdmlzb3J5IGxvY2sgJHtKU09OLnN0cmluZ2lmeShuYW1lKX0gaXMgYWxyZWFkeSBoZWxkIG9uIHRoZSBmaWxlIHRpZXJgLCB7bmFtZX0pXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGxvY2tCYWNrZW5kID0gdGhpcy5maWxlUHJvdmVuYW5jZShmaWxlQmFja2VuZCwgbmFtZSlcblxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnJlY29yZEFkdmlzb3J5TG9ja0FjcXVpc2l0aW9uKHtiYWNrZW5kOiBsb2NrQmFja2VuZC5iYWNrZW5kLCBmZW5jaW5nU3VwcG9ydGVkOiBsb2NrQmFja2VuZC5mZW5jaW5nU3VwcG9ydGVkLCBsb2NrTmFtZTogbmFtZX0pXG5cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJ1bkxvY2tlZENhbGxiYWNrKHtjYWxsYmFjaywgaG9sZFRpbWVvdXRNczogYXJncy5ob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCwgbmFtZSwgcmVsZWFzZTogYXN5bmMgKCkgPT4gYXdhaXQgZmlsZUJhY2tlbmQucmVsZWFzZShuYW1lKX0pXG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMud2l0aExvY2tDb25uZWN0aW9uKGFyZ3MsIGFzeW5jIChjb25uZWN0aW9uKSA9PiB7XG4gICAgICBjb25zdCBsb2NrQmFja2VuZCA9IHRoaXMuZHJpdmVyUHJvdmVuYW5jZShjb25uZWN0aW9uKVxuXG4gICAgICB0aGlzLmFzc2VydERyaXZlclRpZXJFbGlnaWJsZShuYW1lLCBsb2NrQmFja2VuZClcblxuICAgICAgY29uc3QgYWNxdWlyZWQgPSBhd2FpdCBjb25uZWN0aW9uLnRyeUFjcXVpcmVBZHZpc29yeUxvY2sobmFtZSlcblxuICAgICAgaWYgKCFhY3F1aXJlZCkge1xuICAgICAgICB0aHJvdyBuZXcgQWR2aXNvcnlMb2NrQnVzeUVycm9yKGBBZHZpc29yeSBsb2NrICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IGlzIGFscmVhZHkgaGVsZGAsIHtuYW1lfSlcbiAgICAgIH1cblxuICAgICAgdGhpcy5jb25maWd1cmF0aW9uLnJlY29yZEFkdmlzb3J5TG9ja0FjcXVpc2l0aW9uKHtiYWNrZW5kOiBsb2NrQmFja2VuZC5iYWNrZW5kLCBmZW5jaW5nU3VwcG9ydGVkOiBsb2NrQmFja2VuZC5mZW5jaW5nU3VwcG9ydGVkLCBsb2NrTmFtZTogbmFtZX0pXG5cbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLnJ1bkxvY2tlZENhbGxiYWNrKHtjYWxsYmFjaywgaG9sZFRpbWVvdXRNczogYXJncy5ob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCwgbmFtZSwgcmVsZWFzZTogYXN5bmMgKCkgPT4gYXdhaXQgY29ubmVjdGlvbi5yZWxlYXNlQWR2aXNvcnlMb2NrKG5hbWUpfSlcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gIC8qKlxuICAgKiBSdW5zIGEgY2FsbGJhY2sgaWYgdGhlIGFkdmlzb3J5IGxvY2sgY2FuIGJlIGFjcXVpcmVkIHdpdGhvdXQgd2FpdGluZztcbiAgICogb3RoZXJ3aXNlIHJldHVybnMgYSBge2FjcXVpcmVkOiBmYWxzZX1gIGRlZmVyIHJlc3VsdCBpbnN0ZWFkIG9mIHRocm93aW5nLlxuICAgKlxuICAgKiBUaGlzIGlzIHRoZSBub24tdGhyb3dpbmcgY291bnRlcnBhcnQgb2YgYHdpdGhBZHZpc29yeUxvY2tPckZhaWxgIGZvciBob3RcbiAgICogcGF0aHM6IFwiaG9sZGVyIGJ1c3ksIGRlZmVyIG1lXCIgaXMgYSBmaXJzdC1jbGFzcyBvdXRjb21lLCBzbyBhIGNvbnRlbmRlZFxuICAgKiBsb2NrIHByb2R1Y2VzIHplcm8gZXhjZXB0aW9uIHRyYWZmaWMgYW5kIOKAlCBiZWNhdXNlIHRoZSBwcm9iZSBpcyBhIHNpbmdsZVxuICAgKiBpbW1lZGlhdGUgdHJ5LWFjcXVpcmUg4oCUIHplcm8gcGlubmVkIGNvbm5lY3Rpb25zLiBDYWxsZXJzIHJlc2NoZWR1bGUgdmlhXG4gICAqIHRoZWlyIG93biBldmVudC1kcml2ZW4gcmV0cnkgbWFjaGluZXJ5LiBUaGUgcmVzdWx0IGZvcm0gaXMgaWRlbnRpY2FsXG4gICAqIGFjcm9zcyB0aWVyczogdGhlIGRyaXZlcidzIGB0cnlBY3F1aXJlQWR2aXNvcnlMb2NrYCBtYXBzIHBlci10aWVyIChNeVNRTFxuICAgKiBgR0VUX0xPQ0sobmFtZSwgMClgLCBQb3N0Z3JlU1FMIGBwZ190cnlfYWR2aXNvcnlfbG9ja2AsIFNRTCBTZXJ2ZXJcbiAgICogYHNwX2dldGFwcGxvY2sgQExvY2tUaW1lb3V0ID0gMGAsIFNRTGl0ZSBwcm9jZXNzLWxvY2FsIHF1ZXVlLCBTUUxpdGUgTm9kZVxuICAgKiBmaWxlIGxvY2spLCBzbyBhIGNhbGxlciBuZXZlciBicmFuY2hlcyBvbiB0aGUgYmFja2VuZC5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBMb2NrIG5hbWUuXG4gICAqIEBwYXJhbSB7KGFyZ3M/OiB7Y29udHJvbD86IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2wsIGxvY2tCYWNrZW5kOiBBZHZpc29yeUxvY2tCYWNrZW5kUHJvdmVuYW5jZX0pID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2sgdG8gaW52b2tlIHdoaWxlIHRoZSBsb2NrIGlzIGhlbGQuXG4gICAqIEBwYXJhbSB7e2hvbGRUaW1lb3V0TXM/OiBudW1iZXIgfCBudWxsLCBkZWRpY2F0ZWRDb25uZWN0aW9uPzogYm9vbGVhbn19IFthcmdzXSAtIEhvbGQgdGltZW91dCBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTx7YWNxdWlyZWQ6IHRydWUsIHJlc3VsdDogVH0gfCB7YWNxdWlyZWQ6IGZhbHNlLCByZWFzb246IFwiY29udGVuZGVkXCIsIGxvY2tOYW1lOiBzdHJpbmd9Pn0gLSBFaXRoZXIgdGhlIGhlbGQtY2FsbGJhY2sgcmVzdWx0IG9yIHRoZSBkZWZlciBvdXRjb21lLlxuICAgKi9cbiAgYXN5bmMgd2l0aEFkdmlzb3J5TG9ja09yRGVmZXIobmFtZSwgY2FsbGJhY2ssIGFyZ3MgPSB7fSkge1xuICAgIGNvbnN0IGZpbGVCYWNrZW5kID0gYXdhaXQgdGhpcy5maWxlQmFja2VuZEZvck5hbWUobmFtZSlcblxuICAgIGlmIChmaWxlQmFja2VuZCkge1xuICAgICAgY29uc3QgYWNxdWlyZWQgPSBhd2FpdCBmaWxlQmFja2VuZC5hY3F1aXJlKG5hbWUsIHt0aW1lb3V0TXM6IDB9KVxuXG4gICAgICBpZiAoIWFjcXVpcmVkKSByZXR1cm4ge2FjcXVpcmVkOiBmYWxzZSwgcmVhc29uOiBcImNvbnRlbmRlZFwiLCBsb2NrTmFtZTogbmFtZX1cblxuICAgICAgY29uc3QgbG9ja0JhY2tlbmQgPSB0aGlzLmZpbGVQcm92ZW5hbmNlKGZpbGVCYWNrZW5kLCBuYW1lKVxuXG4gICAgICB0aGlzLmNvbmZpZ3VyYXRpb24ucmVjb3JkQWR2aXNvcnlMb2NrQWNxdWlzaXRpb24oe2JhY2tlbmQ6IGxvY2tCYWNrZW5kLmJhY2tlbmQsIGZlbmNpbmdTdXBwb3J0ZWQ6IGxvY2tCYWNrZW5kLmZlbmNpbmdTdXBwb3J0ZWQsIGxvY2tOYW1lOiBuYW1lfSlcblxuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ydW5Mb2NrZWRDYWxsYmFjayh7Y2FsbGJhY2ssIGhvbGRUaW1lb3V0TXM6IGFyZ3MuaG9sZFRpbWVvdXRNcywgbG9ja0JhY2tlbmQsIG5hbWUsIHJlbGVhc2U6IGFzeW5jICgpID0+IGF3YWl0IGZpbGVCYWNrZW5kLnJlbGVhc2UobmFtZSl9KVxuXG4gICAgICByZXR1cm4ge2FjcXVpcmVkOiB0cnVlLCByZXN1bHR9XG4gICAgfVxuXG4gICAgcmV0dXJuIGF3YWl0IHRoaXMud2l0aExvY2tDb25uZWN0aW9uKGFyZ3MsIGFzeW5jIChjb25uZWN0aW9uKSA9PiB7XG4gICAgICBjb25zdCBhY3F1aXJlZCA9IGF3YWl0IGNvbm5lY3Rpb24udHJ5QWNxdWlyZUFkdmlzb3J5TG9jayhuYW1lKVxuXG4gICAgICBpZiAoIWFjcXVpcmVkKSByZXR1cm4ge2FjcXVpcmVkOiBmYWxzZSwgcmVhc29uOiBcImNvbnRlbmRlZFwiLCBsb2NrTmFtZTogbmFtZX1cblxuICAgICAgY29uc3QgbG9ja0JhY2tlbmQgPSB0aGlzLmRyaXZlclByb3ZlbmFuY2UoY29ubmVjdGlvbilcblxuICAgICAgdGhpcy5hc3NlcnREcml2ZXJUaWVyRWxpZ2libGUobmFtZSwgbG9ja0JhY2tlbmQpXG5cbiAgICAgIHRoaXMuY29uZmlndXJhdGlvbi5yZWNvcmRBZHZpc29yeUxvY2tBY3F1aXNpdGlvbih7YmFja2VuZDogbG9ja0JhY2tlbmQuYmFja2VuZCwgZmVuY2luZ1N1cHBvcnRlZDogbG9ja0JhY2tlbmQuZmVuY2luZ1N1cHBvcnRlZCwgbG9ja05hbWU6IG5hbWV9KVxuXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJ1bkxvY2tlZENhbGxiYWNrKHtjYWxsYmFjaywgaG9sZFRpbWVvdXRNczogYXJncy5ob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCwgbmFtZSwgcmVsZWFzZTogYXN5bmMgKCkgPT4gYXdhaXQgY29ubmVjdGlvbi5yZWxlYXNlQWR2aXNvcnlMb2NrKG5hbWUpfSlcblxuICAgICAgcmV0dXJuIHthY3F1aXJlZDogdHJ1ZSwgcmVzdWx0fVxuICAgIH0pXG4gIH1cblxuICAvKipcbiAgICogUnVucyB0aGUgbG9jayBob2xkZXIgY2FsbGJhY2sgYW5kIHJlbGVhc2VzIHRoZSBsb2NrIGZyb20gaXRzIG93bmluZyBiYWNrZW5kLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAcGFyYW0ge3tjYWxsYmFjazogKGFyZ3M/OiB7Y29udHJvbD86IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2wsIGxvY2tCYWNrZW5kOiBBZHZpc29yeUxvY2tCYWNrZW5kUHJvdmVuYW5jZX0pID0+IFByb21pc2U8VD4sIGhvbGRUaW1lb3V0TXM/OiBudW1iZXIgfCBudWxsLCBsb2NrQmFja2VuZDogQWR2aXNvcnlMb2NrQmFja2VuZFByb3ZlbmFuY2UsIG5hbWU6IHN0cmluZywgcmVsZWFzZTogKCkgPT4gUHJvbWlzZTx1bmtub3duPn19IGFyZ3MgLSBMb2NrZWQgY2FsbGJhY2sgYXJncy5cbiAgICogQHJldHVybnMge1Byb21pc2U8VD59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgY2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgcnVuTG9ja2VkQ2FsbGJhY2soe2NhbGxiYWNrLCBob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCwgbmFtZSwgcmVsZWFzZX0pIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IEFkdmlzb3J5TG9ja1J1bm5lci5ydW5XaXRoQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXQobmFtZSwgY2FsbGJhY2ssIGhvbGRUaW1lb3V0TXMsIGxvY2tCYWNrZW5kKVxuICAgIH0gZmluYWxseSB7XG4gICAgICBhd2FpdCByZWxlYXNlKClcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzb2x2ZXMgdGhlIGJhY2tlbmQgcG9saWN5IGZvciBvbmUgbG9jayBuYW1lIGFuZCByZXR1cm5zIHRoZSBmaWxlXG4gICAqIGJhY2tlbmQgd2hlbiB0aGUgbmFtZSBleHBsaWNpdGx5IG9wdHMgaW50byB0aGUgZmlsZSB0aWVyXG4gICAqIChgcHJlZmVycmVkVGllcjogXCJmaWxlXCJgIHBsdXMgYGFkdmlzb3J5TG9ja3MuYmFja2VuZHMuZmlsZS5lbmFibGVkOiB0cnVlYCkuXG4gICAqIEEgbmFtZSB3aG9zZSBkZWNsYXJlZCBtaW5pbXVtIHRpZXIgaXMgY3Jvc3MtaG9zdCBpcyByZWZ1c2VkIGxvdWRseVxuICAgKiAoYEFkdmlzb3J5TG9ja01pblRpZXJSZWZ1c2VkRXJyb3JgKSBiZWZvcmUgYW55IGNvbnRhY3Qgd2l0aCB0aGUgZmlsZVxuICAgKiB0aWVyLiBBIG5hbWUgdGhhdCBwcmVmZXJzIHRoZSBmaWxlIHRpZXIgd2hpbGUgdGhlIGJhY2tlbmQgaXMgZGlzYWJsZWRcbiAgICogbW92ZXMgdG8gdGhlIGRyaXZlciBwYXRoIChhIHN0cm9uZ2VyLW9yLWVxdWFsIHRpZXIpLCBuZXZlciB0aGUgb3RoZXIgd2F5XG4gICAqIGFyb3VuZC4gTm90aGluZyBoZXJlIGV2ZXIgYXV0by1lbmFibGVzIHRoZSBmaWxlIHRpZXIuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTG9jayBuYW1lLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxpbXBvcnQoXCIuL2Fkdmlzb3J5LWxvY2stZmlsZS1iYWNrZW5kLmpzXCIpLmRlZmF1bHQgfCBudWxsPn0gLSBSZXNvbHZlcyB3aXRoIHRoZSBmaWxlIGJhY2tlbmQgc2VydmluZyB0aGlzIG5hbWUsIG9yIG51bGwgZm9yIHRoZSBkcml2ZXIgcGF0aC5cbiAgICovXG4gIGFzeW5jIGZpbGVCYWNrZW5kRm9yTmFtZShuYW1lKSB7XG4gICAgY29uc3QgcG9saWN5ID0gcmVzb2x2ZUFkdmlzb3J5TG9ja0JhY2tlbmRQb2xpY3kobmFtZSwgdGhpcy5jb25maWd1cmF0aW9uLmdldEFkdmlzb3J5TG9ja1BvbGljeSgpKVxuXG4gICAgaWYgKHBvbGljeS5wcmVmZXJyZWRUaWVyICE9PSBcImZpbGVcIikgcmV0dXJuIG51bGxcblxuICAgIGlmICghYWR2aXNvcnlMb2NrUG9saWN5QWxsb3dzRmlsZVRpZXIocG9saWN5KSkge1xuICAgICAgcmVmdXNlQWR2aXNvcnlMb2NrVGllckJlbG93TWluaW11bSh7XG4gICAgICAgIGNvbmZpZ3VyYXRpb246IHRoaXMuY29uZmlndXJhdGlvbixcbiAgICAgICAgbG9ja05hbWU6IG5hbWUsXG4gICAgICAgIG1pblRpZXI6IHBvbGljeS5taW5UaWVyLFxuICAgICAgICByZXF1ZXN0ZWRCYWNrZW5kOiBcImZpbGVcIlxuICAgICAgfSlcbiAgICB9XG5cbiAgICBjb25zdCBiYWNrZW5kID0gYXdhaXQgdGhpcy5jb25maWd1cmF0aW9uLmdldEFkdmlzb3J5TG9ja0ZpbGVCYWNrZW5kKClcblxuICAgIGlmICghYmFja2VuZCkge1xuICAgICAgLy8gUHJlZmVycmVkIHRpZXIgdW5hdmFpbGFibGU6IGZhaWwgKnVwd2FyZCogdG8gdGhlIGRyaXZlciBwYXRoIChhXG4gICAgICAvLyBzdHJvbmdlci1vci1lcXVhbCB0aWVyKSwgbmV2ZXIgZG93bndhcmQuIElmIHRoZSBkcml2ZXIgY2Fubm90IHNhdGlzZnlcbiAgICAgIC8vIHRoZSBtaW5pbXVtIGVpdGhlciwgYGFzc2VydERyaXZlclRpZXJFbGlnaWJsZWAgdGhyb3dzXG4gICAgICAvLyBgQWR2aXNvcnlMb2NrQmFja2VuZFVuYXZhaWxhYmxlRXJyb3JgIG9uIHRoZSBkcml2ZXIgcGF0aC5cbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgcmV0dXJuIGJhY2tlbmRcbiAgfVxuXG4gIC8qKlxuICAgKiBGYWlsLWNsb3NlZCBjaGVjayBvbiB0aGUgZHJpdmVyIHBhdGggKGRlc2lnbiDCpzkpOiBhbiB1bmRlY2xhcmVkIGxvY2sgbmFtZVxuICAgKiBrZWVwcyB0b2RheSdzIGJlaGF2aW9yIChhbnkgZHJpdmVyIHNlcnZlcyBpdCDigJQgZnVsbCBiYWNrd2FyZFxuICAgKiBjb21wYXRpYmlsaXR5KSwgYnV0IGEgbmFtZSB3aXRoIGFuIGV4cGxpY2l0IHBvbGljeSBlbnRyeSBpcyByZWZ1c2VkIHdpdGhcbiAgICogYEFkdmlzb3J5TG9ja0JhY2tlbmRVbmF2YWlsYWJsZUVycm9yYCB3aGVuIHRoZSBjb25maWd1cmVkIGRyaXZlciBjYW5ub3RcbiAgICogc2F0aXNmeSBpdHMgbWluaW11bSB0aWVyIChlLmcuIGBtaW5UaWVyOiBcImRyaXZlci1uYXRpdmVcImAgb24gYSBTUUxpdGVcbiAgICogZHJpdmVyLCB3aGljaCBoYXMgbm8gbmF0aXZlIGFkdmlzb3J5LWxvY2sgcHJpbWl0aXZlKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBMb2NrIG5hbWUuXG4gICAqIEBwYXJhbSB7QWR2aXNvcnlMb2NrQmFja2VuZFByb3ZlbmFuY2V9IGxvY2tCYWNrZW5kIC0gVGllciB0aGUgZHJpdmVyIHBhdGggd291bGQgc2VydmUgd2l0aC5cbiAgICogQHJldHVybnMge3ZvaWR9XG4gICAqL1xuICBhc3NlcnREcml2ZXJUaWVyRWxpZ2libGUobmFtZSwgbG9ja0JhY2tlbmQpIHtcbiAgICBjb25zdCBwb2xpY3kgPSByZXNvbHZlQWR2aXNvcnlMb2NrQmFja2VuZFBvbGljeShuYW1lLCB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0QWR2aXNvcnlMb2NrUG9saWN5KCkpXG5cbiAgICBpZiAoIXBvbGljeS5lbnRyeSkgcmV0dXJuXG5cbiAgICBjb25zdCB0aWVyID0gbG9ja0JhY2tlbmQuYmFja2VuZFxuXG4gICAgaWYgKHRpZXIgPT09IFwicHJvY2Vzcy1sb2NhbFwiICYmICFwb2xpY3kuYWxsb3dlZFRpZXJzLmluY2x1ZGVzKFwicHJvY2Vzcy1sb2NhbFwiKSkge1xuICAgICAgdGhyb3cgbmV3IEFkdmlzb3J5TG9ja0JhY2tlbmRVbmF2YWlsYWJsZUVycm9yKFxuICAgICAgICBgQWR2aXNvcnkgbG9jayAke0pTT04uc3RyaW5naWZ5KG5hbWUpfSByZXF1aXJlcyBtaW5pbXVtIHRpZXIgJHtKU09OLnN0cmluZ2lmeShwb2xpY3kubWluVGllcil9IGJ1dCB0aGUgY29uZmlndXJlZCBkcml2ZXIgKCR7U3RyaW5nKGxvY2tCYWNrZW5kLmRyaXZlclR5cGUpfSkgb25seSBvZmZlcnMgdGhlIHByb2Nlc3MtbG9jYWwgdGllcmAsXG4gICAgICAgIHtsb2NrTmFtZTogbmFtZSwgbWluVGllcjogcG9saWN5Lm1pblRpZXIsIHJlYXNvbnM6IFtgZHJpdmVyIHRpZXIgJHt0aWVyfSBiZWxvdyBtaW5UaWVyICR7cG9saWN5Lm1pblRpZXJ9YF19XG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJlc29sdmVzIHRoZSB3YWl0IGJvdW5kIGZvciBhIGZpbGUtdGllciBhY3F1aXNpdGlvbjogYW4gZXhwbGljaXQgY2FsbGVyXG4gICAqIGB0aW1lb3V0TXNgIChpbmNsdWRpbmcgYW4gZXhwbGljaXQgYG51bGxgIG9wdC1vdXQpIHdpbnMsIG90aGVyd2lzZSB0aGVcbiAgICogc2FtZSBmcmFtZXdvcmsgZGVmYXVsdCB0aGF0IGJvdW5kcyBkcml2ZXIgYWNxdWlzaXRpb25zIGFwcGxpZXMuXG4gICAqIEBwYXJhbSB7e3RpbWVvdXRNcz86IG51bWJlciB8IG51bGx9fSBhcmdzIC0gTG9jayBvcHRpb25zLlxuICAgKiBAcmV0dXJucyB7bnVtYmVyIHwgbnVsbH0gLSBXYWl0IGJvdW5kIGluIG1pbGxpc2Vjb25kcywgb3IgYG51bGxgIGZvciBhbiBpbmRlZmluaXRlIHdhaXQuXG4gICAqL1xuICBmaWxlQWNxdWlyZVRpbWVvdXRNcyhhcmdzKSB7XG4gICAgaWYgKGFyZ3MudGltZW91dE1zICE9PSB1bmRlZmluZWQpIHJldHVybiBhcmdzLnRpbWVvdXRNc1xuXG4gICAgcmV0dXJuIERFRkFVTFRfQURWSVNPUllfTE9DS19BQ1FVSVJFX1RJTUVPVVRfTVNcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZHMgdGhlIGFjcXVpc2l0aW9uIHByb3ZlbmFuY2UgZm9yIGEgZmlsZS10aWVyIGhvbGQuIFRoZSBmaWxlIHRpZXJcbiAgICogY2Fubm90IGNhcnJ5IGZlbmNpbmcgdG9rZW5zLCBzbyB0aGUgbGltaXRhdGlvbiBpcyByZXBvcnRlZCBvbiBldmVyeVxuICAgKiBhY3F1aXNpdGlvbiByYXRoZXIgdGhhbiBzaWxlbnRseSBwcmV0ZW5kZWQgYXdheSAoZGVzaWduIMKnOCkuXG4gICAqIEBwYXJhbSB7aW1wb3J0KFwiLi9hZHZpc29yeS1sb2NrLWZpbGUtYmFja2VuZC5qc1wiKS5kZWZhdWx0fSBiYWNrZW5kIC0gQmFja2VuZCB0aGF0IHNlcnZlZCB0aGUgYWNxdWlzaXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBuYW1lIC0gTG9jayBuYW1lLlxuICAgKiBAcmV0dXJucyB7QWR2aXNvcnlMb2NrQmFja2VuZFByb3ZlbmFuY2V9IC0gQWNxdWlzaXRpb24gcHJvdmVuYW5jZS5cbiAgICovXG4gIGZpbGVQcm92ZW5hbmNlKGJhY2tlbmQsIG5hbWUpIHtcbiAgICByZXR1cm4ge2JhY2tlbmQ6IFwiZmlsZVwiLCBmZW5jaW5nU3VwcG9ydGVkOiBmYWxzZSwgaG9sZGVySWQ6IGJhY2tlbmQuaG9sZGVySWQsIGxvY2tOYW1lOiBuYW1lfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkcyB0aGUgYWNxdWlzaXRpb24gcHJvdmVuYW5jZSBmb3IgYSBkcml2ZXItc2VydmVkIGhvbGQuIFNRTGl0ZSBoYXMgbm9cbiAgICogbmF0aXZlIGFkdmlzb3J5LWxvY2sgcHJpbWl0aXZlLCBzbyBpdHMgZW11bGF0aW9uIHRpZXIgaXMgcmVwb3J0ZWQgYXNcbiAgICogYHByb2Nlc3MtbG9jYWxgIHJhdGhlciB0aGFuIHByZXRlbmRpbmcgdG8gYmUgZGF0YWJhc2UtbmF0aXZlLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHR9IGNvbm5lY3Rpb24gLSBDb25uZWN0aW9uIHRoYXQgc2VydmVkIHRoZSBhY3F1aXNpdGlvbi5cbiAgICogQHJldHVybnMge0Fkdmlzb3J5TG9ja0JhY2tlbmRQcm92ZW5hbmNlfSAtIEFjcXVpc2l0aW9uIHByb3ZlbmFuY2UuXG4gICAqL1xuICBkcml2ZXJQcm92ZW5hbmNlKGNvbm5lY3Rpb24pIHtcbiAgICBsZXQgZHJpdmVyVHlwZSA9IG51bGxcblxuICAgIHRyeSB7XG4gICAgICBkcml2ZXJUeXBlID0gY29ubmVjdGlvbi5nZXRUeXBlKClcbiAgICB9IGNhdGNoIHtcbiAgICAgIC8vIFRlc3Qgc3R1YiBkcml2ZXJzIG1heSBub3QgaW1wbGVtZW50IGdldFR5cGUoKTsgdGhlIHRpZXIgYWxvbmUgaWRlbnRpZmllcyB0aGUgYmFja2VuZC5cbiAgICB9XG5cbiAgICBjb25zdCB0aWVyID0gdHlwZW9mIGNvbm5lY3Rpb24uYWR2aXNvcnlMb2NrQmFja2VuZFRpZXIgPT09IFwiZnVuY3Rpb25cIlxuICAgICAgPyBjb25uZWN0aW9uLmFkdmlzb3J5TG9ja0JhY2tlbmRUaWVyKClcbiAgICAgIDogKGRyaXZlclR5cGUgPT09IFwic3FsaXRlXCIgPyBcInByb2Nlc3MtbG9jYWxcIiA6IFwiZHJpdmVyLW5hdGl2ZVwiKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGJhY2tlbmQ6IC8qKiBAdHlwZSB7aW1wb3J0KFwiLi9hZHZpc29yeS1sb2NrLWJhY2tlbmQtcG9saWN5LmpzXCIpLkFkdmlzb3J5TG9ja1RpZXJ9ICovICh0aWVyKSxcbiAgICAgIGRyaXZlclR5cGU6IGRyaXZlclR5cGUgPz8gdW5kZWZpbmVkLFxuICAgICAgZmVuY2luZ1N1cHBvcnRlZDogdGllciA9PT0gXCJkcml2ZXItbmF0aXZlXCJcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBsb2NrIHdvcmsgb24gdGhlIGNhbGxlciBjb25uZWN0aW9uIHVubGVzcyBgZGVkaWNhdGVkQ29ubmVjdGlvbmAgaXNcbiAgICogcmVxdWVzdGVkIG9yIGEgcG9zaXRpdmUgaG9sZCB0aW1lb3V0IG5lZWRzIGl0cyBvd24gbG9jayBjb25uZWN0aW9uLlxuICAgKiBAdGVtcGxhdGUgVFxuICAgKiBAcGFyYW0ge3tkZWRpY2F0ZWRDb25uZWN0aW9uPzogYm9vbGVhbiwgaG9sZFRpbWVvdXRNcz86IG51bWJlciB8IG51bGx9fSBhcmdzIC0gTG9jayBjb25uZWN0aW9uIG9wdGlvbnMuXG4gICAqIEBwYXJhbSB7KGNvbm5lY3Rpb246IGltcG9ydChcIi4vZHJpdmVycy9iYXNlLmpzXCIpLmRlZmF1bHQpID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2sgcmVjZWl2aW5nIHRoZSBjb25uZWN0aW9uIHRoYXQgb3ducyB0aGUgYWR2aXNvcnkgbG9jay5cbiAgICogQHJldHVybnMge1Byb21pc2U8VD59IC0gUmVzb2x2ZXMgd2l0aCB0aGUgY2FsbGJhY2sgcmVzdWx0LlxuICAgKi9cbiAgYXN5bmMgd2l0aExvY2tDb25uZWN0aW9uKGFyZ3MsIGNhbGxiYWNrKSB7XG4gICAgY29uc3QgaG9sZFRpbWVvdXRNcyA9IGFyZ3MuaG9sZFRpbWVvdXRNc1xuXG4gICAgaWYgKGFyZ3MuZGVkaWNhdGVkQ29ubmVjdGlvbiB8fCAoaG9sZFRpbWVvdXRNcyAmJiBob2xkVGltZW91dE1zID4gMCkpIHtcbiAgICAgIHJldHVybiBhd2FpdCB0aGlzLndpdGhEZWRpY2F0ZWRDb25uZWN0aW9uKGNhbGxiYWNrKVxuICAgIH1cblxuICAgIHJldHVybiBhd2FpdCBjYWxsYmFjayh0aGlzLmNvbm5lY3Rpb25Qcm92aWRlcigpKVxuICB9XG5cbiAgLyoqXG4gICAqIFNwYXducyBhIGRlZGljYXRlZCBsb2NrIGNvbm5lY3Rpb24gYW5kIGNsb3NlcyBpdCBhZnRlciBsb2NrIHdvcmsgY29tcGxldGVzXG4gICAqIHdoZW4gdGhlIHNwYXduZWQgZHJpdmVyIG93bnMgdGhlIHVuZGVybHlpbmcgcGh5c2ljYWwgY29ubmVjdGlvbi5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHsoY29ubmVjdGlvbjogaW1wb3J0KFwiLi9kcml2ZXJzL2Jhc2UuanNcIikuZGVmYXVsdCkgPT4gUHJvbWlzZTxUPn0gY2FsbGJhY2sgLSBDYWxsYmFjayB0aGF0IHJlY2VpdmVzIHRoZSBkZWRpY2F0ZWQgbG9jayBjb25uZWN0aW9uLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUPn0gLSBSZXNvbHZlcyB3aXRoIHRoZSBjYWxsYmFjayByZXN1bHQuXG4gICAqL1xuICBhc3luYyB3aXRoRGVkaWNhdGVkQ29ubmVjdGlvbihjYWxsYmFjaykge1xuICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBhd2FpdCB0aGlzLmNvbmZpZ3VyYXRpb24uZ2V0RGF0YWJhc2VQb29sKHRoaXMuZGF0YWJhc2VJZGVudGlmaWVyKS5zcGF3bkNvbm5lY3Rpb24oKVxuXG4gICAgLy8gVGhlIHNwYXduZWQgZHJpdmVyIG93bnMgaXRzIHBoeXNpY2FsIGNvbm5lY3Rpb24gdW5sZXNzIGl0IGJvcnJvd3MgYSBzaGFyZWQgb25lXG4gICAgLy8gdmlhIGBnZXRDb25uZWN0aW9uYC4gQW4gb3duZWQgY29ubmVjdGlvbiBsaXZlcyBvdXRzaWRlIHRoZSBwb29scycgdHJhY2tlZCBzZXRzLFxuICAgIC8vIHNvIHJlZ2lzdGVyIGl0IHdoaWxlIHRoZSBsb2NrIGlzIGhlbGQ6IGEgc2h1dGRvd24gdGhlbiBjbG9zZXMgaXQgKHJlbGVhc2luZyB0aGVcbiAgICAvLyBsb2NrKSBpbnN0ZWFkIG9mIG9ycGhhbmluZyBhIGhhbGYtb3BlbiBzZXNzaW9uIHVudGlsIHRoZSBEQiBgd2FpdF90aW1lb3V0YC5cbiAgICBjb25zdCBvd25zQ29ubmVjdGlvbiA9ICFjb25uZWN0aW9uLmdldEFyZ3MoKS5nZXRDb25uZWN0aW9uXG5cbiAgICBpZiAob3duc0Nvbm5lY3Rpb24pIHRoaXMuY29uZmlndXJhdGlvbi5yZWdpc3RlckFkdmlzb3J5TG9ja0Nvbm5lY3Rpb24oY29ubmVjdGlvbilcblxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gYXdhaXQgY2FsbGJhY2soY29ubmVjdGlvbilcbiAgICB9IGZpbmFsbHkge1xuICAgICAgaWYgKG93bnNDb25uZWN0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZmlndXJhdGlvbi51bnJlZ2lzdGVyQWR2aXNvcnlMb2NrQ29ubmVjdGlvbihjb25uZWN0aW9uKVxuICAgICAgICBhd2FpdCBjb25uZWN0aW9uLmNsb3NlKClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGF3YWl0IGNvbm5lY3Rpb24ucmVsZWFzZUhlbGRBZHZpc29yeUxvY2tzKClcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUnVucyBgY2FsbGJhY2tgLCByZWplY3Rpbmcgd2l0aCBgQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXRFcnJvcmAgaWYgaXQgaGFzXG4gICAqIG5vdCBzZXR0bGVkIHdpdGhpbiBgaG9sZFRpbWVvdXRNc2AuIFRoZSBjYWxsYmFjayBpcyBub3QgY2FuY2VsbGVkOyBjYWxsZXJzXG4gICAqIHVzZSBhIGRlZGljYXRlZCBhZHZpc29yeS1sb2NrIGNvbm5lY3Rpb24gc28gdGhlIGxvY2sgY2FuIHN0aWxsIGJlIHJlbGVhc2VkLlxuICAgKlxuICAgKiBUaGUgY2FsbGJhY2sgcmVjZWl2ZXMgYSBgVGltZW91dENvbnRyb2xgIGZyb20gYXdhaXRlcnksIGVuYWJsaW5nIGNvb3BlcmF0aXZlXG4gICAqIGNhbmNlbGxhdGlvbiB2aWEgYGNvbnRyb2wuY2hlY2soKWAsIGBjb250cm9sLnNpZ25hbGAsIGBjb250cm9sLnRpbWVkT3V0YCxcbiAgICogYW5kIGBjb250cm9sLnJlbWFpbmluZygpYCwgcGx1cyBgbG9ja0JhY2tlbmRgIHByb3ZlbmFuY2UgZm9yIHRoZSB0aWVyIHRoYXRcbiAgICogc2VydmVkIHRoZSBhY3F1aXNpdGlvbi5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgLSBMb2NrIG5hbWUgKGZvciB0aGUgZXJyb3IgbWVzc2FnZSkuXG4gICAqIEBwYXJhbSB7KGFyZ3M/OiB7Y29udHJvbD86IGltcG9ydChcImF3YWl0ZXJ5L2J1aWxkL3RpbWVvdXQuanNcIikuVGltZW91dENvbnRyb2wsIGxvY2tCYWNrZW5kOiBBZHZpc29yeUxvY2tCYWNrZW5kUHJvdmVuYW5jZX0pID0+IFByb21pc2U8VD59IGNhbGxiYWNrIC0gQ2FsbGJhY2sgaG9sZGluZyB0aGUgbG9jay5cbiAgICogQHBhcmFtIHtudW1iZXIgfCBudWxsfSBbaG9sZFRpbWVvdXRNc10gLSBNYXggaG9sZCB0aW1lOyBmYWxzeSBkaXNhYmxlcyB0aGUgdGltZW91dC5cbiAgICogQHBhcmFtIHtBZHZpc29yeUxvY2tCYWNrZW5kUHJvdmVuYW5jZX0gW2xvY2tCYWNrZW5kXSAtIFByb3ZlbmFuY2Ugb2YgdGhlIGFjcXVpc2l0aW9uIHNlcnZpbmcgdGhpcyBob2xkLlxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUPn0gLSBSZXNvbHZlcyB3aXRoIHRoZSBjYWxsYmFjayByZXN1bHQuXG4gICAqL1xuICBzdGF0aWMgYXN5bmMgcnVuV2l0aEFkdmlzb3J5TG9ja0hvbGRUaW1lb3V0KG5hbWUsIGNhbGxiYWNrLCBob2xkVGltZW91dE1zLCBsb2NrQmFja2VuZCkge1xuICAgIGlmICghaG9sZFRpbWVvdXRNcyB8fCBob2xkVGltZW91dE1zIDw9IDApIHtcbiAgICAgIHJldHVybiBhd2FpdCBjYWxsYmFjayh7bG9ja0JhY2tlbmQ6IGxvY2tCYWNrZW5kID8/IEFkdmlzb3J5TG9ja1J1bm5lci51bmtub3duQmFja2VuZFByb3ZlbmFuY2UoKX0pXG4gICAgfVxuXG4gICAgbGV0IGNhbGxiYWNrU2V0dGxlZCA9IGZhbHNlXG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IHRpbWVvdXQoe3RpbWVvdXQ6IGhvbGRUaW1lb3V0TXN9LCBhc3luYyAoe2NvbnRyb2x9KSA9PiB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgcmV0dXJuIGF3YWl0IGNhbGxiYWNrKHtjb250cm9sLCBsb2NrQmFja2VuZDogbG9ja0JhY2tlbmQgPz8gQWR2aXNvcnlMb2NrUnVubmVyLnVua25vd25CYWNrZW5kUHJvdmVuYW5jZSgpfSlcbiAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICBjYWxsYmFja1NldHRsZWQgPSB0cnVlXG4gICAgICAgIH1cbiAgICAgIH0pXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGlmICghY2FsbGJhY2tTZXR0bGVkIHx8IGVycm9yIGluc3RhbmNlb2YgVGltZW91dEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBBZHZpc29yeUxvY2tIb2xkVGltZW91dEVycm9yKGBBZHZpc29yeSBsb2NrICR7SlNPTi5zdHJpbmdpZnkobmFtZSl9IGhlbGQgbG9uZ2VyIHRoYW4gJHtob2xkVGltZW91dE1zfW1zYCwge25hbWV9KVxuICAgICAgfVxuXG4gICAgICB0aHJvdyBlcnJvclxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBOZXV0cmFsIHByb3ZlbmFuY2UgZm9yIGRpcmVjdCBgcnVuV2l0aEFkdmlzb3J5TG9ja0hvbGRUaW1lb3V0YCBjYWxsZXJzIHRoYXRcbiAgICogaG9sZCBhIGxvY2sgYWNxdWlyZWQgb3V0c2lkZSB0aGlzIHJ1bm5lci5cbiAgICogQHJldHVybnMge0Fkdmlzb3J5TG9ja0JhY2tlbmRQcm92ZW5hbmNlfSAtIFByb3ZlbmFuY2Ugd2l0aCBhbiB1bmtub3duIHRpZXIuXG4gICAqL1xuICBzdGF0aWMgdW5rbm93bkJhY2tlbmRQcm92ZW5hbmNlKCkge1xuICAgIHJldHVybiB7YmFja2VuZDogXCJwcm9jZXNzLWxvY2FsXCIsIGZlbmNpbmdTdXBwb3J0ZWQ6IGZhbHNlfVxuICB9XG59XG5cbi8qKlxuICogUnVucyBhZHZpc29yeSBsb2NrIHBvbGljeSBhbGxvd3MgZmlsZSB0aWVyLlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL2Fkdmlzb3J5LWxvY2stYmFja2VuZC1wb2xpY3kuanNcIikuUmVzb2x2ZWRBZHZpc29yeUxvY2tCYWNrZW5kUG9saWN5fSBwb2xpY3kgLSBSZXNvbHZlZCBwb2xpY3kuXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gLSBXaGV0aGVyIHRoZSBmaWxlIHRpZXIgbWF5IHNlcnZlIHRoaXMgbmFtZS5cbiAqL1xuZnVuY3Rpb24gYWR2aXNvcnlMb2NrUG9saWN5QWxsb3dzRmlsZVRpZXIocG9saWN5KSB7XG4gIHJldHVybiBwb2xpY3kuYWxsb3dlZFRpZXJzLmluY2x1ZGVzKFwiZmlsZVwiKVxufVxuXG5leHBvcnQge0Fkdmlzb3J5TG9ja0J1c3lFcnJvciwgQWR2aXNvcnlMb2NrSG9sZFRpbWVvdXRFcnJvciwgQWR2aXNvcnlMb2NrVGltZW91dEVycm9yfVxuZXhwb3J0IHtBZHZpc29yeUxvY2tCYWNrZW5kVW5hdmFpbGFibGVFcnJvciwgQWR2aXNvcnlMb2NrTWluVGllclJlZnVzZWRFcnJvcn0gZnJvbSBcIi4vYWR2aXNvcnktbG9jay1iYWNrZW5kLXBvbGljeS5qc1wiXG4iXX0=
|
|
@@ -367,6 +367,30 @@ export default class VelociousDatabaseDriversBase {
|
|
|
367
367
|
_transactionsActionsMutex: Mutex;
|
|
368
368
|
_physicalConnectionMutex: Mutex;
|
|
369
369
|
_connectionCheckedOutAtUnixMs: number | undefined;
|
|
370
|
+
/**
|
|
371
|
+
* Process-wide state for the **process-local advisory-lock pre-filter
|
|
372
|
+
* tier** shared by every driver (SQLite, MySQL/MariaDB, PostgreSQL,
|
|
373
|
+
* MSSQL). It serializes concurrent acquisitions of the same lock name
|
|
374
|
+
* inside this process through a FIFO waiter queue before any caller
|
|
375
|
+
* contacts the driver-native tier, so a contended same-process waiter
|
|
376
|
+
* never parks a pooled database connection in a driver lock state
|
|
377
|
+
* (MariaDB `User lock`, `sp_getapplock` session hold, ...).
|
|
378
|
+
*
|
|
379
|
+
* This tier is a pre-filter, **never the authority**: a grant here only
|
|
380
|
+
* means "you are next in this process." Cross-process/cross-host
|
|
381
|
+
* exclusion is confirmed by the driver-native tier (or, once the
|
|
382
|
+
* STC-210 backend chain lands, the configured cross-host backend)
|
|
383
|
+
* before the acquisition succeeds.
|
|
384
|
+
*
|
|
385
|
+
* `ownersByName` maps each held lock name to the driver instance that
|
|
386
|
+
* acquired it so `releaseAdvisoryLock` can reject releases from drivers
|
|
387
|
+
* that do not own the lock.
|
|
388
|
+
* @type {{ownersByName: Map<string, VelociousDatabaseDriversBase>, waitersByName: Map<string, Array<() => void>>}}
|
|
389
|
+
*/
|
|
390
|
+
static _advisoryLockState: {
|
|
391
|
+
ownersByName: Map<string, VelociousDatabaseDriversBase>;
|
|
392
|
+
waitersByName: Map<string, Array<() => void>>;
|
|
393
|
+
};
|
|
370
394
|
/**
|
|
371
395
|
* Id seq.
|
|
372
396
|
* @type {number | undefined} */
|
|
@@ -1490,9 +1514,26 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1490
1514
|
* Advisory locks are connection-scoped and do not interact with row or
|
|
1491
1515
|
* table locks; they are purely cooperative between callers that use the
|
|
1492
1516
|
* same name and let you serialize functionality without blocking readers
|
|
1493
|
-
* or writers that do not participate in the same lock.
|
|
1517
|
+
* or writers that do not participate in the same named lock.
|
|
1518
|
+
*
|
|
1519
|
+
* Acquisition runs as a two-tier chain:
|
|
1520
|
+
* 1. The **process-local pre-filter tier** (this class' FIFO waiter
|
|
1521
|
+
* queue) serializes same-process callers for the lock name without
|
|
1522
|
+
* issuing any driver-native lock query and without parking a
|
|
1523
|
+
* connection in a driver lock state. A queued caller never reaches
|
|
1524
|
+
* tier 2 until the in-process holder releases.
|
|
1525
|
+
* 2. The **driver-native tier** (`_acquireAdvisoryLock`: MariaDB
|
|
1526
|
+
* `GET_LOCK`, PostgreSQL `pg_advisory_lock`, SQL Server
|
|
1527
|
+
* `sp_getapplock`, SQLite filesystem lock on Node) confirms the
|
|
1528
|
+
* cross-process/cross-host exclusion.
|
|
1529
|
+
*
|
|
1530
|
+
* The process-local tier is a pre-filter, **never the authority**: a
|
|
1531
|
+
* lock name that other processes or hosts can request is only granted
|
|
1532
|
+
* after the driver-native tier (or, once the STC-210 backend chain
|
|
1533
|
+
* lands, the configured cross-host backend) confirms it. If the native
|
|
1534
|
+
* tier denies or times out, the in-process hold is rolled back.
|
|
1494
1535
|
* @param {string} name - Lock name.
|
|
1495
|
-
* @param {{timeoutMs?: number | null}} [args] - Optional timeout in milliseconds; `null` blocks forever, and an omitted value uses the database's `advisoryLockAcquireTimeoutMs` or the framework default.
|
|
1536
|
+
* @param {{timeoutMs?: number | null}} [args] - Optional timeout in milliseconds; `null` blocks forever, and an omitted value uses the database's `advisoryLockAcquireTimeoutMs` or the framework default. The bound covers the whole two-tier acquisition.
|
|
1496
1537
|
* @returns {Promise<boolean>} - Resolves to true when the lock has been acquired, false if the timeout elapsed.
|
|
1497
1538
|
*/
|
|
1498
1539
|
acquireAdvisoryLock(name: string, args?: {
|
|
@@ -1510,8 +1551,67 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1510
1551
|
advisoryLockAcquireTimeoutMs(args?: {
|
|
1511
1552
|
timeoutMs?: number | null;
|
|
1512
1553
|
}): number | null;
|
|
1554
|
+
/**
|
|
1555
|
+
* Whether this driver has a driver-native advisory-lock tier behind the
|
|
1556
|
+
* process-local pre-filter. MariaDB (`GET_LOCK`), PostgreSQL
|
|
1557
|
+
* (`pg_advisory_lock`) and SQL Server (`sp_getapplock`) do; SQLite has
|
|
1558
|
+
* no native primitive (the Node SQLite driver substitutes its
|
|
1559
|
+
* filesystem lock directory, the web/native builds have nothing), so
|
|
1560
|
+
* for plain SQLite the process-local tier IS the whole implementation
|
|
1561
|
+
* and callers must not read it as a cross-process guarantee.
|
|
1562
|
+
* @returns {boolean} - Whether the driver-native tier exists.
|
|
1563
|
+
*/
|
|
1564
|
+
supportsDriverNativeAdvisoryLock(): boolean;
|
|
1565
|
+
/**
|
|
1566
|
+
* Whether the driver's native tier is re-entrant within the same
|
|
1567
|
+
* session. `GET_LOCK`, `pg_advisory_lock` and `sp_getapplock` grant the
|
|
1568
|
+
* same session repeatedly, so the process-local tier must let a
|
|
1569
|
+
* re-acquisition by its own owner pass through to the native tier.
|
|
1570
|
+
* SQLite's emulation (including the Node filesystem lock) is not
|
|
1571
|
+
* re-entrant, so the tier keeps treating a re-acquisition as contention
|
|
1572
|
+
* exactly as the SQLite emulation always has.
|
|
1573
|
+
* @returns {boolean} - Whether same-instance re-acquisition is honored.
|
|
1574
|
+
*/
|
|
1575
|
+
supportsReentrantAdvisoryLock(): boolean;
|
|
1576
|
+
/**
|
|
1577
|
+
* Process-local pre-filter tier: FIFO waiter queue for one lock name
|
|
1578
|
+
* inside this process. This is the promoted SQLite emulation from
|
|
1579
|
+
* STC-211 — it now runs in front of **every** driver's native tier so a
|
|
1580
|
+
* same-process waiter never issues a driver-native lock query and never
|
|
1581
|
+
* parks a pooled connection in a driver lock state while queued.
|
|
1582
|
+
*
|
|
1583
|
+
* A grant here means only "you are the next caller in this process."
|
|
1584
|
+
* It is never the authority for cross-process/cross-host exclusion; the
|
|
1585
|
+
* caller must still pass the driver-native tier before the lock counts
|
|
1586
|
+
* as held. A re-entrant acquisition by the owning driver instance is
|
|
1587
|
+
* granted immediately, mirroring the session-scoped re-entrancy of
|
|
1588
|
+
* `GET_LOCK` / `pg_advisory_lock` / `sp_getapplock`.
|
|
1589
|
+
* @param {string} name - Lock name.
|
|
1590
|
+
* @param {{timeoutMs?: number | null}} [args] - Optional timeout in milliseconds; `null`, `undefined`, or negative blocks forever.
|
|
1591
|
+
* @returns {Promise<{acquired: boolean, waited: boolean}>} - Whether the tier granted this caller, and whether it had to queue for it.
|
|
1592
|
+
*/
|
|
1593
|
+
_acquireProcessLocalAdvisoryLock(name: string, { timeoutMs }?: {
|
|
1594
|
+
timeoutMs?: number | null;
|
|
1595
|
+
}): Promise<{
|
|
1596
|
+
acquired: boolean;
|
|
1597
|
+
waited: boolean;
|
|
1598
|
+
}>;
|
|
1599
|
+
/**
|
|
1600
|
+
* Hands the process-local tier for one lock name to the next FIFO waiter,
|
|
1601
|
+
* but only when **this** driver instance currently owns it. A release by
|
|
1602
|
+
* a non-owner is a no-op, matching the "you can only release locks you
|
|
1603
|
+
* own" contract of `RELEASE_LOCK` / `pg_advisory_unlock`.
|
|
1604
|
+
* @param {string} name - Lock name.
|
|
1605
|
+
* @returns {boolean} - Whether this instance owned the tier and released it.
|
|
1606
|
+
*/
|
|
1607
|
+
_releaseProcessLocalAdvisoryLock(name: string): boolean;
|
|
1513
1608
|
/**
|
|
1514
1609
|
* Driver-specific blocking advisory-lock acquisition hook.
|
|
1610
|
+
* This is the **driver-native tier** of the acquisition chain: MariaDB
|
|
1611
|
+
* `GET_LOCK`, PostgreSQL `pg_advisory_lock`, SQL Server `sp_getapplock`,
|
|
1612
|
+
* the Node SQLite filesystem lock. It runs only after the process-local
|
|
1613
|
+
* pre-filter tier has granted this caller its turn, and its result is
|
|
1614
|
+
* what actually confirms cross-process/cross-host exclusion.
|
|
1515
1615
|
* @abstract
|
|
1516
1616
|
* @param {string} name - Lock name.
|
|
1517
1617
|
* @param {{timeoutMs?: number | null}} [_args] - Lock timeout options.
|
|
@@ -1522,6 +1622,12 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1522
1622
|
}): Promise<boolean>;
|
|
1523
1623
|
/**
|
|
1524
1624
|
* Attempts to acquire a named advisory lock without blocking.
|
|
1625
|
+
*
|
|
1626
|
+
* Same two-tier chain as `acquireAdvisoryLock`: the process-local tier
|
|
1627
|
+
* short-circuits contention between callers in this process (a queued
|
|
1628
|
+
* name never reaches the driver-native hook), and the driver-native tier
|
|
1629
|
+
* confirms cross-process/cross-host exclusion. A free in-process tier is
|
|
1630
|
+
* NOT a grant — the native tier still has to agree.
|
|
1525
1631
|
* @param {string} name - Lock name.
|
|
1526
1632
|
* @returns {Promise<boolean>} - Resolves to true if the lock was acquired, false if it was already held.
|
|
1527
1633
|
*/
|
|
@@ -1535,6 +1641,10 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1535
1641
|
_tryAcquireAdvisoryLock(name: string): Promise<boolean>;
|
|
1536
1642
|
/**
|
|
1537
1643
|
* Releases a named advisory lock previously acquired on this connection.
|
|
1644
|
+
* The driver-native release runs first; the process-local tier is handed
|
|
1645
|
+
* to the next waiter only once this connection's counted registry no
|
|
1646
|
+
* longer holds the name, so re-entrant acquisitions release one level at
|
|
1647
|
+
* a time exactly like the session-scoped driver locks.
|
|
1538
1648
|
* @param {string} name - Lock name.
|
|
1539
1649
|
* @returns {Promise<boolean>} - Resolves to true if the lock was held by this session and has now been released.
|
|
1540
1650
|
*/
|
|
@@ -1567,11 +1677,22 @@ export default class VelociousDatabaseDriversBase {
|
|
|
1567
1677
|
* Checks whether a named advisory lock is currently held by any session.
|
|
1568
1678
|
* Intended as an introspection helper; callers who need to act on the
|
|
1569
1679
|
* result should prefer `tryAcquireAdvisoryLock` to avoid a TOCTOU race.
|
|
1570
|
-
*
|
|
1680
|
+
*
|
|
1681
|
+
* The process-local tier answers first (a same-process holder is a
|
|
1682
|
+
* holder, full stop); otherwise the question goes to the driver-native
|
|
1683
|
+
* tier's introspection (`IS_USED_LOCK` / `pg_locks` / `APPLOCK_TEST`).
|
|
1571
1684
|
* @param {string} name - Lock name.
|
|
1572
|
-
* @returns {Promise<boolean>} - Resolves to true if the lock is held by
|
|
1685
|
+
* @returns {Promise<boolean>} - Resolves to true if the lock is held by any session.
|
|
1573
1686
|
*/
|
|
1574
1687
|
isAdvisoryLockHeld(name: string): Promise<boolean>;
|
|
1688
|
+
/**
|
|
1689
|
+
* Driver-native advisory-lock introspection hook behind
|
|
1690
|
+
* `isAdvisoryLockHeld`.
|
|
1691
|
+
* @abstract
|
|
1692
|
+
* @param {string} name - Lock name.
|
|
1693
|
+
* @returns {Promise<boolean>} - Resolves to true if the native tier reports the lock held.
|
|
1694
|
+
*/
|
|
1695
|
+
_isAdvisoryLockHeldNative(name: string): Promise<boolean>;
|
|
1575
1696
|
/**
|
|
1576
1697
|
* Which advisory-lock backend tier this connection serves (STC-210 chain
|
|
1577
1698
|
* naming). The base driver is the driver-native tier; the SQLite drivers
|