velocious 1.0.556 → 1.0.557

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.
@@ -1,6 +1,7 @@
1
1
  // @ts-check
2
2
 
3
3
  import runJobPayload from "./job-runner.js"
4
+ import { closeRunnerConnections, currentConfigurationOrNull } from "./runner-graceful-shutdown.js"
4
5
  import setRunnerProcessTitle from "./runner-process-title.js"
5
6
 
6
7
  // Name the process so `ps`/`top`/`htop` can identify forked job runners at a
@@ -10,6 +11,23 @@ import setRunnerProcessTitle from "./runner-process-title.js"
10
11
  setRunnerProcessTitle()
11
12
 
12
13
  let finishing = false
14
+ let shuttingDown = false
15
+
16
+ /**
17
+ * Closes the runner's connections — releasing any advisory lock a killed-mid-job
18
+ * job still holds — before exiting on shutdown, instead of leaving a half-open
19
+ * session that keeps the lock until the DB server's `wait_timeout`. Normal
20
+ * completion (`finish`) already released its locks via the job's own lock scope.
21
+ * @param {number} exitCode - Process exit code.
22
+ * @returns {Promise<void>}
23
+ */
24
+ async function shutdownRunner(exitCode) {
25
+ if (shuttingDown || finishing) return
26
+ shuttingDown = true
27
+
28
+ await closeRunnerConnections(currentConfigurationOrNull())
29
+ process.exit(exitCode)
30
+ }
13
31
 
14
32
  /**
15
33
  * Runs is job message.
@@ -82,11 +100,11 @@ async function handleJobMessage(message) {
82
100
  }
83
101
 
84
102
  for (const signal of ["SIGTERM", "SIGINT"]) {
85
- process.once(signal, () => process.exit(1))
103
+ process.once(signal, () => void shutdownRunner(1))
86
104
  }
87
105
 
88
106
  process.once("disconnect", () => {
89
- if (!finishing) process.exit(0)
107
+ if (!finishing) void shutdownRunner(0)
90
108
  })
91
109
 
92
110
  process.once("message", (message) => {
@@ -1,12 +1,30 @@
1
1
  // @ts-check
2
2
 
3
3
  import runJobPayload, { BackgroundJobPerformedFailure } from "./job-runner.js"
4
+ import { closeRunnerConnections, currentConfigurationOrNull } from "./runner-graceful-shutdown.js"
4
5
  import setRunnerProcessTitle from "./runner-process-title.js"
5
6
 
6
7
  const BASE_PROCESS_TITLE = "velocious background-jobs-runner"
7
8
 
8
9
  setRunnerProcessTitle()
9
10
 
11
+ let shuttingDown = false
12
+
13
+ /**
14
+ * Closes the runner's connections — releasing any advisory lock a killed-mid-pass
15
+ * job still holds — before exiting, instead of leaving a half-open session that
16
+ * keeps the lock until the DB server's `wait_timeout`.
17
+ * @param {number} exitCode - Process exit code.
18
+ * @returns {Promise<void>}
19
+ */
20
+ async function shutdownRunner(exitCode) {
21
+ if (shuttingDown) return
22
+ shuttingDown = true
23
+
24
+ await closeRunnerConnections(currentConfigurationOrNull())
25
+ process.exit(exitCode)
26
+ }
27
+
10
28
  /**
11
29
  * Ids of jobs currently running in this child. A pooled child runs up to
12
30
  * `pooledRunnerConcurrency` jobs at once (the worker only dispatches within that
@@ -111,5 +129,5 @@ function handleMessage(message) {
111
129
  }
112
130
 
113
131
  process.on("message", (message) => handleMessage(message))
114
- process.once("disconnect", () => process.exit(0))
115
- for (const signal of ["SIGTERM", "SIGINT"]) process.once(signal, () => process.exit(1))
132
+ process.once("disconnect", () => void shutdownRunner(0))
133
+ for (const signal of ["SIGTERM", "SIGINT"]) process.once(signal, () => void shutdownRunner(1))
@@ -0,0 +1,73 @@
1
+ // @ts-check
2
+
3
+ import timeout from "awaitery/build/timeout.js"
4
+
5
+ import Configuration, {CurrentConfigurationNotSetError} from "../configuration.js"
6
+
7
+ /** Bounded grace for closing framework connections on shutdown before forcing exit. */
8
+ const SHUTDOWN_CLOSE_TIMEOUT_MS = 5000
9
+
10
+ /**
11
+ * The subset of a configuration a runner closes on shutdown. Typed structurally so
12
+ * the shutdown path stays typechecked without a broad cast, and a future signature
13
+ * drift surfaces at the call sites (and in tests) instead of hiding behind `any`.
14
+ * @typedef {{disconnectBeacon: () => Promise<void>, closeDatabaseConnections: () => Promise<void>}} RunnerCloseableConfiguration
15
+ */
16
+
17
+ /**
18
+ * Gracefully closes a background-job runner's framework connections (beacon +
19
+ * database) on shutdown, so the database server ends the session and releases any
20
+ * advisory lock the runner still holds *immediately* — instead of leaving a
21
+ * half-open session that keeps the lock (e.g. the build-planner lock) held until
22
+ * the server's idle `wait_timeout` (hours).
23
+ *
24
+ * A runner child otherwise exits abruptly on shutdown (`process.exit`) and relies
25
+ * on the OS tearing down its sockets. A named lock releases only when its owning
26
+ * session ends, and an abrupt exit / container teardown does not reliably deliver a
27
+ * clean disconnect to the server — so the lock leaks. Sending a real close here
28
+ * (`COM_QUIT` via `closeDatabaseConnections`) makes the server end the session and
29
+ * release the lock deterministically.
30
+ *
31
+ * The beacon disconnect and the database close run independently, each bounded by
32
+ * `closeTimeoutMs`: the database close releases the locks and must still run even if
33
+ * the beacon disconnect hangs (a wedged beacon socket during teardown), and neither
34
+ * may block the exit forever. A failed or timed-out close is thrown, not swallowed —
35
+ * the caller surfaces it (a lock that failed to release must be visible).
36
+ * @param {RunnerCloseableConfiguration | null} configuration - Configuration whose connections to close; null when none is set (nothing to close).
37
+ * @param {number} [closeTimeoutMs] - Max time to spend on each close before giving up.
38
+ * @returns {Promise<void>} - Resolves once both closes have settled; rejects if either failed.
39
+ */
40
+ export async function closeRunnerConnections(configuration, closeTimeoutMs = SHUTDOWN_CLOSE_TIMEOUT_MS) {
41
+ if (!configuration) return
42
+
43
+ const [beaconResult, databaseResult] = await Promise.allSettled([
44
+ timeout({timeout: closeTimeoutMs}, () => configuration.disconnectBeacon()),
45
+ timeout({timeout: closeTimeoutMs}, () => configuration.closeDatabaseConnections())
46
+ ])
47
+
48
+ /** @type {unknown[]} */
49
+ const errors = []
50
+
51
+ if (beaconResult.status == "rejected") errors.push(beaconResult.reason)
52
+ if (databaseResult.status == "rejected") errors.push(databaseResult.reason)
53
+
54
+ if (errors.length == 1) throw errors[0]
55
+ if (errors.length > 1) throw new AggregateError(errors, "Failed to close background-job runner connections on shutdown")
56
+ }
57
+
58
+ /**
59
+ * The current configuration, or null when none has been set yet — a runner that is
60
+ * signalled before it runs any job holds no connections (and no locks) to close.
61
+ * Only that expected "not set yet" case is treated as null; any other error is a real
62
+ * fault and is rethrown rather than masked.
63
+ * @returns {Configuration | null} - The current configuration, or null when none is set.
64
+ */
65
+ export function currentConfigurationOrNull() {
66
+ try {
67
+ return Configuration.current()
68
+ } catch (error) {
69
+ if (error instanceof CurrentConfigurationNotSetError) return null
70
+
71
+ throw error
72
+ }
73
+ }
@@ -119,6 +119,15 @@ export default class VelociousConfiguration {
119
119
  * Close database connections promise.
120
120
  * @type {Promise<void> | null} */
121
121
  _closeDatabaseConnectionsPromise = null
122
+
123
+ /**
124
+ * Dedicated advisory-lock connections currently holding a lock. These are spawned
125
+ * outside the pools' tracked sets (so a hold-timeout lock survives pool checkouts),
126
+ * so `closeDatabaseConnections` would otherwise walk past them; tracking them here
127
+ * lets a shutdown close them and release the lock instead of orphaning it.
128
+ * @type {Set<import("./database/drivers/base.js").default>} */
129
+ _advisoryLockConnections = new Set()
130
+
122
131
  /**
123
132
  * Runs current.
124
133
  * @returns {VelociousConfiguration} - The current.
@@ -2986,6 +2995,53 @@ export default class VelociousConfiguration {
2986
2995
  })
2987
2996
  }
2988
2997
 
2998
+ /**
2999
+ * Registers a dedicated connection that currently holds an advisory lock, so a
3000
+ * shutdown can close it and release the lock. See `_advisoryLockConnections`.
3001
+ * @param {import("./database/drivers/base.js").default} connection - The dedicated lock connection.
3002
+ * @returns {void}
3003
+ */
3004
+ registerAdvisoryLockConnection(connection) {
3005
+ this._advisoryLockConnections.add(connection)
3006
+ }
3007
+
3008
+ /**
3009
+ * Unregisters a dedicated advisory-lock connection once its lock scope ends and the
3010
+ * connection has been (or is about to be) closed by its owner.
3011
+ * @param {import("./database/drivers/base.js").default} connection - The dedicated lock connection.
3012
+ * @returns {void}
3013
+ */
3014
+ unregisterAdvisoryLockConnection(connection) {
3015
+ this._advisoryLockConnections.delete(connection)
3016
+ }
3017
+
3018
+ /**
3019
+ * Closes every registered dedicated advisory-lock connection, ending its session so
3020
+ * the DB server releases the lock. Every connection is attempted before any failure
3021
+ * is surfaced, so one stuck close does not leave the others' locks held; a failure is
3022
+ * then thrown (never swallowed), aggregated when more than one connection failed.
3023
+ * @returns {Promise<void>} - Resolves once all have been closed; rejects if any failed.
3024
+ */
3025
+ async _closeAdvisoryLockConnections() {
3026
+ const connections = [...this._advisoryLockConnections]
3027
+
3028
+ this._advisoryLockConnections.clear()
3029
+
3030
+ /** @type {unknown[]} */
3031
+ const errors = []
3032
+
3033
+ for (const connection of connections) {
3034
+ try {
3035
+ await connection.close()
3036
+ } catch (error) {
3037
+ errors.push(error)
3038
+ }
3039
+ }
3040
+
3041
+ if (errors.length == 1) throw errors[0]
3042
+ if (errors.length > 1) throw new AggregateError(errors, "Failed to close dedicated advisory-lock connections")
3043
+ }
3044
+
2989
3045
  /**
2990
3046
  * Closes active database connections and clears global connections.
2991
3047
  * @returns {Promise<void>} - Resolves when complete.
@@ -3000,21 +3056,30 @@ export default class VelociousConfiguration {
3000
3056
  const constructors = new Set()
3001
3057
 
3002
3058
  this._closeDatabaseConnectionsPromise = (async () => {
3003
- for (const pool of Object.values(this.databasePools)) {
3004
- if (!pool) continue
3005
-
3006
- await pool.closeAll()
3059
+ try {
3060
+ // Close dedicated advisory-lock connections first: they are spawned outside the
3061
+ // pools' tracked sets, so `pool.closeAll()` would not reach them and a lock held
3062
+ // by a runner torn down mid-pass would leak until the DB server's `wait_timeout`.
3063
+ // Still close the pools even if this throws, so a stuck lock connection does not
3064
+ // leave the rest of the connections open.
3065
+ await this._closeAdvisoryLockConnections()
3066
+ } finally {
3067
+ for (const pool of Object.values(this.databasePools)) {
3068
+ if (!pool) continue
3069
+
3070
+ await pool.closeAll()
3071
+
3072
+ const PoolClass = /** @type {typeof import("./database/pool/base.js").default} */ (pool.constructor)
3073
+ constructors.add(PoolClass)
3074
+ }
3007
3075
 
3008
- const PoolClass = /** @type {typeof import("./database/pool/base.js").default} */ (pool.constructor)
3009
- constructors.add(PoolClass)
3010
- }
3076
+ for (const PoolClass of constructors) {
3077
+ PoolClass.clearGlobalConnections(this)
3078
+ }
3011
3079
 
3012
- for (const PoolClass of constructors) {
3013
- PoolClass.clearGlobalConnections(this)
3080
+ // Allow models to be re-initialized after connections are closed.
3081
+ this._modelsInitialized = false
3014
3082
  }
3015
-
3016
- // Allow models to be re-initialized after connections are closed.
3017
- this._modelsInitialized = false
3018
3083
  })()
3019
3084
 
3020
3085
  try {
@@ -150,13 +150,22 @@ export default class AdvisoryLockRunner {
150
150
  async withDedicatedConnection(callback) {
151
151
  const connection = await this.configuration.getDatabasePool(this.databaseIdentifier).spawnConnection()
152
152
 
153
+ // The spawned driver owns its physical connection unless it borrows a shared one
154
+ // via `getConnection`. An owned connection lives outside the pools' tracked sets,
155
+ // so register it while the lock is held: a shutdown then closes it (releasing the
156
+ // lock) instead of orphaning a half-open session until the DB `wait_timeout`.
157
+ const ownsConnection = !connection.getArgs().getConnection
158
+
159
+ if (ownsConnection) this.configuration.registerAdvisoryLockConnection(connection)
160
+
153
161
  try {
154
162
  return await callback(connection)
155
163
  } finally {
156
- if (connection.getArgs().getConnection) {
157
- await connection.releaseHeldAdvisoryLocks()
158
- } else {
164
+ if (ownsConnection) {
165
+ this.configuration.unregisterAdvisoryLockConnection(connection)
159
166
  await connection.close()
167
+ } else {
168
+ await connection.releaseHeldAdvisoryLocks()
160
169
  }
161
170
  }
162
171
  }
@@ -1,5 +1,6 @@
1
1
  // @ts-check
2
2
  import runJobPayload from "./job-runner.js";
3
+ import { closeRunnerConnections, currentConfigurationOrNull } from "./runner-graceful-shutdown.js";
3
4
  import setRunnerProcessTitle from "./runner-process-title.js";
4
5
  // Name the process so `ps`/`top`/`htop` can identify forked job runners at a
5
6
  // glance instead of a wall of generic "node" entries. Updated to the specific
@@ -7,6 +8,22 @@ import setRunnerProcessTitle from "./runner-process-title.js";
7
8
  // which jobs are running, how many of each, and which are eating resources.
8
9
  setRunnerProcessTitle();
9
10
  let finishing = false;
11
+ let shuttingDown = false;
12
+ /**
13
+ * Closes the runner's connections — releasing any advisory lock a killed-mid-job
14
+ * job still holds — before exiting on shutdown, instead of leaving a half-open
15
+ * session that keeps the lock until the DB server's `wait_timeout`. Normal
16
+ * completion (`finish`) already released its locks via the job's own lock scope.
17
+ * @param {number} exitCode - Process exit code.
18
+ * @returns {Promise<void>}
19
+ */
20
+ async function shutdownRunner(exitCode) {
21
+ if (shuttingDown || finishing)
22
+ return;
23
+ shuttingDown = true;
24
+ await closeRunnerConnections(currentConfigurationOrNull());
25
+ process.exit(exitCode);
26
+ }
10
27
  /**
11
28
  * Runs is job message.
12
29
  * @param {?} message - IPC message.
@@ -71,13 +88,13 @@ async function handleJobMessage(message) {
71
88
  }
72
89
  }
73
90
  for (const signal of ["SIGTERM", "SIGINT"]) {
74
- process.once(signal, () => process.exit(1));
91
+ process.once(signal, () => void shutdownRunner(1));
75
92
  }
76
93
  process.once("disconnect", () => {
77
94
  if (!finishing)
78
- process.exit(0);
95
+ void shutdownRunner(0);
79
96
  });
80
97
  process.once("message", (message) => {
81
98
  void handleJobMessage(message);
82
99
  });
83
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ya2VkLXJ1bm5lci1jaGlsZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvZm9ya2VkLXJ1bm5lci1jaGlsZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0saUJBQWlCLENBQUE7QUFDM0MsT0FBTyxxQkFBcUIsTUFBTSwyQkFBMkIsQ0FBQTtBQUU3RCw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLDhFQUE4RTtBQUM5RSw0RUFBNEU7QUFDNUUscUJBQXFCLEVBQUUsQ0FBQTtBQUV2QixJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUE7QUFFckI7Ozs7R0FJRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQU87SUFDM0IsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRO1FBQUUsT0FBTyxLQUFLLENBQUE7SUFFekQsTUFBTSxhQUFhLEdBQUcsc0NBQXNDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUV0RSxPQUFPLGFBQWEsQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsYUFBYSxFQUFFLFNBQVMsQ0FBQyxDQUFBO0FBQ2hGLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxNQUFNLENBQUMsUUFBUTtJQUN0QixTQUFTLEdBQUcsSUFBSSxDQUFBO0lBQ2hCLE9BQU8sQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO0lBRTNCLElBQUksT0FBTyxDQUFDLFNBQVMsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDNUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFBO0lBQ3RCLENBQUM7SUFFRCxZQUFZLENBQUMsR0FBRyxFQUFFLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFBO0FBQzVDLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxTQUFTLGlCQUFpQjtJQUN4QixJQUFJLE9BQU8sQ0FBQyxJQUFJO1FBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFDLElBQUksRUFBRSxjQUFjLEVBQUMsQ0FBQyxDQUFBO0FBQ3hELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLGFBQWEsQ0FBQyxPQUFPO0lBQ2xDLElBQUksQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUMzQixNQUFNLElBQUksS0FBSyxDQUFDLHVEQUF1RCxDQUFDLENBQUE7SUFDMUUsQ0FBQztJQUVELDJFQUEyRTtJQUMzRSw2RUFBNkU7SUFDN0UsOEVBQThFO0lBQzlFLE1BQU0sYUFBYSxDQUFDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsRUFBQyxnQkFBZ0IsRUFBRSxLQUFLLEVBQUMsQ0FBQyxDQUFBO0FBQ2pFLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsS0FBSyxVQUFVLGdCQUFnQixDQUFDLE9BQU87SUFDckMsSUFBSSxDQUFDO1FBQ0gsTUFBTSxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDNUIsaUJBQWlCLEVBQUUsQ0FBQTtRQUNuQixNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDWCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLGlCQUFpQixFQUFFLENBQUE7UUFDbkIsT0FBTyxDQUFDLEtBQUssQ0FBQyxzQ0FBc0MsRUFBRSxLQUFLLENBQUMsQ0FBQTtRQUM1RCxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDWCxDQUFDO0FBQ0gsQ0FBQztBQUVELEtBQUssTUFBTSxNQUFNLElBQUksQ0FBQyxTQUFTLEVBQUUsUUFBUSxDQUFDLEVBQUUsQ0FBQztJQUMzQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDN0MsQ0FBQztBQUVELE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtJQUM5QixJQUFJLENBQUMsU0FBUztRQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDakMsQ0FBQyxDQUFDLENBQUE7QUFFRixPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFO0lBQ2xDLEtBQUssZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUE7QUFDaEMsQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHJ1bkpvYlBheWxvYWQgZnJvbSBcIi4vam9iLXJ1bm5lci5qc1wiXG5pbXBvcnQgc2V0UnVubmVyUHJvY2Vzc1RpdGxlIGZyb20gXCIuL3J1bm5lci1wcm9jZXNzLXRpdGxlLmpzXCJcblxuLy8gTmFtZSB0aGUgcHJvY2VzcyBzbyBgcHNgL2B0b3BgL2BodG9wYCBjYW4gaWRlbnRpZnkgZm9ya2VkIGpvYiBydW5uZXJzIGF0IGFcbi8vIGdsYW5jZSBpbnN0ZWFkIG9mIGEgd2FsbCBvZiBnZW5lcmljIFwibm9kZVwiIGVudHJpZXMuIFVwZGF0ZWQgdG8gdGhlIHNwZWNpZmljXG4vLyBqb2IgbmFtZSBvbmNlIG9uZSBhcnJpdmVzIChzZWUgcnVuSm9iTWVzc2FnZSksIHNvIG9wZXJhdG9ycyBjYW4gc2VlIGV4YWN0bHlcbi8vIHdoaWNoIGpvYnMgYXJlIHJ1bm5pbmcsIGhvdyBtYW55IG9mIGVhY2gsIGFuZCB3aGljaCBhcmUgZWF0aW5nIHJlc291cmNlcy5cbnNldFJ1bm5lclByb2Nlc3NUaXRsZSgpXG5cbmxldCBmaW5pc2hpbmcgPSBmYWxzZVxuXG4vKipcbiAqIFJ1bnMgaXMgam9iIG1lc3NhZ2UuXG4gKiBAcGFyYW0gez99IG1lc3NhZ2UgLSBJUEMgbWVzc2FnZS5cbiAqIEByZXR1cm5zIHttZXNzYWdlIGlzIHt0eXBlOiBcImpvYlwiLCBwYXlsb2FkOiBpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JQYXlsb2FkfX0gLSBXaGV0aGVyIHRoaXMgaXMgYSBqb2IgbWVzc2FnZS5cbiAqL1xuZnVuY3Rpb24gaXNKb2JNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgaWYgKCFtZXNzYWdlIHx8IHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiKSByZXR1cm4gZmFsc2VcblxuICBjb25zdCBtZXNzYWdlUmVjb3JkID0gLyoqIEB0eXBlIHt7dHlwZT86ID8sIHBheWxvYWQ/OiA/fX0gKi8gKG1lc3NhZ2UpXG5cbiAgcmV0dXJuIG1lc3NhZ2VSZWNvcmQudHlwZSA9PT0gXCJqb2JcIiAmJiBPYmplY3QuaGFzT3duKG1lc3NhZ2VSZWNvcmQsIFwicGF5bG9hZFwiKVxufVxuXG4vKipcbiAqIFJ1bnMgZmluaXNoLlxuICogQHBhcmFtIHtudW1iZXJ9IGV4aXRDb2RlIC0gUHJvY2VzcyBleGl0IGNvZGUuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gZmluaXNoKGV4aXRDb2RlKSB7XG4gIGZpbmlzaGluZyA9IHRydWVcbiAgcHJvY2Vzcy5leGl0Q29kZSA9IGV4aXRDb2RlXG5cbiAgaWYgKHByb2Nlc3MuY29ubmVjdGVkICYmIHByb2Nlc3MuZGlzY29ubmVjdCkge1xuICAgIHByb2Nlc3MuZGlzY29ubmVjdCgpXG4gIH1cblxuICBzZXRJbW1lZGlhdGUoKCkgPT4gcHJvY2Vzcy5leGl0KGV4aXRDb2RlKSlcbn1cblxuLyoqXG4gKiBSdW5zIHJlcG9ydCBqb2IgZmluaXNoZWQuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gcmVwb3J0Sm9iRmluaXNoZWQoKSB7XG4gIGlmIChwcm9jZXNzLnNlbmQpIHByb2Nlc3Muc2VuZCh7dHlwZTogXCJqb2ItcmVwb3J0ZWRcIn0pXG59XG5cbi8qKlxuICogUnVucyBydW4gam9iIG1lc3NhZ2UuXG4gKiBAcGFyYW0gez99IG1lc3NhZ2UgLSBJUEMgbWVzc2FnZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIHRoZSBwYXlsb2FkIGhhcyBydW4uXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bkpvYk1lc3NhZ2UobWVzc2FnZSkge1xuICBpZiAoIWlzSm9iTWVzc2FnZShtZXNzYWdlKSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkZvcmtlZCBiYWNrZ3JvdW5kIGpvYiBydW5uZXIgcmVjZWl2ZWQgaW52YWxpZCBwYXlsb2FkXCIpXG4gIH1cblxuICAvLyBUaGUgcGVyLWpvYiBwcm9jZXNzIHRpdGxlIChhbmQgaXRzIHJlc3RvcmUpIGlzIHNldCBpbnNpZGUgcnVuSm9iUGF5bG9hZCxcbiAgLy8gd2hpY2ggcmVhZHMgdGhlIGpvYiBjbGFzcydzIGBzdGF0aWMgcHJvY2Vzc1RpdGxlYC4gVGhpcyBwcm9jZXNzIGJvb3RzIHdpdGhcbiAgLy8gdGhlIGJhc2UgXCJ2ZWxvY2lvdXMgYmFja2dyb3VuZC1qb2JzLXJ1bm5lclwiIHRpdGxlIHNldCBhdCBtb2R1bGUgbG9hZCBhYm92ZS5cbiAgYXdhaXQgcnVuSm9iUGF5bG9hZChtZXNzYWdlLnBheWxvYWQsIHtjbG9zZUNvbm5lY3Rpb25zOiBmYWxzZX0pXG59XG5cbi8qKlxuICogUnVucyBoYW5kbGUgam9iIG1lc3NhZ2UuXG4gKiBAcGFyYW0gez99IG1lc3NhZ2UgLSBJUEMgbWVzc2FnZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIGNvbXBsZXRpb24gaXMgcmVwb3J0ZWQuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZUpvYk1lc3NhZ2UobWVzc2FnZSkge1xuICB0cnkge1xuICAgIGF3YWl0IHJ1bkpvYk1lc3NhZ2UobWVzc2FnZSlcbiAgICByZXBvcnRKb2JGaW5pc2hlZCgpXG4gICAgZmluaXNoKDApXG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgcmVwb3J0Sm9iRmluaXNoZWQoKVxuICAgIGNvbnNvbGUuZXJyb3IoXCJGb3JrZWQgYmFja2dyb3VuZCBqb2IgcnVubmVyIGZhaWxlZDpcIiwgZXJyb3IpXG4gICAgZmluaXNoKDEpXG4gIH1cbn1cblxuZm9yIChjb25zdCBzaWduYWwgb2YgW1wiU0lHVEVSTVwiLCBcIlNJR0lOVFwiXSkge1xuICBwcm9jZXNzLm9uY2Uoc2lnbmFsLCAoKSA9PiBwcm9jZXNzLmV4aXQoMSkpXG59XG5cbnByb2Nlc3Mub25jZShcImRpc2Nvbm5lY3RcIiwgKCkgPT4ge1xuICBpZiAoIWZpbmlzaGluZykgcHJvY2Vzcy5leGl0KDApXG59KVxuXG5wcm9jZXNzLm9uY2UoXCJtZXNzYWdlXCIsIChtZXNzYWdlKSA9PiB7XG4gIHZvaWQgaGFuZGxlSm9iTWVzc2FnZShtZXNzYWdlKVxufSlcbiJdfQ==
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ya2VkLXJ1bm5lci1jaGlsZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvZm9ya2VkLXJ1bm5lci1jaGlsZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLE1BQU0saUJBQWlCLENBQUE7QUFDM0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLDBCQUEwQixFQUFFLE1BQU0sK0JBQStCLENBQUE7QUFDbEcsT0FBTyxxQkFBcUIsTUFBTSwyQkFBMkIsQ0FBQTtBQUU3RCw2RUFBNkU7QUFDN0UsOEVBQThFO0FBQzlFLDhFQUE4RTtBQUM5RSw0RUFBNEU7QUFDNUUscUJBQXFCLEVBQUUsQ0FBQTtBQUV2QixJQUFJLFNBQVMsR0FBRyxLQUFLLENBQUE7QUFDckIsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFBO0FBRXhCOzs7Ozs7O0dBT0c7QUFDSCxLQUFLLFVBQVUsY0FBYyxDQUFDLFFBQVE7SUFDcEMsSUFBSSxZQUFZLElBQUksU0FBUztRQUFFLE9BQU07SUFDckMsWUFBWSxHQUFHLElBQUksQ0FBQTtJQUVuQixNQUFNLHNCQUFzQixDQUFDLDBCQUEwQixFQUFFLENBQUMsQ0FBQTtJQUMxRCxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQ3hCLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyxZQUFZLENBQUMsT0FBTztJQUMzQixJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVE7UUFBRSxPQUFPLEtBQUssQ0FBQTtJQUV6RCxNQUFNLGFBQWEsR0FBRyxzQ0FBc0MsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0lBRXRFLE9BQU8sYUFBYSxDQUFDLElBQUksS0FBSyxLQUFLLElBQUksTUFBTSxDQUFDLE1BQU0sQ0FBQyxhQUFhLEVBQUUsU0FBUyxDQUFDLENBQUE7QUFDaEYsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLE1BQU0sQ0FBQyxRQUFRO0lBQ3RCLFNBQVMsR0FBRyxJQUFJLENBQUE7SUFDaEIsT0FBTyxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUE7SUFFM0IsSUFBSSxPQUFPLENBQUMsU0FBUyxJQUFJLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUM1QyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUE7SUFDdEIsQ0FBQztJQUVELFlBQVksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUE7QUFDNUMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsaUJBQWlCO0lBQ3hCLElBQUksT0FBTyxDQUFDLElBQUk7UUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUMsSUFBSSxFQUFFLGNBQWMsRUFBQyxDQUFDLENBQUE7QUFDeEQsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsYUFBYSxDQUFDLE9BQU87SUFDbEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQzNCLE1BQU0sSUFBSSxLQUFLLENBQUMsdURBQXVELENBQUMsQ0FBQTtJQUMxRSxDQUFDO0lBRUQsMkVBQTJFO0lBQzNFLDZFQUE2RTtJQUM3RSw4RUFBOEU7SUFDOUUsTUFBTSxhQUFhLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxFQUFDLGdCQUFnQixFQUFFLEtBQUssRUFBQyxDQUFDLENBQUE7QUFDakUsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxLQUFLLFVBQVUsZ0JBQWdCLENBQUMsT0FBTztJQUNyQyxJQUFJLENBQUM7UUFDSCxNQUFNLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUM1QixpQkFBaUIsRUFBRSxDQUFBO1FBQ25CLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNYLENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsaUJBQWlCLEVBQUUsQ0FBQTtRQUNuQixPQUFPLENBQUMsS0FBSyxDQUFDLHNDQUFzQyxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBQzVELE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNYLENBQUM7QUFDSCxDQUFDO0FBRUQsS0FBSyxNQUFNLE1BQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUMsRUFBRSxDQUFDO0lBQzNDLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDcEQsQ0FBQztBQUVELE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRTtJQUM5QixJQUFJLENBQUMsU0FBUztRQUFFLEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFBO0FBQ3hDLENBQUMsQ0FBQyxDQUFBO0FBRUYsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRTtJQUNsQyxLQUFLLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBQ2hDLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBydW5Kb2JQYXlsb2FkIGZyb20gXCIuL2pvYi1ydW5uZXIuanNcIlxuaW1wb3J0IHsgY2xvc2VSdW5uZXJDb25uZWN0aW9ucywgY3VycmVudENvbmZpZ3VyYXRpb25Pck51bGwgfSBmcm9tIFwiLi9ydW5uZXItZ3JhY2VmdWwtc2h1dGRvd24uanNcIlxuaW1wb3J0IHNldFJ1bm5lclByb2Nlc3NUaXRsZSBmcm9tIFwiLi9ydW5uZXItcHJvY2Vzcy10aXRsZS5qc1wiXG5cbi8vIE5hbWUgdGhlIHByb2Nlc3Mgc28gYHBzYC9gdG9wYC9gaHRvcGAgY2FuIGlkZW50aWZ5IGZvcmtlZCBqb2IgcnVubmVycyBhdCBhXG4vLyBnbGFuY2UgaW5zdGVhZCBvZiBhIHdhbGwgb2YgZ2VuZXJpYyBcIm5vZGVcIiBlbnRyaWVzLiBVcGRhdGVkIHRvIHRoZSBzcGVjaWZpY1xuLy8gam9iIG5hbWUgb25jZSBvbmUgYXJyaXZlcyAoc2VlIHJ1bkpvYk1lc3NhZ2UpLCBzbyBvcGVyYXRvcnMgY2FuIHNlZSBleGFjdGx5XG4vLyB3aGljaCBqb2JzIGFyZSBydW5uaW5nLCBob3cgbWFueSBvZiBlYWNoLCBhbmQgd2hpY2ggYXJlIGVhdGluZyByZXNvdXJjZXMuXG5zZXRSdW5uZXJQcm9jZXNzVGl0bGUoKVxuXG5sZXQgZmluaXNoaW5nID0gZmFsc2VcbmxldCBzaHV0dGluZ0Rvd24gPSBmYWxzZVxuXG4vKipcbiAqIENsb3NlcyB0aGUgcnVubmVyJ3MgY29ubmVjdGlvbnMg4oCUIHJlbGVhc2luZyBhbnkgYWR2aXNvcnkgbG9jayBhIGtpbGxlZC1taWQtam9iXG4gKiBqb2Igc3RpbGwgaG9sZHMg4oCUIGJlZm9yZSBleGl0aW5nIG9uIHNodXRkb3duLCBpbnN0ZWFkIG9mIGxlYXZpbmcgYSBoYWxmLW9wZW5cbiAqIHNlc3Npb24gdGhhdCBrZWVwcyB0aGUgbG9jayB1bnRpbCB0aGUgREIgc2VydmVyJ3MgYHdhaXRfdGltZW91dGAuIE5vcm1hbFxuICogY29tcGxldGlvbiAoYGZpbmlzaGApIGFscmVhZHkgcmVsZWFzZWQgaXRzIGxvY2tzIHZpYSB0aGUgam9iJ3Mgb3duIGxvY2sgc2NvcGUuXG4gKiBAcGFyYW0ge251bWJlcn0gZXhpdENvZGUgLSBQcm9jZXNzIGV4aXQgY29kZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICovXG5hc3luYyBmdW5jdGlvbiBzaHV0ZG93blJ1bm5lcihleGl0Q29kZSkge1xuICBpZiAoc2h1dHRpbmdEb3duIHx8IGZpbmlzaGluZykgcmV0dXJuXG4gIHNodXR0aW5nRG93biA9IHRydWVcblxuICBhd2FpdCBjbG9zZVJ1bm5lckNvbm5lY3Rpb25zKGN1cnJlbnRDb25maWd1cmF0aW9uT3JOdWxsKCkpXG4gIHByb2Nlc3MuZXhpdChleGl0Q29kZSlcbn1cblxuLyoqXG4gKiBSdW5zIGlzIGpvYiBtZXNzYWdlLlxuICogQHBhcmFtIHs/fSBtZXNzYWdlIC0gSVBDIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7bWVzc2FnZSBpcyB7dHlwZTogXCJqb2JcIiwgcGF5bG9hZDogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iUGF5bG9hZH19IC0gV2hldGhlciB0aGlzIGlzIGEgam9iIG1lc3NhZ2UuXG4gKi9cbmZ1bmN0aW9uIGlzSm9iTWVzc2FnZShtZXNzYWdlKSB7XG4gIGlmICghbWVzc2FnZSB8fCB0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIikgcmV0dXJuIGZhbHNlXG5cbiAgY29uc3QgbWVzc2FnZVJlY29yZCA9IC8qKiBAdHlwZSB7e3R5cGU/OiA/LCBwYXlsb2FkPzogP319ICovIChtZXNzYWdlKVxuXG4gIHJldHVybiBtZXNzYWdlUmVjb3JkLnR5cGUgPT09IFwiam9iXCIgJiYgT2JqZWN0Lmhhc093bihtZXNzYWdlUmVjb3JkLCBcInBheWxvYWRcIilcbn1cblxuLyoqXG4gKiBSdW5zIGZpbmlzaC5cbiAqIEBwYXJhbSB7bnVtYmVyfSBleGl0Q29kZSAtIFByb2Nlc3MgZXhpdCBjb2RlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGZpbmlzaChleGl0Q29kZSkge1xuICBmaW5pc2hpbmcgPSB0cnVlXG4gIHByb2Nlc3MuZXhpdENvZGUgPSBleGl0Q29kZVxuXG4gIGlmIChwcm9jZXNzLmNvbm5lY3RlZCAmJiBwcm9jZXNzLmRpc2Nvbm5lY3QpIHtcbiAgICBwcm9jZXNzLmRpc2Nvbm5lY3QoKVxuICB9XG5cbiAgc2V0SW1tZWRpYXRlKCgpID0+IHByb2Nlc3MuZXhpdChleGl0Q29kZSkpXG59XG5cbi8qKlxuICogUnVucyByZXBvcnQgam9iIGZpbmlzaGVkLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHJlcG9ydEpvYkZpbmlzaGVkKCkge1xuICBpZiAocHJvY2Vzcy5zZW5kKSBwcm9jZXNzLnNlbmQoe3R5cGU6IFwiam9iLXJlcG9ydGVkXCJ9KVxufVxuXG4vKipcbiAqIFJ1bnMgcnVuIGpvYiBtZXNzYWdlLlxuICogQHBhcmFtIHs/fSBtZXNzYWdlIC0gSVBDIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciB0aGUgcGF5bG9hZCBoYXMgcnVuLlxuICovXG5hc3luYyBmdW5jdGlvbiBydW5Kb2JNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgaWYgKCFpc0pvYk1lc3NhZ2UobWVzc2FnZSkpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJGb3JrZWQgYmFja2dyb3VuZCBqb2IgcnVubmVyIHJlY2VpdmVkIGludmFsaWQgcGF5bG9hZFwiKVxuICB9XG5cbiAgLy8gVGhlIHBlci1qb2IgcHJvY2VzcyB0aXRsZSAoYW5kIGl0cyByZXN0b3JlKSBpcyBzZXQgaW5zaWRlIHJ1bkpvYlBheWxvYWQsXG4gIC8vIHdoaWNoIHJlYWRzIHRoZSBqb2IgY2xhc3MncyBgc3RhdGljIHByb2Nlc3NUaXRsZWAuIFRoaXMgcHJvY2VzcyBib290cyB3aXRoXG4gIC8vIHRoZSBiYXNlIFwidmVsb2Npb3VzIGJhY2tncm91bmQtam9icy1ydW5uZXJcIiB0aXRsZSBzZXQgYXQgbW9kdWxlIGxvYWQgYWJvdmUuXG4gIGF3YWl0IHJ1bkpvYlBheWxvYWQobWVzc2FnZS5wYXlsb2FkLCB7Y2xvc2VDb25uZWN0aW9uczogZmFsc2V9KVxufVxuXG4vKipcbiAqIFJ1bnMgaGFuZGxlIGpvYiBtZXNzYWdlLlxuICogQHBhcmFtIHs/fSBtZXNzYWdlIC0gSVBDIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciBjb21wbGV0aW9uIGlzIHJlcG9ydGVkLlxuICovXG5hc3luYyBmdW5jdGlvbiBoYW5kbGVKb2JNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBydW5Kb2JNZXNzYWdlKG1lc3NhZ2UpXG4gICAgcmVwb3J0Sm9iRmluaXNoZWQoKVxuICAgIGZpbmlzaCgwKVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIHJlcG9ydEpvYkZpbmlzaGVkKClcbiAgICBjb25zb2xlLmVycm9yKFwiRm9ya2VkIGJhY2tncm91bmQgam9iIHJ1bm5lciBmYWlsZWQ6XCIsIGVycm9yKVxuICAgIGZpbmlzaCgxKVxuICB9XG59XG5cbmZvciAoY29uc3Qgc2lnbmFsIG9mIFtcIlNJR1RFUk1cIiwgXCJTSUdJTlRcIl0pIHtcbiAgcHJvY2Vzcy5vbmNlKHNpZ25hbCwgKCkgPT4gdm9pZCBzaHV0ZG93blJ1bm5lcigxKSlcbn1cblxucHJvY2Vzcy5vbmNlKFwiZGlzY29ubmVjdFwiLCAoKSA9PiB7XG4gIGlmICghZmluaXNoaW5nKSB2b2lkIHNodXRkb3duUnVubmVyKDApXG59KVxuXG5wcm9jZXNzLm9uY2UoXCJtZXNzYWdlXCIsIChtZXNzYWdlKSA9PiB7XG4gIHZvaWQgaGFuZGxlSm9iTWVzc2FnZShtZXNzYWdlKVxufSlcbiJdfQ==
@@ -1,8 +1,24 @@
1
1
  // @ts-check
2
2
  import runJobPayload, { BackgroundJobPerformedFailure } from "./job-runner.js";
3
+ import { closeRunnerConnections, currentConfigurationOrNull } from "./runner-graceful-shutdown.js";
3
4
  import setRunnerProcessTitle from "./runner-process-title.js";
4
5
  const BASE_PROCESS_TITLE = "velocious background-jobs-runner";
5
6
  setRunnerProcessTitle();
7
+ let shuttingDown = false;
8
+ /**
9
+ * Closes the runner's connections — releasing any advisory lock a killed-mid-pass
10
+ * job still holds — before exiting, instead of leaving a half-open session that
11
+ * keeps the lock until the DB server's `wait_timeout`.
12
+ * @param {number} exitCode - Process exit code.
13
+ * @returns {Promise<void>}
14
+ */
15
+ async function shutdownRunner(exitCode) {
16
+ if (shuttingDown)
17
+ return;
18
+ shuttingDown = true;
19
+ await closeRunnerConnections(currentConfigurationOrNull());
20
+ process.exit(exitCode);
21
+ }
6
22
  /**
7
23
  * Ids of jobs currently running in this child. A pooled child runs up to
8
24
  * `pooledRunnerConcurrency` jobs at once (the worker only dispatches within that
@@ -102,7 +118,7 @@ function handleMessage(message) {
102
118
  void runJob(message.payload);
103
119
  }
104
120
  process.on("message", (message) => handleMessage(message));
105
- process.once("disconnect", () => process.exit(0));
121
+ process.once("disconnect", () => void shutdownRunner(0));
106
122
  for (const signal of ["SIGTERM", "SIGINT"])
107
- process.once(signal, () => process.exit(1));
108
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9vbGVkLXJ1bm5lci1jaGlsZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvcG9vbGVkLXJ1bm5lci1jaGlsZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLEVBQUUsRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzlFLE9BQU8scUJBQXFCLE1BQU0sMkJBQTJCLENBQUE7QUFFN0QsTUFBTSxrQkFBa0IsR0FBRyxrQ0FBa0MsQ0FBQTtBQUU3RCxxQkFBcUIsRUFBRSxDQUFBO0FBRXZCOzs7Ozs7R0FNRztBQUNILE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7QUFFL0I7Ozs7Ozs7R0FPRztBQUNILFNBQVMsa0JBQWtCO0lBQ3pCLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUE7SUFFaEMsT0FBTyxDQUFDLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGtCQUFrQixLQUFLLEtBQUssSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQTtBQUNwSCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILFNBQVMsWUFBWSxDQUFDLE9BQU87SUFDM0IsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRO1FBQUUsT0FBTyxLQUFLLENBQUE7SUFDekQsTUFBTSxNQUFNLEdBQUcsc0NBQXNDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQTtJQUUvRCxPQUFPLE1BQU0sQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLE9BQU8sTUFBTSxDQUFDLE9BQU8sS0FBSyxRQUFRLElBQUksT0FBTyxNQUFNLENBQUMsT0FB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QyxDQUFDLENBQUMsQ0FBQTtBQUNqRCxLQUFLLE1BQU0sTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQztJQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbIi8vIEB0cy1jaGVja1xuXG5pbXBvcnQgcnVuSm9iUGF5bG9hZCwgeyBCYWNrZ3JvdW5kSm9iUGVyZm9ybWVkRmFpbHVyZSB9IGZyb20gXCIuL2pvYi1ydW5uZXIuanNcIlxuaW1wb3J0IHNldFJ1bm5lclByb2Nlc3NUaXRsZSBmcm9tIFwiLi9ydW5uZXItcHJvY2Vzcy10aXRsZS5qc1wiXG5cbmNvbnN0IEJBU0VfUFJPQ0VTU19USVRMRSA9IFwidmVsb2Npb3VzIGJhY2tncm91bmQtam9icy1ydW5uZXJcIlxuXG5zZXRSdW5uZXJQcm9jZXNzVGl0bGUoKVxuXG4vKipcbiAqIElkcyBvZiBqb2JzIGN1cnJlbnRseSBydW5uaW5nIGluIHRoaXMgY2hpbGQuIEEgcG9vbGVkIGNoaWxkIHJ1bnMgdXAgdG9cbiAqIGBwb29sZWRSdW5uZXJDb25jdXJyZW5jeWAgam9icyBhdCBvbmNlICh0aGUgd29ya2VyIG9ubHkgZGlzcGF0Y2hlcyB3aXRoaW4gdGhhdFxuICogYm91bmQpOyB0aGUgc2V0IGRlZHVwZXMgYSByZWRlbGl2ZXJlZCBqb2IgaWQgYW5kIGxldHMgZWFjaCBqb2Igc2V0dGxlXG4gKiBpbmRlcGVuZGVudGx5LlxuICogQHR5cGUge1NldDxzdHJpbmc+fVxuICovXG5jb25zdCBydW5uaW5nSm9iSWRzID0gbmV3IFNldCgpXG5cbi8qKlxuICogU2V0cyBhbiBhZ2dyZWdhdGUgcHJvY2VzcyB0aXRsZSBmcm9tIHRoZSBjdXJyZW50IGluLWZsaWdodCBjb3VudC4gQSBjaGlsZCBydW5zXG4gKiBqb2JzIGNvbmN1cnJlbnRseSwgc28gYSBwZXItam9iIHRpdGxlICh3aGljaCBgcnVuSm9iUGF5bG9hZGAgd291bGQgc25hcHNob3QgYW5kXG4gKiByZXN0b3JlIGFyb3VuZCBhIHNpbmdsZSBqb2IpIGNhbm5vdCByZXByZXNlbnQgdGhlIHByb2Nlc3Mg4oCUIGludGVybGVhdmVkXG4gKiBjb21wbGV0aW9ucyB3b3VsZCBsZWF2ZSBhIHN0YWxlIGxhYmVsLiBSZWNvbXB1dGluZyBmcm9tIGBydW5uaW5nSm9iSWRzLnNpemVgIGlzXG4gKiBjb25jdXJyZW5jeS1zYWZlIGFuZCBob25lc3Q6IGBwc2AvYHRvcGAgc2hvdyBob3cgbWFueSBqb2JzIHRoZSBjaGlsZCBpcyBydW5uaW5nLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVByb2Nlc3NUaXRsZSgpIHtcbiAgY29uc3QgY291bnQgPSBydW5uaW5nSm9iSWRzLnNpemVcblxuICBwcm9jZXNzLnRpdGxlID0gY291bnQgPiAwID8gYCR7QkFTRV9QUk9DRVNTX1RJVExFfTogJHtjb3VudH0gJHtjb3VudCA9PT0gMSA/IFwiam9iXCIgOiBcImpvYnNcIn1gIDogQkFTRV9QUk9DRVNTX1RJVExFXG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYW4gSVBDIHZhbHVlIGlzIGEgcnVubmFibGUgcG9vbGVkIGpvYiBtZXNzYWdlLlxuICogQHBhcmFtIHs/fSBtZXNzYWdlIC0gSVBDIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7bWVzc2FnZSBpcyB7dHlwZTogXCJqb2JcIiwgcGF5bG9hZDogaW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iUGF5bG9hZCAmIHtpZDogc3RyaW5nfX19IC0gV2hldGhlciB0aGlzIGlzIGEgdmFsaWQgam9iIG1lc3NhZ2UuXG4gKi9cbmZ1bmN0aW9uIGlzSm9iTWVzc2FnZShtZXNzYWdlKSB7XG4gIGlmICghbWVzc2FnZSB8fCB0eXBlb2YgbWVzc2FnZSAhPT0gXCJvYmplY3RcIikgcmV0dXJuIGZhbHNlXG4gIGNvbnN0IHJlY29yZCA9IC8qKiBAdHlwZSB7e3R5cGU/OiA/LCBwYXlsb2FkPzogP319ICovIChtZXNzYWdlKVxuXG4gIHJldHVybiByZWNvcmQudHlwZSA9PT0gXCJqb2JcIiAmJiAhIXJlY29yZC5wYXlsb2FkICYmIHR5cGVvZiByZWNvcmQucGF5bG9hZCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcmVjb3JkLnBheWxvYWQuaWQgPT09IFwic3RyaW5nXCJcbn1cblxuLyoqXG4gKiBTZW5kcyB0aGUgdGVybWluYWwgb3V0Y29tZSBhZnRlciB0aGUgbWFpbi9EQiByZXBvcnQgaGFzIGJlZW4gYWNrbm93bGVkZ2VkIG9yIHJlamVjdGVkLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPdXRjb21lLlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muam9iSWQgLSBKb2IgaWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFyZ3MuYWNrbm93bGVkZ2VkIC0gV2hldGhlciB0aGUgdGVybWluYWwgcmVwb3J0IHdhcyBhY2tub3dsZWRnZWQuXG4gKiBAcGFyYW0ge1wiY29tcGxldGVkXCIgfCBcImZhaWxlZFwifSBbYXJncy5zdGF0dXNdIC0gQWNrbm93bGVkZ2VkIHRlcm1pbmFsIHN0YXR1cy5cbiAqIEBwYXJhbSB7RXJyb3J9IFthcmdzLmVycm9yXSAtIFJlcG9ydGluZyBlcnJvciB3aGVuIGFja25vd2xlZGdlbWVudCB3YXMgbm90IG9idGFpbmVkLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgSVBDIGFjY2VwdHMgdGhlIG1lc3NhZ2UuXG4gKi9cbmZ1bmN0aW9uIHNlbmRPdXRjb21lKHtqb2JJZCwgYWNrbm93bGVkZ2VkLCBzdGF0dXMsIGVycm9yfSkge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHtcbiAgICBpZiAoIXByb2Nlc3Muc2VuZCkge1xuICAgICAgcmVzb2x2ZSh1bmRlZmluZWQpXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBwcm9jZXNzLnNlbmQoe1xuICAgICAgdHlwZTogXCJqb2Itb3V0Y29tZVwiLFxuICAgICAgam9iSWQsXG4gICAgICBhY2tub3dsZWRnZWQsXG4gICAgICBzdGF0dXMsXG4gICAgICByc3NCeXRlczogcHJvY2Vzcy5tZW1vcnlVc2FnZSgpLnJzcyxcbiAgICAgIGVycm9yOiBlcnJvcj8ubWVzc2FnZVxuICAgIH0sICgpID0+IHJlc29sdmUodW5kZWZpbmVkKSlcbiAgfSlcbn1cblxuLyoqXG4gKiBSdW5zIG9uZSBqb2IgY29uY3VycmVudGx5IHdpdGggYW55IHNpYmxpbmdzIGFuZCByZXBvcnRzIGl0cyBvd24gdGVybWluYWxcbiAqIG91dGNvbWUuIEEgc2luZ2xlIGpvYidzIHVuZXhwZWN0ZWQgZmFpbHVyZSByZXBvcnRzIHRoYXQgam9iIGZvciByZWNsYW1hdGlvblxuICogKGBhY2tub3dsZWRnZWQ6IGZhbHNlYCkgYnV0IGRvZXMgTk9UIHRha2UgZG93biB0aGUgY2hpbGQg4oCUIGl0cyBjb25jdXJyZW50XG4gKiBzaWJsaW5ncyBrZWVwIHJ1bm5pbmcuIE9ubHkgYSBwcm9jZXNzLWxldmVsIGZhdWx0ICh3aGljaCBlc2NhcGVzIGV2ZXJ5XG4gKiBwZXItam9iIHRyeS9jYXRjaCkgZW5kcyB0aGUgY2hpbGQsIHdoaWNoIHRoZSB3b3JrZXIgc2VlcyBhcyBhbiBleGl0IGFuZFxuICogcmVjbGFpbXMgZm9yIHRoZSB3aG9sZSBpbi1mbGlnaHQgc2V0LlxuICogQHBhcmFtIHtpbXBvcnQoXCIuL3R5cGVzLmpzXCIpLkJhY2tncm91bmRKb2JQYXlsb2FkICYge2lkOiBzdHJpbmd9fSBwYXlsb2FkIC0gSm9iIHBheWxvYWQuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciByZXBvcnRpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bkpvYihwYXlsb2FkKSB7XG4gIHRyeSB7XG4gICAgYXdhaXQgcnVuSm9iUGF5bG9hZChwYXlsb2FkLCB7Y2xvc2VDb25uZWN0aW9uczogZmFsc2UsIG1hbmFnZVByb2Nlc3NUaXRsZTogZmFsc2V9KVxuICAgIGF3YWl0IHNlbmRPdXRjb21lKHtqb2JJZDogcGF5bG9hZC5pZCwgYWNrbm93bGVkZ2VkOiB0cnVlLCBzdGF0dXM6IFwiY29tcGxldGVkXCJ9KVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEJhY2tncm91bmRKb2JQZXJmb3JtZWRGYWlsdXJlKSB7XG4gICAgICBhd2FpdCBzZW5kT3V0Y29tZSh7am9iSWQ6IHBheWxvYWQuaWQsIGFja25vd2xlZGdlZDogdHJ1ZSwgc3RhdHVzOiBcImZhaWxlZFwifSlcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmVwb3J0RXJyb3IgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSlcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJQb29sZWQgYmFja2dyb3VuZCBqb2IgcnVubmVyIGZhaWxlZCBiZWZvcmUgdGVybWluYWwgYWNrbm93bGVkZ2VtZW50OlwiLCByZXBvcnRFcnJvcilcbiAgICAgIGF3YWl0IHNlbmRPdXRjb21lKHtqb2JJZDogcGF5bG9hZC5pZCwgYWNrbm93bGVkZ2VkOiBmYWxzZSwgZXJyb3I6IHJlcG9ydEVycm9yfSlcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgcnVubmluZ0pvYklkcy5kZWxldGUocGF5bG9hZC5pZClcbiAgICB1cGRhdGVQcm9jZXNzVGl0bGUoKVxuICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIGpvYiBtZXNzYWdlLCBzdGFydGluZyBpdCBhbG9uZ3NpZGUgYW55IGNvbmN1cnJlbnQgc2libGluZ3MuXG4gKiBAcGFyYW0gez99IG1lc3NhZ2UgLSBJUEMgbWVzc2FnZS5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiBoYW5kbGVNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgaWYgKCFpc0pvYk1lc3NhZ2UobWVzc2FnZSkgfHwgcnVubmluZ0pvYklkcy5oYXMobWVzc2FnZS5wYXlsb2FkLmlkKSkgcmV0dXJuXG5cbiAgcnVubmluZ0pvYklkcy5hZGQobWVzc2FnZS5wYXlsb2FkLmlkKVxuICB1cGRhdGVQcm9jZXNzVGl0bGUoKVxuICB2b2lkIHJ1bkpvYihtZXNzYWdlLnBheWxvYWQpXG59XG5cbnByb2Nlc3Mub24oXCJtZXNzYWdlXCIsIChtZXNzYWdlKSA9PiBoYW5kbGVNZXNzYWdlKG1lc3NhZ2UpKVxucHJvY2Vzcy5vbmNlKFwiZGlzY29ubmVjdFwiLCAoKSA9PiBwcm9jZXNzLmV4aXQoMCkpXG5mb3IgKGNvbnN0IHNpZ25hbCBvZiBbXCJTSUdURVJNXCIsIFwiU0lHSU5UXCJdKSBwcm9jZXNzLm9uY2Uoc2lnbmFsLCAoKSA9PiBwcm9jZXNzLmV4aXQoMSkpXG4iXX0=
123
+ process.once(signal, () => void shutdownRunner(1));
124
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9vbGVkLXJ1bm5lci1jaGlsZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvcG9vbGVkLXJ1bm5lci1jaGlsZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLEVBQUUsRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzlFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLCtCQUErQixDQUFBO0FBQ2xHLE9BQU8scUJBQXFCLE1BQU0sMkJBQTJCLENBQUE7QUFFN0QsTUFBTSxrQkFBa0IsR0FBRyxrQ0FBa0MsQ0FBQTtBQUU3RCxxQkFBcUIsRUFBRSxDQUFBO0FBRXZCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQTtBQUV4Qjs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsY0FBYyxDQUFDLFFBQVE7SUFDcEMsSUFBSSxZQUFZO1FBQUUsT0FBTTtJQUN4QixZQUFZLEdBQUcsSUFBSSxDQUFBO0lBRW5CLE1BQU0sc0JBQXNCLENBQUMsMEJBQTBCLEVBQUUsQ0FBQyxDQUFBO0lBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDeEIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7QUFFL0I7Ozs7Ozs7R0FPRztBQUNILFNBQVMsa0JBQWtCO0lBQ3pCLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUE7SUFFaEMsT0FBTyxDQUFDLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGtCQUFrQixLQUFLLEtBQUssSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQTtBQUNwSCxDQUFD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QUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUNyQyxrQkFBa0IsRUFBRSxDQUFBO0lBQ3BCLEtBQUssTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQTtBQUM5QixDQUFDO0FBRUQsT0FBTyxDQUFDLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFBO0FBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7QUFDeEQsS0FBSyxNQUFNLE1BQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxRQUFRLENBQUM7SUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxLQUFLLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCBydW5Kb2JQYXlsb2FkLCB7IEJhY2tncm91bmRKb2JQZXJmb3JtZWRGYWlsdXJlIH0gZnJvbSBcIi4vam9iLXJ1bm5lci5qc1wiXG5pbXBvcnQgeyBjbG9zZVJ1bm5lckNvbm5lY3Rpb25zLCBjdXJyZW50Q29uZmlndXJhdGlvbk9yTnVsbCB9IGZyb20gXCIuL3J1bm5lci1ncmFjZWZ1bC1zaHV0ZG93bi5qc1wiXG5pbXBvcnQgc2V0UnVubmVyUHJvY2Vzc1RpdGxlIGZyb20gXCIuL3J1bm5lci1wcm9jZXNzLXRpdGxlLmpzXCJcblxuY29uc3QgQkFTRV9QUk9DRVNTX1RJVExFID0gXCJ2ZWxvY2lvdXMgYmFja2dyb3VuZC1qb2JzLXJ1bm5lclwiXG5cbnNldFJ1bm5lclByb2Nlc3NUaXRsZSgpXG5cbmxldCBzaHV0dGluZ0Rvd24gPSBmYWxzZVxuXG4vKipcbiAqIENsb3NlcyB0aGUgcnVubmVyJ3MgY29ubmVjdGlvbnMg4oCUIHJlbGVhc2luZyBhbnkgYWR2aXNvcnkgbG9jayBhIGtpbGxlZC1taWQtcGFzc1xuICogam9iIHN0aWxsIGhvbGRzIOKAlCBiZWZvcmUgZXhpdGluZywgaW5zdGVhZCBvZiBsZWF2aW5nIGEgaGFsZi1vcGVuIHNlc3Npb24gdGhhdFxuICoga2VlcHMgdGhlIGxvY2sgdW50aWwgdGhlIERCIHNlcnZlcidzIGB3YWl0X3RpbWVvdXRgLlxuICogQHBhcmFtIHtudW1iZXJ9IGV4aXRDb2RlIC0gUHJvY2VzcyBleGl0IGNvZGUuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn1cbiAqL1xuYXN5bmMgZnVuY3Rpb24gc2h1dGRvd25SdW5uZXIoZXhpdENvZGUpIHtcbiAgaWYgKHNodXR0aW5nRG93bikgcmV0dXJuXG4gIHNodXR0aW5nRG93biA9IHRydWVcblxuICBhd2FpdCBjbG9zZVJ1bm5lckNvbm5lY3Rpb25zKGN1cnJlbnRDb25maWd1cmF0aW9uT3JOdWxsKCkpXG4gIHByb2Nlc3MuZXhpdChleGl0Q29kZSlcbn1cblxuLyoqXG4gKiBJZHMgb2Ygam9icyBjdXJyZW50bHkgcnVubmluZyBpbiB0aGlzIGNoaWxkLiBBIHBvb2xlZCBjaGlsZCBydW5zIHVwIHRvXG4gKiBgcG9vbGVkUnVubmVyQ29uY3VycmVuY3lgIGpvYnMgYXQgb25jZSAodGhlIHdvcmtlciBvbmx5IGRpc3BhdGNoZXMgd2l0aGluIHRoYXRcbiAqIGJvdW5kKTsgdGhlIHNldCBkZWR1cGVzIGEgcmVkZWxpdmVyZWQgam9iIGlkIGFuZCBsZXRzIGVhY2ggam9iIHNldHRsZVxuICogaW5kZXBlbmRlbnRseS5cbiAqIEB0eXBlIHtTZXQ8c3RyaW5nPn1cbiAqL1xuY29uc3QgcnVubmluZ0pvYklkcyA9IG5ldyBTZXQoKVxuXG4vKipcbiAqIFNldHMgYW4gYWdncmVnYXRlIHByb2Nlc3MgdGl0bGUgZnJvbSB0aGUgY3VycmVudCBpbi1mbGlnaHQgY291bnQuIEEgY2hpbGQgcnVuc1xuICogam9icyBjb25jdXJyZW50bHksIHNvIGEgcGVyLWpvYiB0aXRsZSAod2hpY2ggYHJ1bkpvYlBheWxvYWRgIHdvdWxkIHNuYXBzaG90IGFuZFxuICogcmVzdG9yZSBhcm91bmQgYSBzaW5nbGUgam9iKSBjYW5ub3QgcmVwcmVzZW50IHRoZSBwcm9jZXNzIOKAlCBpbnRlcmxlYXZlZFxuICogY29tcGxldGlvbnMgd291bGQgbGVhdmUgYSBzdGFsZSBsYWJlbC4gUmVjb21wdXRpbmcgZnJvbSBgcnVubmluZ0pvYklkcy5zaXplYCBpc1xuICogY29uY3VycmVuY3ktc2FmZSBhbmQgaG9uZXN0OiBgcHNgL2B0b3BgIHNob3cgaG93IG1hbnkgam9icyB0aGUgY2hpbGQgaXMgcnVubmluZy5cbiAqIEByZXR1cm5zIHt2b2lkfVxuICovXG5mdW5jdGlvbiB1cGRhdGVQcm9jZXNzVGl0bGUoKSB7XG4gIGNvbnN0IGNvdW50ID0gcnVubmluZ0pvYklkcy5zaXplXG5cbiAgcHJvY2Vzcy50aXRsZSA9IGNvdW50ID4gMCA/IGAke0JBU0VfUFJPQ0VTU19USVRMRX06ICR7Y291bnR9ICR7Y291bnQgPT09IDEgPyBcImpvYlwiIDogXCJqb2JzXCJ9YCA6IEJBU0VfUFJPQ0VTU19USVRMRVxufVxuXG4vKipcbiAqIENoZWNrcyB3aGV0aGVyIGFuIElQQyB2YWx1ZSBpcyBhIHJ1bm5hYmxlIHBvb2xlZCBqb2IgbWVzc2FnZS5cbiAqIEBwYXJhbSB7P30gbWVzc2FnZSAtIElQQyBtZXNzYWdlLlxuICogQHJldHVybnMge21lc3NhZ2UgaXMge3R5cGU6IFwiam9iXCIsIHBheWxvYWQ6IGltcG9ydChcIi4vdHlwZXMuanNcIikuQmFja2dyb3VuZEpvYlBheWxvYWQgJiB7aWQ6IHN0cmluZ319fSAtIFdoZXRoZXIgdGhpcyBpcyBhIHZhbGlkIGpvYiBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiBpc0pvYk1lc3NhZ2UobWVzc2FnZSkge1xuICBpZiAoIW1lc3NhZ2UgfHwgdHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIpIHJldHVybiBmYWxzZVxuICBjb25zdCByZWNvcmQgPSAvKiogQHR5cGUge3t0eXBlPzogPywgcGF5bG9hZD86ID99fSAqLyAobWVzc2FnZSlcblxuICByZXR1cm4gcmVjb3JkLnR5cGUgPT09IFwiam9iXCIgJiYgISFyZWNvcmQucGF5bG9hZCAmJiB0eXBlb2YgcmVjb3JkLnBheWxvYWQgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHJlY29yZC5wYXlsb2FkLmlkID09PSBcInN0cmluZ1wiXG59XG5cbi8qKlxuICogU2VuZHMgdGhlIHRlcm1pbmFsIG91dGNvbWUgYWZ0ZXIgdGhlIG1haW4vREIgcmVwb3J0IGhhcyBiZWVuIGFja25vd2xlZGdlZCBvciByZWplY3RlZC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3V0Y29tZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmpvYklkIC0gSm9iIGlkLlxuICogQHBhcmFtIHtib29sZWFufSBhcmdzLmFja25vd2xlZGdlZCAtIFdoZXRoZXIgdGhlIHRlcm1pbmFsIHJlcG9ydCB3YXMgYWNrbm93bGVkZ2VkLlxuICogQHBhcmFtIHtcImNvbXBsZXRlZFwiIHwgXCJmYWlsZWRcIn0gW2FyZ3Muc3RhdHVzXSAtIEFja25vd2xlZGdlZCB0ZXJtaW5hbCBzdGF0dXMuXG4gKiBAcGFyYW0ge0Vycm9yfSBbYXJncy5lcnJvcl0gLSBSZXBvcnRpbmcgZXJyb3Igd2hlbiBhY2tub3dsZWRnZW1lbnQgd2FzIG5vdCBvYnRhaW5lZC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIElQQyBhY2NlcHRzIHRoZSBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiBzZW5kT3V0Y29tZSh7am9iSWQsIGFja25vd2xlZGdlZCwgc3RhdHVzLCBlcnJvcn0pIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgaWYgKCFwcm9jZXNzLnNlbmQpIHtcbiAgICAgIHJlc29sdmUodW5kZWZpbmVkKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgcHJvY2Vzcy5zZW5kKHtcbiAgICAgIHR5cGU6IFwiam9iLW91dGNvbWVcIixcbiAgICAgIGpvYklkLFxuICAgICAgYWNrbm93bGVkZ2VkLFxuICAgICAgc3RhdHVzLFxuICAgICAgcnNzQnl0ZXM6IHByb2Nlc3MubWVtb3J5VXNhZ2UoKS5yc3MsXG4gICAgICBlcnJvcjogZXJyb3I/Lm1lc3NhZ2VcbiAgICB9LCAoKSA9PiByZXNvbHZlKHVuZGVmaW5lZCkpXG4gIH0pXG59XG5cbi8qKlxuICogUnVucyBvbmUgam9iIGNvbmN1cnJlbnRseSB3aXRoIGFueSBzaWJsaW5ncyBhbmQgcmVwb3J0cyBpdHMgb3duIHRlcm1pbmFsXG4gKiBvdXRjb21lLiBBIHNpbmdsZSBqb2IncyB1bmV4cGVjdGVkIGZhaWx1cmUgcmVwb3J0cyB0aGF0IGpvYiBmb3IgcmVjbGFtYXRpb25cbiAqIChgYWNrbm93bGVkZ2VkOiBmYWxzZWApIGJ1dCBkb2VzIE5PVCB0YWtlIGRvd24gdGhlIGNoaWxkIOKAlCBpdHMgY29uY3VycmVudFxuICogc2libGluZ3Mga2VlcCBydW5uaW5nLiBPbmx5IGEgcHJvY2Vzcy1sZXZlbCBmYXVsdCAod2hpY2ggZXNjYXBlcyBldmVyeVxuICogcGVyLWpvYiB0cnkvY2F0Y2gpIGVuZHMgdGhlIGNoaWxkLCB3aGljaCB0aGUgd29ya2VyIHNlZXMgYXMgYW4gZXhpdCBhbmRcbiAqIHJlY2xhaW1zIGZvciB0aGUgd2hvbGUgaW4tZmxpZ2h0IHNldC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iUGF5bG9hZCAmIHtpZDogc3RyaW5nfX0gcGF5bG9hZCAtIEpvYiBwYXlsb2FkLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgcmVwb3J0aW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBydW5Kb2IocGF5bG9hZCkge1xuICB0cnkge1xuICAgIGF3YWl0IHJ1bkpvYlBheWxvYWQocGF5bG9hZCwge2Nsb3NlQ29ubmVjdGlvbnM6IGZhbHNlLCBtYW5hZ2VQcm9jZXNzVGl0bGU6IGZhbHNlfSlcbiAgICBhd2FpdCBzZW5kT3V0Y29tZSh7am9iSWQ6IHBheWxvYWQuaWQsIGFja25vd2xlZGdlZDogdHJ1ZSwgc3RhdHVzOiBcImNvbXBsZXRlZFwifSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBCYWNrZ3JvdW5kSm9iUGVyZm9ybWVkRmFpbHVyZSkge1xuICAgICAgYXdhaXQgc2VuZE91dGNvbWUoe2pvYklkOiBwYXlsb2FkLmlkLCBhY2tub3dsZWRnZWQ6IHRydWUsIHN0YXR1czogXCJmYWlsZWRcIn0pXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlcG9ydEVycm9yID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpXG4gICAgICBjb25zb2xlLmVycm9yKFwiUG9vbGVkIGJhY2tncm91bmQgam9iIHJ1bm5lciBmYWlsZWQgYmVmb3JlIHRlcm1pbmFsIGFja25vd2xlZGdlbWVudDpcIiwgcmVwb3J0RXJyb3IpXG4gICAgICBhd2FpdCBzZW5kT3V0Y29tZSh7am9iSWQ6IHBheWxvYWQuaWQsIGFja25vd2xlZGdlZDogZmFsc2UsIGVycm9yOiByZXBvcnRFcnJvcn0pXG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIHJ1bm5pbmdKb2JJZHMuZGVsZXRlKHBheWxvYWQuaWQpXG4gICAgdXBkYXRlUHJvY2Vzc1RpdGxlKClcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZXMgYSBqb2IgbWVzc2FnZSwgc3RhcnRpbmcgaXQgYWxvbmdzaWRlIGFueSBjb25jdXJyZW50IHNpYmxpbmdzLlxuICogQHBhcmFtIHs/fSBtZXNzYWdlIC0gSVBDIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gaGFuZGxlTWVzc2FnZShtZXNzYWdlKSB7XG4gIGlmICghaXNKb2JNZXNzYWdlKG1lc3NhZ2UpIHx8IHJ1bm5pbmdKb2JJZHMuaGFzKG1lc3NhZ2UucGF5bG9hZC5pZCkpIHJldHVyblxuXG4gIHJ1bm5pbmdKb2JJZHMuYWRkKG1lc3NhZ2UucGF5bG9hZC5pZClcbiAgdXBkYXRlUHJvY2Vzc1RpdGxlKClcbiAgdm9pZCBydW5Kb2IobWVzc2FnZS5wYXlsb2FkKVxufVxuXG5wcm9jZXNzLm9uKFwibWVzc2FnZVwiLCAobWVzc2FnZSkgPT4gaGFuZGxlTWVzc2FnZShtZXNzYWdlKSlcbnByb2Nlc3Mub25jZShcImRpc2Nvbm5lY3RcIiwgKCkgPT4gdm9pZCBzaHV0ZG93blJ1bm5lcigwKSlcbmZvciAoY29uc3Qgc2lnbmFsIG9mIFtcIlNJR1RFUk1cIiwgXCJTSUdJTlRcIl0pIHByb2Nlc3Mub25jZShzaWduYWwsICgpID0+IHZvaWQgc2h1dGRvd25SdW5uZXIoMSkpXG4iXX0=
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The subset of a configuration a runner closes on shutdown. Typed structurally so
3
+ * the shutdown path stays typechecked without a broad cast, and a future signature
4
+ * drift surfaces at the call sites (and in tests) instead of hiding behind `any`.
5
+ * @typedef {{disconnectBeacon: () => Promise<void>, closeDatabaseConnections: () => Promise<void>}} RunnerCloseableConfiguration
6
+ */
7
+ /**
8
+ * Gracefully closes a background-job runner's framework connections (beacon +
9
+ * database) on shutdown, so the database server ends the session and releases any
10
+ * advisory lock the runner still holds *immediately* — instead of leaving a
11
+ * half-open session that keeps the lock (e.g. the build-planner lock) held until
12
+ * the server's idle `wait_timeout` (hours).
13
+ *
14
+ * A runner child otherwise exits abruptly on shutdown (`process.exit`) and relies
15
+ * on the OS tearing down its sockets. A named lock releases only when its owning
16
+ * session ends, and an abrupt exit / container teardown does not reliably deliver a
17
+ * clean disconnect to the server — so the lock leaks. Sending a real close here
18
+ * (`COM_QUIT` via `closeDatabaseConnections`) makes the server end the session and
19
+ * release the lock deterministically.
20
+ *
21
+ * The beacon disconnect and the database close run independently, each bounded by
22
+ * `closeTimeoutMs`: the database close releases the locks and must still run even if
23
+ * the beacon disconnect hangs (a wedged beacon socket during teardown), and neither
24
+ * may block the exit forever. A failed or timed-out close is thrown, not swallowed —
25
+ * the caller surfaces it (a lock that failed to release must be visible).
26
+ * @param {RunnerCloseableConfiguration | null} configuration - Configuration whose connections to close; null when none is set (nothing to close).
27
+ * @param {number} [closeTimeoutMs] - Max time to spend on each close before giving up.
28
+ * @returns {Promise<void>} - Resolves once both closes have settled; rejects if either failed.
29
+ */
30
+ export function closeRunnerConnections(configuration: RunnerCloseableConfiguration | null, closeTimeoutMs?: number): Promise<void>;
31
+ /**
32
+ * The current configuration, or null when none has been set yet — a runner that is
33
+ * signalled before it runs any job holds no connections (and no locks) to close.
34
+ * Only that expected "not set yet" case is treated as null; any other error is a real
35
+ * fault and is rethrown rather than masked.
36
+ * @returns {Configuration | null} - The current configuration, or null when none is set.
37
+ */
38
+ export function currentConfigurationOrNull(): Configuration | null;
39
+ /**
40
+ * The subset of a configuration a runner closes on shutdown. Typed structurally so
41
+ * the shutdown path stays typechecked without a broad cast, and a future signature
42
+ * drift surfaces at the call sites (and in tests) instead of hiding behind `any`.
43
+ */
44
+ export type RunnerCloseableConfiguration = {
45
+ disconnectBeacon: () => Promise<void>;
46
+ closeDatabaseConnections: () => Promise<void>;
47
+ };
48
+ import Configuration from "../configuration.js";
49
+ //# sourceMappingURL=runner-graceful-shutdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-graceful-shutdown.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/runner-graceful-shutdown.js"],"names":[],"mappings":"AASA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,sDAJW,4BAA4B,GAAG,IAAI,mBACnC,MAAM,GACJ,OAAO,CAAC,IAAI,CAAC,CAkBzB;AAED;;;;;;GAMG;AACH,8CAFa,aAAa,GAAG,IAAI,CAUhC;;;;;;2CA3DY;IAAC,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,wBAAwB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAC;0BATtC,qBAAqB"}
@@ -0,0 +1,70 @@
1
+ // @ts-check
2
+ import timeout from "awaitery/build/timeout.js";
3
+ import Configuration, { CurrentConfigurationNotSetError } from "../configuration.js";
4
+ /** Bounded grace for closing framework connections on shutdown before forcing exit. */
5
+ const SHUTDOWN_CLOSE_TIMEOUT_MS = 5000;
6
+ /**
7
+ * The subset of a configuration a runner closes on shutdown. Typed structurally so
8
+ * the shutdown path stays typechecked without a broad cast, and a future signature
9
+ * drift surfaces at the call sites (and in tests) instead of hiding behind `any`.
10
+ * @typedef {{disconnectBeacon: () => Promise<void>, closeDatabaseConnections: () => Promise<void>}} RunnerCloseableConfiguration
11
+ */
12
+ /**
13
+ * Gracefully closes a background-job runner's framework connections (beacon +
14
+ * database) on shutdown, so the database server ends the session and releases any
15
+ * advisory lock the runner still holds *immediately* — instead of leaving a
16
+ * half-open session that keeps the lock (e.g. the build-planner lock) held until
17
+ * the server's idle `wait_timeout` (hours).
18
+ *
19
+ * A runner child otherwise exits abruptly on shutdown (`process.exit`) and relies
20
+ * on the OS tearing down its sockets. A named lock releases only when its owning
21
+ * session ends, and an abrupt exit / container teardown does not reliably deliver a
22
+ * clean disconnect to the server — so the lock leaks. Sending a real close here
23
+ * (`COM_QUIT` via `closeDatabaseConnections`) makes the server end the session and
24
+ * release the lock deterministically.
25
+ *
26
+ * The beacon disconnect and the database close run independently, each bounded by
27
+ * `closeTimeoutMs`: the database close releases the locks and must still run even if
28
+ * the beacon disconnect hangs (a wedged beacon socket during teardown), and neither
29
+ * may block the exit forever. A failed or timed-out close is thrown, not swallowed —
30
+ * the caller surfaces it (a lock that failed to release must be visible).
31
+ * @param {RunnerCloseableConfiguration | null} configuration - Configuration whose connections to close; null when none is set (nothing to close).
32
+ * @param {number} [closeTimeoutMs] - Max time to spend on each close before giving up.
33
+ * @returns {Promise<void>} - Resolves once both closes have settled; rejects if either failed.
34
+ */
35
+ export async function closeRunnerConnections(configuration, closeTimeoutMs = SHUTDOWN_CLOSE_TIMEOUT_MS) {
36
+ if (!configuration)
37
+ return;
38
+ const [beaconResult, databaseResult] = await Promise.allSettled([
39
+ timeout({ timeout: closeTimeoutMs }, () => configuration.disconnectBeacon()),
40
+ timeout({ timeout: closeTimeoutMs }, () => configuration.closeDatabaseConnections())
41
+ ]);
42
+ /** @type {unknown[]} */
43
+ const errors = [];
44
+ if (beaconResult.status == "rejected")
45
+ errors.push(beaconResult.reason);
46
+ if (databaseResult.status == "rejected")
47
+ errors.push(databaseResult.reason);
48
+ if (errors.length == 1)
49
+ throw errors[0];
50
+ if (errors.length > 1)
51
+ throw new AggregateError(errors, "Failed to close background-job runner connections on shutdown");
52
+ }
53
+ /**
54
+ * The current configuration, or null when none has been set yet — a runner that is
55
+ * signalled before it runs any job holds no connections (and no locks) to close.
56
+ * Only that expected "not set yet" case is treated as null; any other error is a real
57
+ * fault and is rethrown rather than masked.
58
+ * @returns {Configuration | null} - The current configuration, or null when none is set.
59
+ */
60
+ export function currentConfigurationOrNull() {
61
+ try {
62
+ return Configuration.current();
63
+ }
64
+ catch (error) {
65
+ if (error instanceof CurrentConfigurationNotSetError)
66
+ return null;
67
+ throw error;
68
+ }
69
+ }
70
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVubmVyLWdyYWNlZnVsLXNodXRkb3duLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL2JhY2tncm91bmQtam9icy9ydW5uZXItZ3JhY2VmdWwtc2h1dGRvd24uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsWUFBWTtBQUVaLE9BQU8sT0FBTyxNQUFNLDJCQUEyQixDQUFBO0FBRS9DLE9BQU8sYUFBYSxFQUFFLEVBQUMsK0JBQStCLEVBQUMsTUFBTSxxQkFBcUIsQ0FBQTtBQUVsRix1RkFBdUY7QUFDdkYsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUE7QUFFdEM7Ozs7O0dBS0c7QUFFSDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXNCRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsc0JBQXNCLENBQUMsYUFBYSxFQUFFLGNBQWMsR0FBRyx5QkFBeUI7SUFDcEcsSUFBSSxDQUFDLGFBQWE7UUFBRSxPQUFNO0lBRTFCLE1BQU0sQ0FBQyxZQUFZLEVBQUUsY0FBYyxDQUFDLEdBQUcsTUFBTSxPQUFPLENBQUMsVUFBVSxDQUFDO1FBQzlELE9BQU8sQ0FBQyxFQUFDLE9BQU8sRUFBRSxjQUFjLEVBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztRQUMxRSxPQUFPLENBQUMsRUFBQyxPQUFPLEVBQUUsY0FBYyxFQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsYUFBYSxDQUFDLHdCQUF3QixFQUFFLENBQUM7S0FDbkYsQ0FBQyxDQUFBO0lBRUYsd0JBQXdCO0lBQ3hCLE1BQU0sTUFBTSxHQUFHLEVBQUUsQ0FBQTtJQUVqQixJQUFJLFlBQVksQ0FBQyxNQUFNLElBQUksVUFBVTtRQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3ZFLElBQUksY0FBYyxDQUFDLE1BQU0sSUFBSSxVQUFVO1FBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUE7SUFFM0UsSUFBSSxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUM7UUFBRSxNQUFNLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUN2QyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUFFLE1BQU0sSUFBSSxjQUFjLENBQUMsTUFBTSxFQUFFLCtEQUErRCxDQUFDLENBQUE7QUFDMUgsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSwwQkFBMEI7SUFDeEMsSUFBSSxDQUFDO1FBQ0gsT0FBTyxhQUFhLENBQUMsT0FBTyxFQUFFLENBQUE7SUFDaEMsQ0FBQztJQUFDLE9BQU8sS0FBSyxFQUFFLENBQUM7UUFDZixJQUFJLEtBQUssWUFBWSwrQkFBK0I7WUFBRSxPQUFPLElBQUksQ0FBQTtRQUVqRSxNQUFNLEtBQUssQ0FBQTtJQUNiLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmltcG9ydCB0aW1lb3V0IGZyb20gXCJhd2FpdGVyeS9idWlsZC90aW1lb3V0LmpzXCJcblxuaW1wb3J0IENvbmZpZ3VyYXRpb24sIHtDdXJyZW50Q29uZmlndXJhdGlvbk5vdFNldEVycm9yfSBmcm9tIFwiLi4vY29uZmlndXJhdGlvbi5qc1wiXG5cbi8qKiBCb3VuZGVkIGdyYWNlIGZvciBjbG9zaW5nIGZyYW1ld29yayBjb25uZWN0aW9ucyBvbiBzaHV0ZG93biBiZWZvcmUgZm9yY2luZyBleGl0LiAqL1xuY29uc3QgU0hVVERPV05fQ0xPU0VfVElNRU9VVF9NUyA9IDUwMDBcblxuLyoqXG4gKiBUaGUgc3Vic2V0IG9mIGEgY29uZmlndXJhdGlvbiBhIHJ1bm5lciBjbG9zZXMgb24gc2h1dGRvd24uIFR5cGVkIHN0cnVjdHVyYWxseSBzb1xuICogdGhlIHNodXRkb3duIHBhdGggc3RheXMgdHlwZWNoZWNrZWQgd2l0aG91dCBhIGJyb2FkIGNhc3QsIGFuZCBhIGZ1dHVyZSBzaWduYXR1cmVcbiAqIGRyaWZ0IHN1cmZhY2VzIGF0IHRoZSBjYWxsIHNpdGVzIChhbmQgaW4gdGVzdHMpIGluc3RlYWQgb2YgaGlkaW5nIGJlaGluZCBgYW55YC5cbiAqIEB0eXBlZGVmIHt7ZGlzY29ubmVjdEJlYWNvbjogKCkgPT4gUHJvbWlzZTx2b2lkPiwgY2xvc2VEYXRhYmFzZUNvbm5lY3Rpb25zOiAoKSA9PiBQcm9taXNlPHZvaWQ+fX0gUnVubmVyQ2xvc2VhYmxlQ29uZmlndXJhdGlvblxuICovXG5cbi8qKlxuICogR3JhY2VmdWxseSBjbG9zZXMgYSBiYWNrZ3JvdW5kLWpvYiBydW5uZXIncyBmcmFtZXdvcmsgY29ubmVjdGlvbnMgKGJlYWNvbiArXG4gKiBkYXRhYmFzZSkgb24gc2h1dGRvd24sIHNvIHRoZSBkYXRhYmFzZSBzZXJ2ZXIgZW5kcyB0aGUgc2Vzc2lvbiBhbmQgcmVsZWFzZXMgYW55XG4gKiBhZHZpc29yeSBsb2NrIHRoZSBydW5uZXIgc3RpbGwgaG9sZHMgKmltbWVkaWF0ZWx5KiDigJQgaW5zdGVhZCBvZiBsZWF2aW5nIGFcbiAqIGhhbGYtb3BlbiBzZXNzaW9uIHRoYXQga2VlcHMgdGhlIGxvY2sgKGUuZy4gdGhlIGJ1aWxkLXBsYW5uZXIgbG9jaykgaGVsZCB1bnRpbFxuICogdGhlIHNlcnZlcidzIGlkbGUgYHdhaXRfdGltZW91dGAgKGhvdXJzKS5cbiAqXG4gKiBBIHJ1bm5lciBjaGlsZCBvdGhlcndpc2UgZXhpdHMgYWJydXB0bHkgb24gc2h1dGRvd24gKGBwcm9jZXNzLmV4aXRgKSBhbmQgcmVsaWVzXG4gKiBvbiB0aGUgT1MgdGVhcmluZyBkb3duIGl0cyBzb2NrZXRzLiBBIG5hbWVkIGxvY2sgcmVsZWFzZXMgb25seSB3aGVuIGl0cyBvd25pbmdcbiAqIHNlc3Npb24gZW5kcywgYW5kIGFuIGFicnVwdCBleGl0IC8gY29udGFpbmVyIHRlYXJkb3duIGRvZXMgbm90IHJlbGlhYmx5IGRlbGl2ZXIgYVxuICogY2xlYW4gZGlzY29ubmVjdCB0byB0aGUgc2VydmVyIOKAlCBzbyB0aGUgbG9jayBsZWFrcy4gU2VuZGluZyBhIHJlYWwgY2xvc2UgaGVyZVxuICogKGBDT01fUVVJVGAgdmlhIGBjbG9zZURhdGFiYXNlQ29ubmVjdGlvbnNgKSBtYWtlcyB0aGUgc2VydmVyIGVuZCB0aGUgc2Vzc2lvbiBhbmRcbiAqIHJlbGVhc2UgdGhlIGxvY2sgZGV0ZXJtaW5pc3RpY2FsbHkuXG4gKlxuICogVGhlIGJlYWNvbiBkaXNjb25uZWN0IGFuZCB0aGUgZGF0YWJhc2UgY2xvc2UgcnVuIGluZGVwZW5kZW50bHksIGVhY2ggYm91bmRlZCBieVxuICogYGNsb3NlVGltZW91dE1zYDogdGhlIGRhdGFiYXNlIGNsb3NlIHJlbGVhc2VzIHRoZSBsb2NrcyBhbmQgbXVzdCBzdGlsbCBydW4gZXZlbiBpZlxuICogdGhlIGJlYWNvbiBkaXNjb25uZWN0IGhhbmdzIChhIHdlZGdlZCBiZWFjb24gc29ja2V0IGR1cmluZyB0ZWFyZG93biksIGFuZCBuZWl0aGVyXG4gKiBtYXkgYmxvY2sgdGhlIGV4aXQgZm9yZXZlci4gQSBmYWlsZWQgb3IgdGltZWQtb3V0IGNsb3NlIGlzIHRocm93biwgbm90IHN3YWxsb3dlZCDigJRcbiAqIHRoZSBjYWxsZXIgc3VyZmFjZXMgaXQgKGEgbG9jayB0aGF0IGZhaWxlZCB0byByZWxlYXNlIG11c3QgYmUgdmlzaWJsZSkuXG4gKiBAcGFyYW0ge1J1bm5lckNsb3NlYWJsZUNvbmZpZ3VyYXRpb24gfCBudWxsfSBjb25maWd1cmF0aW9uIC0gQ29uZmlndXJhdGlvbiB3aG9zZSBjb25uZWN0aW9ucyB0byBjbG9zZTsgbnVsbCB3aGVuIG5vbmUgaXMgc2V0IChub3RoaW5nIHRvIGNsb3NlKS5cbiAqIEBwYXJhbSB7bnVtYmVyfSBbY2xvc2VUaW1lb3V0TXNdIC0gTWF4IHRpbWUgdG8gc3BlbmQgb24gZWFjaCBjbG9zZSBiZWZvcmUgZ2l2aW5nIHVwLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgb25jZSBib3RoIGNsb3NlcyBoYXZlIHNldHRsZWQ7IHJlamVjdHMgaWYgZWl0aGVyIGZhaWxlZC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsb3NlUnVubmVyQ29ubmVjdGlvbnMoY29uZmlndXJhdGlvbiwgY2xvc2VUaW1lb3V0TXMgPSBTSFVURE9XTl9DTE9TRV9USU1FT1VUX01TKSB7XG4gIGlmICghY29uZmlndXJhdGlvbikgcmV0dXJuXG5cbiAgY29uc3QgW2JlYWNvblJlc3VsdCwgZGF0YWJhc2VSZXN1bHRdID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFtcbiAgICB0aW1lb3V0KHt0aW1lb3V0OiBjbG9zZVRpbWVvdXRNc30sICgpID0+IGNvbmZpZ3VyYXRpb24uZGlzY29ubmVjdEJlYWNvbigpKSxcbiAgICB0aW1lb3V0KHt0aW1lb3V0OiBjbG9zZVRpbWVvdXRNc30sICgpID0+IGNvbmZpZ3VyYXRpb24uY2xvc2VEYXRhYmFzZUNvbm5lY3Rpb25zKCkpXG4gIF0pXG5cbiAgLyoqIEB0eXBlIHt1bmtub3duW119ICovXG4gIGNvbnN0IGVycm9ycyA9IFtdXG5cbiAgaWYgKGJlYWNvblJlc3VsdC5zdGF0dXMgPT0gXCJyZWplY3RlZFwiKSBlcnJvcnMucHVzaChiZWFjb25SZXN1bHQucmVhc29uKVxuICBpZiAoZGF0YWJhc2VSZXN1bHQuc3RhdHVzID09IFwicmVqZWN0ZWRcIikgZXJyb3JzLnB1c2goZGF0YWJhc2VSZXN1bHQucmVhc29uKVxuXG4gIGlmIChlcnJvcnMubGVuZ3RoID09IDEpIHRocm93IGVycm9yc1swXVxuICBpZiAoZXJyb3JzLmxlbmd0aCA+IDEpIHRocm93IG5ldyBBZ2dyZWdhdGVFcnJvcihlcnJvcnMsIFwiRmFpbGVkIHRvIGNsb3NlIGJhY2tncm91bmQtam9iIHJ1bm5lciBjb25uZWN0aW9ucyBvbiBzaHV0ZG93blwiKVxufVxuXG4vKipcbiAqIFRoZSBjdXJyZW50IGNvbmZpZ3VyYXRpb24sIG9yIG51bGwgd2hlbiBub25lIGhhcyBiZWVuIHNldCB5ZXQg4oCUIGEgcnVubmVyIHRoYXQgaXNcbiAqIHNpZ25hbGxlZCBiZWZvcmUgaXQgcnVucyBhbnkgam9iIGhvbGRzIG5vIGNvbm5lY3Rpb25zIChhbmQgbm8gbG9ja3MpIHRvIGNsb3NlLlxuICogT25seSB0aGF0IGV4cGVjdGVkIFwibm90IHNldCB5ZXRcIiBjYXNlIGlzIHRyZWF0ZWQgYXMgbnVsbDsgYW55IG90aGVyIGVycm9yIGlzIGEgcmVhbFxuICogZmF1bHQgYW5kIGlzIHJldGhyb3duIHJhdGhlciB0aGFuIG1hc2tlZC5cbiAqIEByZXR1cm5zIHtDb25maWd1cmF0aW9uIHwgbnVsbH0gLSBUaGUgY3VycmVudCBjb25maWd1cmF0aW9uLCBvciBudWxsIHdoZW4gbm9uZSBpcyBzZXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjdXJyZW50Q29uZmlndXJhdGlvbk9yTnVsbCgpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gQ29uZmlndXJhdGlvbi5jdXJyZW50KClcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBDdXJyZW50Q29uZmlndXJhdGlvbk5vdFNldEVycm9yKSByZXR1cm4gbnVsbFxuXG4gICAgdGhyb3cgZXJyb3JcbiAgfVxufVxuIl19
@@ -14,6 +14,13 @@ export default class VelociousConfiguration {
14
14
  * Close database connections promise.
15
15
  * @type {Promise<void> | null} */
16
16
  _closeDatabaseConnectionsPromise: Promise<void> | null;
17
+ /**
18
+ * Dedicated advisory-lock connections currently holding a lock. These are spawned
19
+ * outside the pools' tracked sets (so a hold-timeout lock survives pool checkouts),
20
+ * so `closeDatabaseConnections` would otherwise walk past them; tracking them here
21
+ * lets a shutdown close them and release the lock instead of orphaning it.
22
+ * @type {Set<import("./database/drivers/base.js").default>} */
23
+ _advisoryLockConnections: Set<import("./database/drivers/base.js").default>;
17
24
  _abilityResolver: import("./configuration-types.js").AbilityResolverType | undefined;
18
25
  _abilityResources: typeof import("./authorization/base-resource.js").default[];
19
26
  _autoload: boolean;
@@ -1310,6 +1317,28 @@ export default class VelociousConfiguration {
1310
1317
  * @returns {Promise<T>} - Resolves with the callback result.
1311
1318
  */
1312
1319
  ensureConnections<T>(optionsOrCallback: WithConnectionsOptionsType | WithConnectionsCallbackType<T>, callback?: WithConnectionsCallbackType<T>): Promise<T>;
1320
+ /**
1321
+ * Registers a dedicated connection that currently holds an advisory lock, so a
1322
+ * shutdown can close it and release the lock. See `_advisoryLockConnections`.
1323
+ * @param {import("./database/drivers/base.js").default} connection - The dedicated lock connection.
1324
+ * @returns {void}
1325
+ */
1326
+ registerAdvisoryLockConnection(connection: import("./database/drivers/base.js").default): void;
1327
+ /**
1328
+ * Unregisters a dedicated advisory-lock connection once its lock scope ends and the
1329
+ * connection has been (or is about to be) closed by its owner.
1330
+ * @param {import("./database/drivers/base.js").default} connection - The dedicated lock connection.
1331
+ * @returns {void}
1332
+ */
1333
+ unregisterAdvisoryLockConnection(connection: import("./database/drivers/base.js").default): void;
1334
+ /**
1335
+ * Closes every registered dedicated advisory-lock connection, ending its session so
1336
+ * the DB server releases the lock. Every connection is attempted before any failure
1337
+ * is surfaced, so one stuck close does not leave the others' locks held; a failure is
1338
+ * then thrown (never swallowed), aggregated when more than one connection failed.
1339
+ * @returns {Promise<void>} - Resolves once all have been closed; rejects if any failed.
1340
+ */
1341
+ _closeAdvisoryLockConnections(): Promise<void>;
1313
1342
  /**
1314
1343
  * Closes active database connections and clears global connections.
1315
1344
  * @returns {Promise<void>} - Resolves when complete.