velocious 1.0.590 → 1.0.591
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 +4 -0
- package/build/background-jobs/pooled-runner-broker-identity.js +76 -0
- package/build/background-jobs/pooled-runner-child.js +15 -5
- package/build/background-jobs/store.js +11 -14
- package/build/background-jobs/worker.js +17 -2
- package/build/database/pool/base.js +18 -1
- package/build/environment-handlers/base.js +8 -0
- package/build/environment-handlers/node.js +12 -0
- package/build/src/background-jobs/pooled-runner-broker-identity.d.ts +44 -0
- package/build/src/background-jobs/pooled-runner-broker-identity.d.ts.map +1 -0
- package/build/src/background-jobs/pooled-runner-broker-identity.js +76 -0
- package/build/src/background-jobs/pooled-runner-child.js +16 -6
- package/build/src/background-jobs/store.d.ts.map +1 -1
- package/build/src/background-jobs/store.js +12 -14
- package/build/src/background-jobs/worker.d.ts +6 -0
- package/build/src/background-jobs/worker.d.ts.map +1 -1
- package/build/src/background-jobs/worker.js +17 -3
- package/build/src/database/pool/base.d.ts +6 -0
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +18 -2
- package/build/src/environment-handlers/base.d.ts +12 -0
- package/build/src/environment-handlers/base.d.ts.map +1 -1
- package/build/src/environment-handlers/base.js +8 -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 +13 -1
- package/build/src/testing/shared-transaction-broker-client.d.ts +53 -0
- package/build/src/testing/shared-transaction-broker-client.d.ts.map +1 -0
- package/build/src/testing/shared-transaction-broker-client.js +105 -0
- package/build/src/testing/shared-transaction-broker.d.ts +153 -0
- package/build/src/testing/shared-transaction-broker.d.ts.map +1 -0
- package/build/src/testing/shared-transaction-broker.js +414 -0
- package/build/src/testing/shared-transaction-codec.d.ts +21 -0
- package/build/src/testing/shared-transaction-codec.d.ts.map +1 -0
- package/build/src/testing/shared-transaction-codec.js +114 -0
- package/build/src/testing/shared-transaction-connection-coordinator.d.ts +23 -0
- package/build/src/testing/shared-transaction-connection-coordinator.d.ts.map +1 -0
- package/build/src/testing/shared-transaction-connection-coordinator.js +36 -0
- package/build/src/testing/shared-transaction-proxy-driver.d.ts +42 -0
- package/build/src/testing/shared-transaction-proxy-driver.d.ts.map +1 -0
- package/build/src/testing/shared-transaction-proxy-driver.js +195 -0
- package/build/src/testing/test-runner.d.ts +20 -0
- package/build/src/testing/test-runner.d.ts.map +1 -1
- package/build/src/testing/test-runner.js +64 -3
- package/build/testing/shared-transaction-broker-client.js +107 -0
- package/build/testing/shared-transaction-broker.js +401 -0
- package/build/testing/shared-transaction-codec.js +110 -0
- package/build/testing/shared-transaction-connection-coordinator.js +38 -0
- package/build/testing/shared-transaction-proxy-driver.js +205 -0
- package/build/testing/test-runner.js +65 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -2
- package/src/background-jobs/pooled-runner-broker-identity.js +76 -0
- package/src/background-jobs/pooled-runner-child.js +15 -5
- package/src/background-jobs/store.js +11 -14
- package/src/background-jobs/worker.js +17 -2
- package/src/database/pool/base.js +18 -1
- package/src/environment-handlers/base.js +8 -0
- package/src/environment-handlers/node.js +12 -0
- package/src/testing/shared-transaction-broker-client.js +107 -0
- package/src/testing/shared-transaction-broker.js +401 -0
- package/src/testing/shared-transaction-codec.js +110 -0
- package/src/testing/shared-transaction-connection-coordinator.js +38 -0
- package/src/testing/shared-transaction-proxy-driver.js +205 -0
- package/src/testing/test-runner.js +65 -2
package/README.md
CHANGED
|
@@ -2072,6 +2072,10 @@ Tests default to a 60-second timeout. Override per test with `{timeoutSeconds: 5
|
|
|
2072
2072
|
|
|
2073
2073
|
Request tests share transaction-active, non-tenant database connections with their in-process HTTP handlers. Eligibility is evaluated when each request is dispatched, so a hook can start a transaction and issue a request in the same callback. This makes uncommitted setup visible to handlers while preserving rollback isolation. Without an active transaction, handlers use independent pooled connections, so concurrency and locking tests can opt out of transaction cleanup and exercise production-style connections. Shared connection state is scoped to the test lifecycle and cleared around each test. See [docs/testing-guidelines.md](docs/testing-guidelines.md#request-test-database-connections).
|
|
2074
2074
|
|
|
2075
|
+
Transactional tests also share active non-tenant connections with real forked, reusable pooled, and spawned background-job child runners through a per-attempt test-only loopback broker. Parent setup and child writes therefore occupy the same physical transaction and roll back together, including background-job persistence. Multiple configured databases route by identifier; tenant-only databases remain excluded. Tests using `{transaction: false, truncate: true}` retain ordinary independent physical connections for concurrency and locking coverage. See [docs/testing-guidelines.md](docs/testing-guidelines.md#request-test-database-connections).
|
|
2076
|
+
|
|
2077
|
+
Warm pooled children receive the active broker capability per job, discard retained proxy state when the capability changes, and fail closed if a transactional dispatch lacks coordinates. Child transaction/savepoint work holds a FIFO lease on the parent physical connection until the matching root release or rollback.
|
|
2078
|
+
|
|
2075
2079
|
# Writing a request test
|
|
2076
2080
|
|
|
2077
2081
|
First create a test file under something like the following path 'src/routes/accounts/create-test.js' with something like the following content:
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export default class PooledRunnerBrokerIdentity {
|
|
4
|
+
/**
|
|
5
|
+
* Creates a pooled runner identity coordinator.
|
|
6
|
+
* @param {{closeConnections: () => Promise<void>}} args - Connection cleanup hook.
|
|
7
|
+
*/
|
|
8
|
+
constructor({closeConnections}) {
|
|
9
|
+
this.closeConnections = closeConnections
|
|
10
|
+
/** @type {string | undefined} */
|
|
11
|
+
this.activeIdentity = undefined
|
|
12
|
+
/** @type {{identity: string, promise: Promise<void>} | undefined} */
|
|
13
|
+
this.pending = undefined
|
|
14
|
+
this.activeUsers = 0
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Gets the current prepared identity.
|
|
19
|
+
* @returns {string | undefined} - Current prepared identity.
|
|
20
|
+
*/
|
|
21
|
+
current() { return this.activeIdentity }
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Prepares one identity, sharing an in-flight same-identity rotation.
|
|
25
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} config - Dispatch configuration.
|
|
26
|
+
* @returns {Promise<void>} - Resolves after stale connections close.
|
|
27
|
+
*/
|
|
28
|
+
async prepare(config) {
|
|
29
|
+
const identity = JSON.stringify(config)
|
|
30
|
+
if (this.pending) {
|
|
31
|
+
if (this.pending.identity !== identity) throw new Error("Pooled runner cannot mix shared transaction broker capabilities concurrently")
|
|
32
|
+
return await this.pending.promise
|
|
33
|
+
}
|
|
34
|
+
if (this.activeIdentity === identity) return
|
|
35
|
+
if (this.activeUsers > 0) throw new Error("Pooled runner cannot mix shared transaction broker capabilities concurrently")
|
|
36
|
+
if (this.activeIdentity === undefined) {
|
|
37
|
+
this.activeIdentity = identity
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const promise = this.rotate(identity)
|
|
42
|
+
this.pending = {identity, promise}
|
|
43
|
+
try {
|
|
44
|
+
await promise
|
|
45
|
+
} finally {
|
|
46
|
+
this.pending = undefined
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Runs work while preventing a different identity from replacing its connections.
|
|
52
|
+
* @template T
|
|
53
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} config - Dispatch configuration.
|
|
54
|
+
* @param {() => Promise<T>} callback - Job callback.
|
|
55
|
+
* @returns {Promise<T>} - Job result.
|
|
56
|
+
*/
|
|
57
|
+
async run(config, callback) {
|
|
58
|
+
await this.prepare(config)
|
|
59
|
+
this.activeUsers++
|
|
60
|
+
try {
|
|
61
|
+
return await callback()
|
|
62
|
+
} finally {
|
|
63
|
+
this.activeUsers--
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Rotates retained connection state to an identity.
|
|
69
|
+
* @param {string} identity - Target identity.
|
|
70
|
+
* @returns {Promise<void>} - Resolves after rotation.
|
|
71
|
+
*/
|
|
72
|
+
async rotate(identity) {
|
|
73
|
+
await this.closeConnections()
|
|
74
|
+
this.activeIdentity = identity
|
|
75
|
+
}
|
|
76
|
+
}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import runJobPayload, { BackgroundJobPerformedFailure } from "./job-runner.js"
|
|
4
4
|
import { closeRunnerConnections, currentConfigurationOrNull } from "./runner-graceful-shutdown.js"
|
|
5
5
|
import setRunnerProcessTitle from "./runner-process-title.js"
|
|
6
|
+
import PooledRunnerBrokerIdentity from "./pooled-runner-broker-identity.js"
|
|
7
|
+
import { runWithSharedTransactionBrokerConfig } from "../testing/shared-transaction-proxy-driver.js"
|
|
6
8
|
|
|
7
9
|
const BASE_PROCESS_TITLE = "velocious background-jobs-runner"
|
|
8
10
|
|
|
@@ -33,6 +35,9 @@ async function shutdownRunner(exitCode) {
|
|
|
33
35
|
* @type {Set<string>}
|
|
34
36
|
*/
|
|
35
37
|
const runningJobIds = new Set()
|
|
38
|
+
const brokerIdentity = new PooledRunnerBrokerIdentity({
|
|
39
|
+
closeConnections: async () => await closeRunnerConnections(currentConfigurationOrNull())
|
|
40
|
+
})
|
|
36
41
|
|
|
37
42
|
/**
|
|
38
43
|
* Sets an aggregate process title from the current in-flight count. A child runs
|
|
@@ -51,11 +56,11 @@ function updateProcessTitle() {
|
|
|
51
56
|
/**
|
|
52
57
|
* Checks whether an IPC value is a runnable pooled job message.
|
|
53
58
|
* @param {ReturnType<typeof JSON.parse>} message - IPC message.
|
|
54
|
-
* @returns {message is {type: "job", payload: import("./types.js").BackgroundJobPayload & {id: string}}} - Whether this is a valid job message.
|
|
59
|
+
* @returns {message is {type: "job", payload: import("./types.js").BackgroundJobPayload & {id: string}, sharedTransactionBroker?: import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig}} - Whether this is a valid job message.
|
|
55
60
|
*/
|
|
56
61
|
function isJobMessage(message) {
|
|
57
62
|
if (!message || typeof message !== "object") return false
|
|
58
|
-
const record = /** @type {{type?: ReturnType<typeof JSON.parse>, payload?: ReturnType<typeof JSON.parse>}} */ (message)
|
|
63
|
+
const record = /** @type {{type?: ReturnType<typeof JSON.parse>, payload?: ReturnType<typeof JSON.parse>, sharedTransactionBroker?: ReturnType<typeof JSON.parse>}} */ (message)
|
|
59
64
|
|
|
60
65
|
return record.type === "job" && !!record.payload && typeof record.payload === "object" && typeof record.payload.id === "string"
|
|
61
66
|
}
|
|
@@ -95,11 +100,16 @@ function sendOutcome({jobId, acknowledged, status, error}) {
|
|
|
95
100
|
* per-job try/catch) ends the child, which the worker sees as an exit and
|
|
96
101
|
* reclaims for the whole in-flight set.
|
|
97
102
|
* @param {import("./types.js").BackgroundJobPayload & {id: string}} payload - Job payload.
|
|
103
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} sharedTransactionBroker - Per-job broker configuration.
|
|
98
104
|
* @returns {Promise<void>} - Resolves after reporting.
|
|
99
105
|
*/
|
|
100
|
-
async function runJob(payload) {
|
|
106
|
+
async function runJob(payload, sharedTransactionBroker) {
|
|
101
107
|
try {
|
|
102
|
-
const status = await
|
|
108
|
+
const status = await runWithSharedTransactionBrokerConfig(sharedTransactionBroker, async () => {
|
|
109
|
+
return await brokerIdentity.run(sharedTransactionBroker, async () => {
|
|
110
|
+
return await runJobPayload(payload, {closeConnections: false, manageProcessTitle: false})
|
|
111
|
+
})
|
|
112
|
+
})
|
|
103
113
|
await sendOutcome({jobId: payload.id, acknowledged: true, status})
|
|
104
114
|
} catch (error) {
|
|
105
115
|
if (error instanceof BackgroundJobPerformedFailure) {
|
|
@@ -125,7 +135,7 @@ function handleMessage(message) {
|
|
|
125
135
|
|
|
126
136
|
runningJobIds.add(message.payload.id)
|
|
127
137
|
updateProcessTitle()
|
|
128
|
-
void runJob(message.payload)
|
|
138
|
+
void runJob(message.payload, message.sharedTransactionBroker || {expected: false})
|
|
129
139
|
}
|
|
130
140
|
|
|
131
141
|
process.on("message", (message) => handleMessage(message))
|
|
@@ -6,6 +6,7 @@ import TableData from "../database/table-data/index.js"
|
|
|
6
6
|
import VelociousError from "../velocious-error.js"
|
|
7
7
|
import BackgroundJobRecord from "./job-record.js"
|
|
8
8
|
import normalizeBackgroundJobError from "./normalize-error.js"
|
|
9
|
+
import {coordinateSharedTransactionConnection} from "../testing/shared-transaction-connection-coordinator.js"
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* PreparedBackgroundJob type.
|
|
@@ -2376,23 +2377,19 @@ export default class BackgroundJobsStore {
|
|
|
2376
2377
|
* @returns {Promise<T>} - Callback result.
|
|
2377
2378
|
*/
|
|
2378
2379
|
async _withDb(callback) {
|
|
2379
|
-
const
|
|
2380
|
-
|
|
2381
|
-
/**
|
|
2382
|
-
* Defines result.
|
|
2383
|
-
* @type {T | undefined} */
|
|
2384
|
-
let result
|
|
2385
|
-
|
|
2386
|
-
await pool.withConnection({name: "Background jobs store"}, async (db) => {
|
|
2387
|
-
callbackCalled = true
|
|
2388
|
-
result = await callback(db)
|
|
2389
|
-
})
|
|
2380
|
+
const databaseIdentifier = this.getDatabaseIdentifier()
|
|
2381
|
+
const pool = this.configuration.getDatabasePool(databaseIdentifier)
|
|
2390
2382
|
|
|
2391
|
-
if (!
|
|
2392
|
-
|
|
2383
|
+
if (!pool.testSharedConnection()) {
|
|
2384
|
+
return await pool.withConnection({name: "Background jobs store"}, callback)
|
|
2393
2385
|
}
|
|
2394
2386
|
|
|
2395
|
-
return
|
|
2387
|
+
return await this.configuration.runWithTestSharedConnectionContexts(async () => {
|
|
2388
|
+
return await this.configuration.ensureConnections({databaseIdentifiers: [databaseIdentifier], name: "Background jobs store"}, async (dbs) => {
|
|
2389
|
+
const connection = dbs[databaseIdentifier]
|
|
2390
|
+
return await coordinateSharedTransactionConnection(connection, async () => await callback(connection))
|
|
2391
|
+
})
|
|
2392
|
+
})
|
|
2396
2393
|
}
|
|
2397
2394
|
|
|
2398
2395
|
/**
|
|
@@ -693,13 +693,26 @@ export default class BackgroundJobsWorker {
|
|
|
693
693
|
|
|
694
694
|
state.inflight.set(payload.id, {payload, resolve, timeoutTimer})
|
|
695
695
|
try {
|
|
696
|
-
child.send({type: "job", payload})
|
|
696
|
+
child.send({type: "job", payload, sharedTransactionBroker: this._pooledJobSharedTransactionBrokerConfig()})
|
|
697
697
|
} catch (error) {
|
|
698
698
|
void this._handlePooledChildFailure({child, error})
|
|
699
699
|
}
|
|
700
700
|
})
|
|
701
701
|
}
|
|
702
702
|
|
|
703
|
+
/**
|
|
704
|
+
* Captures the current test attempt's broker mode at dispatch time. A warm
|
|
705
|
+
* pooled child must never rely on its immutable fork-time environment.
|
|
706
|
+
* @returns {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} - Per-job broker configuration.
|
|
707
|
+
*/
|
|
708
|
+
_pooledJobSharedTransactionBrokerConfig() {
|
|
709
|
+
const serialized = process.env.VELOCIOUS_TEST_SHARED_TRANSACTION_BROKER
|
|
710
|
+
if (!serialized) return {expected: false}
|
|
711
|
+
|
|
712
|
+
const config = JSON.parse(Buffer.from(serialized, "base64url").toString("utf8"))
|
|
713
|
+
return {...config, expected: true}
|
|
714
|
+
}
|
|
715
|
+
|
|
703
716
|
/**
|
|
704
717
|
* Selects a pooled child to run the next job, or undefined when every non-retiring
|
|
705
718
|
* child is already full (the caller then lazily spawns one). Among children with a
|
|
@@ -792,7 +805,7 @@ export default class BackgroundJobsWorker {
|
|
|
792
805
|
const config = configuration.getBackgroundJobsConfig()
|
|
793
806
|
const child = fork(POOLED_RUNNER_ENTRY_PATH, [], {
|
|
794
807
|
cwd: configuration.getDirectory(), execArgv: [], stdio: ["ignore", "ignore", "ignore", "ipc"],
|
|
795
|
-
env: Object.assign({}, process.env, {VELOCIOUS_ENV: configuration.getEnvironment(), VELOCIOUS_BACKGROUND_JOBS_HOST: config.host, VELOCIOUS_BACKGROUND_JOBS_PORT: `${config.port}`})
|
|
808
|
+
env: Object.assign({}, process.env, {VELOCIOUS_BACKGROUND_JOB_CHILD: "1", VELOCIOUS_ENV: configuration.getEnvironment(), VELOCIOUS_BACKGROUND_JOBS_HOST: config.host, VELOCIOUS_BACKGROUND_JOBS_PORT: `${config.port}`})
|
|
796
809
|
})
|
|
797
810
|
this.pooledChildren.add(child)
|
|
798
811
|
this.inflightProcessChildren.add(child)
|
|
@@ -989,6 +1002,7 @@ export default class BackgroundJobsWorker {
|
|
|
989
1002
|
execArgv: [],
|
|
990
1003
|
stdio: ["ignore", "ignore", "ignore", "ipc"],
|
|
991
1004
|
env: Object.assign({}, process.env, {
|
|
1005
|
+
VELOCIOUS_BACKGROUND_JOB_CHILD: "1",
|
|
992
1006
|
VELOCIOUS_ENV: configuration.getEnvironment(),
|
|
993
1007
|
VELOCIOUS_BACKGROUND_JOBS_HOST: backgroundJobsConfig.host,
|
|
994
1008
|
VELOCIOUS_BACKGROUND_JOBS_PORT: `${backgroundJobsConfig.port}`
|
|
@@ -1216,6 +1230,7 @@ export default class BackgroundJobsWorker {
|
|
|
1216
1230
|
detached: true,
|
|
1217
1231
|
stdio: "ignore",
|
|
1218
1232
|
env: Object.assign({}, process.env, {
|
|
1233
|
+
VELOCIOUS_BACKGROUND_JOB_CHILD: "1",
|
|
1219
1234
|
VELOCIOUS_ENV: configuration.getEnvironment(),
|
|
1220
1235
|
VELOCIOUS_BACKGROUND_JOBS_HOST: backgroundJobsConfig.host,
|
|
1221
1236
|
VELOCIOUS_BACKGROUND_JOBS_PORT: `${backgroundJobsConfig.port}`,
|
|
@@ -193,6 +193,15 @@ class VelociousDatabasePoolBase {
|
|
|
193
193
|
return callback()
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Returns the connection registered for test-only in-process sharing.
|
|
198
|
+
* Base pools do not need a separate shared connection.
|
|
199
|
+
* @returns {import("../drivers/base.js").default | undefined} - Shared connection.
|
|
200
|
+
*/
|
|
201
|
+
testSharedConnection() {
|
|
202
|
+
return undefined
|
|
203
|
+
}
|
|
204
|
+
|
|
196
205
|
/**
|
|
197
206
|
* Returns whether the current connection is pinned to an execution context.
|
|
198
207
|
* @returns {boolean} - Whether the current connection can be reused by nested code.
|
|
@@ -349,7 +358,15 @@ class VelociousDatabasePoolBase {
|
|
|
349
358
|
|
|
350
359
|
if (!DriverClass) throw new Error("No driver class set in database pool or in given config")
|
|
351
360
|
|
|
352
|
-
const
|
|
361
|
+
const sharedConnection = config.tenantOnly
|
|
362
|
+
? undefined
|
|
363
|
+
: await this.configuration.getEnvironmentHandler().createTestSharedTransactionConnection({
|
|
364
|
+
DriverClass,
|
|
365
|
+
config,
|
|
366
|
+
configuration: this.configuration,
|
|
367
|
+
databaseIdentifier: this.identifier
|
|
368
|
+
})
|
|
369
|
+
const connection = sharedConnection || new DriverClass(config, this.configuration)
|
|
353
370
|
|
|
354
371
|
try {
|
|
355
372
|
await connection.connect()
|
|
@@ -19,6 +19,14 @@ import {validateTimeZone} from "../time-zone.js"
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
export default class VelociousEnvironmentHandlerBase {
|
|
22
|
+
/**
|
|
23
|
+
* Node test runtimes may replace a physical child connection with a broker
|
|
24
|
+
* proxy. Other environments never participate in this test-only protocol.
|
|
25
|
+
* @param {{DriverClass: typeof import("../database/drivers/base.js").default, config: import("../configuration-types.js").DatabaseConfigurationType, configuration: import("../configuration.js").default, databaseIdentifier: string}} _args - Connection details.
|
|
26
|
+
* @returns {Promise<import("../database/drivers/base.js").default | undefined>} - Optional proxy.
|
|
27
|
+
*/
|
|
28
|
+
async createTestSharedTransactionConnection(_args) { return undefined }
|
|
29
|
+
|
|
22
30
|
/**
|
|
23
31
|
* Mutable ambient tenant used by runtimes without async-context storage.
|
|
24
32
|
* @type {ReturnType<typeof JSON.parse> | undefined}
|
|
@@ -36,6 +36,7 @@ import InitializerFromRequireContext from "../database/initializer-from-require-
|
|
|
36
36
|
import toImportSpecifier from "../utils/to-import-specifier.js"
|
|
37
37
|
import {validateTimeZone} from "../time-zone.js"
|
|
38
38
|
import AttachmentPathSource from "./node/attachment-path-source.js"
|
|
39
|
+
import { createSharedTransactionProxyDriver, sharedTransactionBrokerConfig } from "../testing/shared-transaction-proxy-driver.js"
|
|
39
40
|
|
|
40
41
|
/**
|
|
41
42
|
* Defines this typedef.
|
|
@@ -63,6 +64,17 @@ function pathWithinAllowedPrefixes(filePath, allowedPathPrefixes) {
|
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
export default class VelociousEnvironmentHandlerNode extends Base{
|
|
67
|
+
/**
|
|
68
|
+
* Creates a test-only child proxy when TestRunner supplied an active broker.
|
|
69
|
+
* @param {{DriverClass: typeof import("../database/drivers/base.js").default, config: import("../configuration-types.js").DatabaseConfigurationType, configuration: import("../configuration.js").default, databaseIdentifier: string}} args - Connection details.
|
|
70
|
+
* @returns {Promise<import("../database/drivers/base.js").default | undefined>} - Optional proxy.
|
|
71
|
+
*/
|
|
72
|
+
async createTestSharedTransactionConnection({DriverClass, config, configuration, databaseIdentifier}) {
|
|
73
|
+
const brokerConfig = sharedTransactionBrokerConfig(databaseIdentifier)
|
|
74
|
+
if (!brokerConfig) return undefined
|
|
75
|
+
return createSharedTransactionProxyDriver(DriverClass, config, configuration, databaseIdentifier, brokerConfig)
|
|
76
|
+
}
|
|
77
|
+
|
|
66
78
|
/**
|
|
67
79
|
* Timezone async local storage.
|
|
68
80
|
* @type {import("node:async_hooks").AsyncLocalStorage<TimezoneStore> | undefined} */
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export default class PooledRunnerBrokerIdentity {
|
|
2
|
+
closeConnections: () => Promise<void>;
|
|
3
|
+
/** @type {string | undefined} */
|
|
4
|
+
activeIdentity: string | undefined;
|
|
5
|
+
/** @type {{identity: string, promise: Promise<void>} | undefined} */
|
|
6
|
+
pending: {
|
|
7
|
+
identity: string;
|
|
8
|
+
promise: Promise<void>;
|
|
9
|
+
} | undefined;
|
|
10
|
+
activeUsers: number;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a pooled runner identity coordinator.
|
|
13
|
+
* @param {{closeConnections: () => Promise<void>}} args - Connection cleanup hook.
|
|
14
|
+
*/
|
|
15
|
+
constructor({ closeConnections }: {
|
|
16
|
+
closeConnections: () => Promise<void>;
|
|
17
|
+
});
|
|
18
|
+
/**
|
|
19
|
+
* Gets the current prepared identity.
|
|
20
|
+
* @returns {string | undefined} - Current prepared identity.
|
|
21
|
+
*/
|
|
22
|
+
current(): string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Prepares one identity, sharing an in-flight same-identity rotation.
|
|
25
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} config - Dispatch configuration.
|
|
26
|
+
* @returns {Promise<void>} - Resolves after stale connections close.
|
|
27
|
+
*/
|
|
28
|
+
prepare(config: import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Runs work while preventing a different identity from replacing its connections.
|
|
31
|
+
* @template T
|
|
32
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} config - Dispatch configuration.
|
|
33
|
+
* @param {() => Promise<T>} callback - Job callback.
|
|
34
|
+
* @returns {Promise<T>} - Job result.
|
|
35
|
+
*/
|
|
36
|
+
run<T>(config: import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig, callback: () => Promise<T>): Promise<T>;
|
|
37
|
+
/**
|
|
38
|
+
* Rotates retained connection state to an identity.
|
|
39
|
+
* @param {string} identity - Target identity.
|
|
40
|
+
* @returns {Promise<void>} - Resolves after rotation.
|
|
41
|
+
*/
|
|
42
|
+
rotate(identity: string): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=pooled-runner-broker-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pooled-runner-broker-identity.d.ts","sourceRoot":"","sources":["../../../src/background-jobs/pooled-runner-broker-identity.js"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,0BAA0B;IAMtC,gBAAgB,QAHa,OAAO,CAAC,IAAI,CAAC;IAI/C,iCAAiC;IAC5B,cAAc,EADR,MAAM,GAAG,SAAS;IAE7B,qEAAqE;IAChE,OAAO,EADD;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;KAAC,GAAG,SAAS;IAE5D,WAAW;IAVlB;;;OAGG;IACH,YAAY,EAAC,gBAAgB,EAAC,EAFnB;QAAC,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;KAEnB,EAO7B;IAED;;;OAGG;IACH,OAAO,IAFM,MAAM,GAAG,SAAS,CAES;IAExC;;;;OAIG;IACG,OAAO,CAAC,MAAM,EAHT,OAAO,+CAA+C,EAAE,gCAG/C,GAFP,OAAO,CAAC,IAAI,CAAC,CAsBzB;IAED;;;;;;OAMG;IACG,GAAG,CALI,CAAC,EAKJ,MAAM,EAJL,OAAO,+CAA+C,EAAE,gCAInD,EAAE,QAAQ,EAHf,MAAM,OAAO,CAAC,CAAC,CAGA,GAFb,OAAO,CAAC,CAAC,CAAC,CAUtB;IAED;;;;OAIG;IACG,MAAM,CAAC,QAAQ,EAHV,MAGU,GAFR,OAAO,CAAC,IAAI,CAAC,CAKzB;CACF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
export default class PooledRunnerBrokerIdentity {
|
|
3
|
+
/**
|
|
4
|
+
* Creates a pooled runner identity coordinator.
|
|
5
|
+
* @param {{closeConnections: () => Promise<void>}} args - Connection cleanup hook.
|
|
6
|
+
*/
|
|
7
|
+
constructor({ closeConnections }) {
|
|
8
|
+
this.closeConnections = closeConnections;
|
|
9
|
+
/** @type {string | undefined} */
|
|
10
|
+
this.activeIdentity = undefined;
|
|
11
|
+
/** @type {{identity: string, promise: Promise<void>} | undefined} */
|
|
12
|
+
this.pending = undefined;
|
|
13
|
+
this.activeUsers = 0;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Gets the current prepared identity.
|
|
17
|
+
* @returns {string | undefined} - Current prepared identity.
|
|
18
|
+
*/
|
|
19
|
+
current() { return this.activeIdentity; }
|
|
20
|
+
/**
|
|
21
|
+
* Prepares one identity, sharing an in-flight same-identity rotation.
|
|
22
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} config - Dispatch configuration.
|
|
23
|
+
* @returns {Promise<void>} - Resolves after stale connections close.
|
|
24
|
+
*/
|
|
25
|
+
async prepare(config) {
|
|
26
|
+
const identity = JSON.stringify(config);
|
|
27
|
+
if (this.pending) {
|
|
28
|
+
if (this.pending.identity !== identity)
|
|
29
|
+
throw new Error("Pooled runner cannot mix shared transaction broker capabilities concurrently");
|
|
30
|
+
return await this.pending.promise;
|
|
31
|
+
}
|
|
32
|
+
if (this.activeIdentity === identity)
|
|
33
|
+
return;
|
|
34
|
+
if (this.activeUsers > 0)
|
|
35
|
+
throw new Error("Pooled runner cannot mix shared transaction broker capabilities concurrently");
|
|
36
|
+
if (this.activeIdentity === undefined) {
|
|
37
|
+
this.activeIdentity = identity;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const promise = this.rotate(identity);
|
|
41
|
+
this.pending = { identity, promise };
|
|
42
|
+
try {
|
|
43
|
+
await promise;
|
|
44
|
+
}
|
|
45
|
+
finally {
|
|
46
|
+
this.pending = undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Runs work while preventing a different identity from replacing its connections.
|
|
51
|
+
* @template T
|
|
52
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} config - Dispatch configuration.
|
|
53
|
+
* @param {() => Promise<T>} callback - Job callback.
|
|
54
|
+
* @returns {Promise<T>} - Job result.
|
|
55
|
+
*/
|
|
56
|
+
async run(config, callback) {
|
|
57
|
+
await this.prepare(config);
|
|
58
|
+
this.activeUsers++;
|
|
59
|
+
try {
|
|
60
|
+
return await callback();
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
this.activeUsers--;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Rotates retained connection state to an identity.
|
|
68
|
+
* @param {string} identity - Target identity.
|
|
69
|
+
* @returns {Promise<void>} - Resolves after rotation.
|
|
70
|
+
*/
|
|
71
|
+
async rotate(identity) {
|
|
72
|
+
await this.closeConnections();
|
|
73
|
+
this.activeIdentity = identity;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9vbGVkLXJ1bm5lci1icm9rZXItaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvYmFja2dyb3VuZC1qb2JzL3Bvb2xlZC1ydW5uZXItYnJva2VyLWlkZW50aXR5LmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLFlBQVk7QUFFWixNQUFNLENBQUMsT0FBTyxPQUFPLDBCQUEwQjtJQUM3Qzs7O09BR0c7SUFDSCxZQUFZLEVBQUMsZ0JBQWdCLEVBQUM7UUFDNUIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLGdCQUFnQixDQUFBO1FBQ3hDLGlDQUFpQztRQUNqQyxJQUFJLENBQUMsY0FBYyxHQUFHLFNBQVMsQ0FBQTtRQUMvQixxRUFBcUU7UUFDckUsSUFBSSxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUE7UUFDeEIsSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDLENBQUE7SUFDdEIsQ0FBQztJQUVEOzs7T0FHRztJQUNILE9BQU8sS0FBSyxPQUFPLElBQUksQ0FBQyxjQUFjLENBQUEsQ0FBQyxDQUFDO0lBRXhDOzs7O09BSUc7SUFDSCxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU07UUFDbEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUN2QyxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNqQixJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxLQUFLLFFBQVE7Z0JBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw4RUFBOEUsQ0FBQyxDQUFBO1lBQ3ZJLE9BQU8sTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQTtRQUNuQyxDQUFDO1FBQ0QsSUFBSSxJQUFJLENBQUMsY0FBYyxLQUFLLFFBQVE7WUFBRSxPQUFNO1FBQzVDLElBQUksSUFBSSxDQUFDLFdBQVcsR0FBRyxDQUFDO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyw4RUFBOEUsQ0FBQyxDQUFBO1FBQ3pILElBQUksSUFBSSxDQUFDLGNBQWMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN0QyxJQUFJLENBQUMsY0FBYyxHQUFHLFFBQVEsQ0FBQTtZQUM5QixPQUFNO1FBQ1IsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDckMsSUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFDLFFBQVEsRUFBRSxPQUFPLEVBQUMsQ0FBQTtRQUNsQyxJQUFJLENBQUM7WUFDSCxNQUFNLE9BQU8sQ0FBQTtRQUNmLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyxPQUFPLEdBQUcsU0FBUyxDQUFBO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsS0FBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsUUFBUTtRQUN4QixNQUFNLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDMUIsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFBO1FBQ2xCLElBQUksQ0FBQztZQUNILE9BQU8sTUFBTSxRQUFRLEVBQUUsQ0FBQTtRQUN6QixDQUFDO2dCQUFTLENBQUM7WUFDVCxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFDcEIsQ0FBQztJQUNILENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsS0FBSyxDQUFDLE1BQU0sQ0FBQyxRQUFRO1FBQ25CLE1BQU0sSUFBSSxDQUFDLGdCQUFnQixFQUFFLENBQUE7UUFDN0IsSUFBSSxDQUFDLGNBQWMsR0FBRyxRQUFRLENBQUE7SUFDaEMsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQHRzLWNoZWNrXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFBvb2xlZFJ1bm5lckJyb2tlcklkZW50aXR5IHtcbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBwb29sZWQgcnVubmVyIGlkZW50aXR5IGNvb3JkaW5hdG9yLlxuICAgKiBAcGFyYW0ge3tjbG9zZUNvbm5lY3Rpb25zOiAoKSA9PiBQcm9taXNlPHZvaWQ+fX0gYXJncyAtIENvbm5lY3Rpb24gY2xlYW51cCBob29rLlxuICAgKi9cbiAgY29uc3RydWN0b3Ioe2Nsb3NlQ29ubmVjdGlvbnN9KSB7XG4gICAgdGhpcy5jbG9zZUNvbm5lY3Rpb25zID0gY2xvc2VDb25uZWN0aW9uc1xuICAgIC8qKiBAdHlwZSB7c3RyaW5nIHwgdW5kZWZpbmVkfSAqL1xuICAgIHRoaXMuYWN0aXZlSWRlbnRpdHkgPSB1bmRlZmluZWRcbiAgICAvKiogQHR5cGUge3tpZGVudGl0eTogc3RyaW5nLCBwcm9taXNlOiBQcm9taXNlPHZvaWQ+fSB8IHVuZGVmaW5lZH0gKi9cbiAgICB0aGlzLnBlbmRpbmcgPSB1bmRlZmluZWRcbiAgICB0aGlzLmFjdGl2ZVVzZXJzID0gMFxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgcHJlcGFyZWQgaWRlbnRpdHkuXG4gICAqIEByZXR1cm5zIHtzdHJpbmcgfCB1bmRlZmluZWR9IC0gQ3VycmVudCBwcmVwYXJlZCBpZGVudGl0eS5cbiAgICovXG4gIGN1cnJlbnQoKSB7IHJldHVybiB0aGlzLmFjdGl2ZUlkZW50aXR5IH1cblxuICAvKipcbiAgICogUHJlcGFyZXMgb25lIGlkZW50aXR5LCBzaGFyaW5nIGFuIGluLWZsaWdodCBzYW1lLWlkZW50aXR5IHJvdGF0aW9uLlxuICAgKiBAcGFyYW0ge2ltcG9ydChcIi4uL3Rlc3Rpbmcvc2hhcmVkLXRyYW5zYWN0aW9uLXByb3h5LWRyaXZlci5qc1wiKS5TaGFyZWRUcmFuc2FjdGlvbkJyb2tlckpvYkNvbmZpZ30gY29uZmlnIC0gRGlzcGF0Y2ggY29uZmlndXJhdGlvbi5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgc3RhbGUgY29ubmVjdGlvbnMgY2xvc2UuXG4gICAqL1xuICBhc3luYyBwcmVwYXJlKGNvbmZpZykge1xuICAgIGNvbnN0IGlkZW50aXR5ID0gSlNPTi5zdHJpbmdpZnkoY29uZmlnKVxuICAgIGlmICh0aGlzLnBlbmRpbmcpIHtcbiAgICAgIGlmICh0aGlzLnBlbmRpbmcuaWRlbnRpdHkgIT09IGlkZW50aXR5KSB0aHJvdyBuZXcgRXJyb3IoXCJQb29sZWQgcnVubmVyIGNhbm5vdCBtaXggc2hhcmVkIHRyYW5zYWN0aW9uIGJyb2tlciBjYXBhYmlsaXRpZXMgY29uY3VycmVudGx5XCIpXG4gICAgICByZXR1cm4gYXdhaXQgdGhpcy5wZW5kaW5nLnByb21pc2VcbiAgICB9XG4gICAgaWYgKHRoaXMuYWN0aXZlSWRlbnRpdHkgPT09IGlkZW50aXR5KSByZXR1cm5cbiAgICBpZiAodGhpcy5hY3RpdmVVc2VycyA+IDApIHRocm93IG5ldyBFcnJvcihcIlBvb2xlZCBydW5uZXIgY2Fubm90IG1peCBzaGFyZWQgdHJhbnNhY3Rpb24gYnJva2VyIGNhcGFiaWxpdGllcyBjb25jdXJyZW50bHlcIilcbiAgICBpZiAodGhpcy5hY3RpdmVJZGVudGl0eSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmFjdGl2ZUlkZW50aXR5ID0gaWRlbnRpdHlcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLnJvdGF0ZShpZGVudGl0eSlcbiAgICB0aGlzLnBlbmRpbmcgPSB7aWRlbnRpdHksIHByb21pc2V9XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHByb21pc2VcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5wZW5kaW5nID0gdW5kZWZpbmVkXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJ1bnMgd29yayB3aGlsZSBwcmV2ZW50aW5nIGEgZGlmZmVyZW50IGlkZW50aXR5IGZyb20gcmVwbGFjaW5nIGl0cyBjb25uZWN0aW9ucy5cbiAgICogQHRlbXBsYXRlIFRcbiAgICogQHBhcmFtIHtpbXBvcnQoXCIuLi90ZXN0aW5nL3NoYXJlZC10cmFuc2FjdGlvbi1wcm94eS1kcml2ZXIuanNcIikuU2hhcmVkVHJhbnNhY3Rpb25Ccm9rZXJKb2JDb25maWd9IGNvbmZpZyAtIERpc3BhdGNoIGNvbmZpZ3VyYXRpb24uXG4gICAqIEBwYXJhbSB7KCkgPT4gUHJvbWlzZTxUPn0gY2FsbGJhY2sgLSBKb2IgY2FsbGJhY2suXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFQ+fSAtIEpvYiByZXN1bHQuXG4gICAqL1xuICBhc3luYyBydW4oY29uZmlnLCBjYWxsYmFjaykge1xuICAgIGF3YWl0IHRoaXMucHJlcGFyZShjb25maWcpXG4gICAgdGhpcy5hY3RpdmVVc2VycysrXG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBhd2FpdCBjYWxsYmFjaygpXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMuYWN0aXZlVXNlcnMtLVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSb3RhdGVzIHJldGFpbmVkIGNvbm5lY3Rpb24gc3RhdGUgdG8gYW4gaWRlbnRpdHkuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZGVudGl0eSAtIFRhcmdldCBpZGVudGl0eS5cbiAgICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgcm90YXRpb24uXG4gICAqL1xuICBhc3luYyByb3RhdGUoaWRlbnRpdHkpIHtcbiAgICBhd2FpdCB0aGlzLmNsb3NlQ29ubmVjdGlvbnMoKVxuICAgIHRoaXMuYWN0aXZlSWRlbnRpdHkgPSBpZGVudGl0eVxuICB9XG59XG4iXX0=
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import runJobPayload, { BackgroundJobPerformedFailure } from "./job-runner.js";
|
|
3
3
|
import { closeRunnerConnections, currentConfigurationOrNull } from "./runner-graceful-shutdown.js";
|
|
4
4
|
import setRunnerProcessTitle from "./runner-process-title.js";
|
|
5
|
+
import PooledRunnerBrokerIdentity from "./pooled-runner-broker-identity.js";
|
|
6
|
+
import { runWithSharedTransactionBrokerConfig } from "../testing/shared-transaction-proxy-driver.js";
|
|
5
7
|
const BASE_PROCESS_TITLE = "velocious background-jobs-runner";
|
|
6
8
|
setRunnerProcessTitle();
|
|
7
9
|
let shuttingDown = false;
|
|
@@ -27,6 +29,9 @@ async function shutdownRunner(exitCode) {
|
|
|
27
29
|
* @type {Set<string>}
|
|
28
30
|
*/
|
|
29
31
|
const runningJobIds = new Set();
|
|
32
|
+
const brokerIdentity = new PooledRunnerBrokerIdentity({
|
|
33
|
+
closeConnections: async () => await closeRunnerConnections(currentConfigurationOrNull())
|
|
34
|
+
});
|
|
30
35
|
/**
|
|
31
36
|
* Sets an aggregate process title from the current in-flight count. A child runs
|
|
32
37
|
* jobs concurrently, so a per-job title (which `runJobPayload` would snapshot and
|
|
@@ -42,12 +47,12 @@ function updateProcessTitle() {
|
|
|
42
47
|
/**
|
|
43
48
|
* Checks whether an IPC value is a runnable pooled job message.
|
|
44
49
|
* @param {ReturnType<typeof JSON.parse>} message - IPC message.
|
|
45
|
-
* @returns {message is {type: "job", payload: import("./types.js").BackgroundJobPayload & {id: string}}} - Whether this is a valid job message.
|
|
50
|
+
* @returns {message is {type: "job", payload: import("./types.js").BackgroundJobPayload & {id: string}, sharedTransactionBroker?: import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig}} - Whether this is a valid job message.
|
|
46
51
|
*/
|
|
47
52
|
function isJobMessage(message) {
|
|
48
53
|
if (!message || typeof message !== "object")
|
|
49
54
|
return false;
|
|
50
|
-
const record = /** @type {{type?: ReturnType<typeof JSON.parse>, payload?: ReturnType<typeof JSON.parse>}} */ (message);
|
|
55
|
+
const record = /** @type {{type?: ReturnType<typeof JSON.parse>, payload?: ReturnType<typeof JSON.parse>, sharedTransactionBroker?: ReturnType<typeof JSON.parse>}} */ (message);
|
|
51
56
|
return record.type === "job" && !!record.payload && typeof record.payload === "object" && typeof record.payload.id === "string";
|
|
52
57
|
}
|
|
53
58
|
/**
|
|
@@ -83,11 +88,16 @@ function sendOutcome({ jobId, acknowledged, status, error }) {
|
|
|
83
88
|
* per-job try/catch) ends the child, which the worker sees as an exit and
|
|
84
89
|
* reclaims for the whole in-flight set.
|
|
85
90
|
* @param {import("./types.js").BackgroundJobPayload & {id: string}} payload - Job payload.
|
|
91
|
+
* @param {import("../testing/shared-transaction-proxy-driver.js").SharedTransactionBrokerJobConfig} sharedTransactionBroker - Per-job broker configuration.
|
|
86
92
|
* @returns {Promise<void>} - Resolves after reporting.
|
|
87
93
|
*/
|
|
88
|
-
async function runJob(payload) {
|
|
94
|
+
async function runJob(payload, sharedTransactionBroker) {
|
|
89
95
|
try {
|
|
90
|
-
const status = await
|
|
96
|
+
const status = await runWithSharedTransactionBrokerConfig(sharedTransactionBroker, async () => {
|
|
97
|
+
return await brokerIdentity.run(sharedTransactionBroker, async () => {
|
|
98
|
+
return await runJobPayload(payload, { closeConnections: false, manageProcessTitle: false });
|
|
99
|
+
});
|
|
100
|
+
});
|
|
91
101
|
await sendOutcome({ jobId: payload.id, acknowledged: true, status });
|
|
92
102
|
}
|
|
93
103
|
catch (error) {
|
|
@@ -115,10 +125,10 @@ function handleMessage(message) {
|
|
|
115
125
|
return;
|
|
116
126
|
runningJobIds.add(message.payload.id);
|
|
117
127
|
updateProcessTitle();
|
|
118
|
-
void runJob(message.payload);
|
|
128
|
+
void runJob(message.payload, message.sharedTransactionBroker || { expected: false });
|
|
119
129
|
}
|
|
120
130
|
process.on("message", (message) => handleMessage(message));
|
|
121
131
|
process.once("disconnect", () => void shutdownRunner(0));
|
|
122
132
|
for (const signal of ["SIGTERM", "SIGINT"])
|
|
123
133
|
process.once(signal, () => void shutdownRunner(1));
|
|
124
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9vbGVkLXJ1bm5lci1jaGlsZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvcG9vbGVkLXJ1bm5lci1jaGlsZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLEVBQUUsRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzlFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLCtCQUErQixDQUFBO0FBQ2xHLE9BQU8scUJBQXFCLE1BQU0sMkJBQTJCLENBQUE7QUFFN0QsTUFBTSxrQkFBa0IsR0FBRyxrQ0FBa0MsQ0FBQTtBQUU3RCxxQkFBcUIsRUFBRSxDQUFBO0FBRXZCLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQTtBQUV4Qjs7Ozs7O0dBTUc7QUFDSCxLQUFLLFVBQVUsY0FBYyxDQUFDLFFBQVE7SUFDcEMsSUFBSSxZQUFZO1FBQUUsT0FBTTtJQUN4QixZQUFZLEdBQUcsSUFBSSxDQUFBO0lBRW5CLE1BQU0sc0JBQXNCLENBQUMsMEJBQTBCLEVBQUUsQ0FBQyxDQUFBO0lBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7QUFDeEIsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sYUFBYSxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7QUFFL0I7Ozs7Ozs7R0FPRztBQUNILFNBQVMsa0JBQWtCO0lBQ3pCLE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxJQUFJLENBQUE7SUFFaEMsT0FBTyxDQUFDLEtBQUssR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGtCQUFrQixLQUFLLEtBQUssSUFBSSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQTtBQUNwSCxDQUFD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QUcsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQyxDQUFBO0lBQ3JDLGtCQUFrQixFQUFFLENBQUE7SUFDcEIsS0FBSyxNQUFNLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBQzlCLENBQUM7QUFFRCxPQUFPLENBQUMsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7QUFDMUQsT0FBTyxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUUsR0FBRyxFQUFFLENBQUMsS0FBSyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUN4RCxLQUFLLE1BQU0sTUFBTSxJQUFJLENBQUMsU0FBUyxFQUFFLFFBQVEsQ0FBQztJQUFFLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuaW1wb3J0IHJ1bkpvYlBheWxvYWQsIHsgQmFja2dyb3VuZEpvYlBlcmZvcm1lZEZhaWx1cmUgfSBmcm9tIFwiLi9qb2ItcnVubmVyLmpzXCJcbmltcG9ydCB7IGNsb3NlUnVubmVyQ29ubmVjdGlvbnMsIGN1cnJlbnRDb25maWd1cmF0aW9uT3JOdWxsIH0gZnJvbSBcIi4vcnVubmVyLWdyYWNlZnVsLXNodXRkb3duLmpzXCJcbmltcG9ydCBzZXRSdW5uZXJQcm9jZXNzVGl0bGUgZnJvbSBcIi4vcnVubmVyLXByb2Nlc3MtdGl0bGUuanNcIlxuXG5jb25zdCBCQVNFX1BST0NFU1NfVElUTEUgPSBcInZlbG9jaW91cyBiYWNrZ3JvdW5kLWpvYnMtcnVubmVyXCJcblxuc2V0UnVubmVyUHJvY2Vzc1RpdGxlKClcblxubGV0IHNodXR0aW5nRG93biA9IGZhbHNlXG5cbi8qKlxuICogQ2xvc2VzIHRoZSBydW5uZXIncyBjb25uZWN0aW9ucyDigJQgcmVsZWFzaW5nIGFueSBhZHZpc29yeSBsb2NrIGEga2lsbGVkLW1pZC1wYXNzXG4gKiBqb2Igc3RpbGwgaG9sZHMg4oCUIGJlZm9yZSBleGl0aW5nLCBpbnN0ZWFkIG9mIGxlYXZpbmcgYSBoYWxmLW9wZW4gc2Vzc2lvbiB0aGF0XG4gKiBrZWVwcyB0aGUgbG9jayB1bnRpbCB0aGUgREIgc2VydmVyJ3MgYHdhaXRfdGltZW91dGAuXG4gKiBAcGFyYW0ge251bWJlcn0gZXhpdENvZGUgLSBQcm9jZXNzIGV4aXQgY29kZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICovXG5hc3luYyBmdW5jdGlvbiBzaHV0ZG93blJ1bm5lcihleGl0Q29kZSkge1xuICBpZiAoc2h1dHRpbmdEb3duKSByZXR1cm5cbiAgc2h1dHRpbmdEb3duID0gdHJ1ZVxuXG4gIGF3YWl0IGNsb3NlUnVubmVyQ29ubmVjdGlvbnMoY3VycmVudENvbmZpZ3VyYXRpb25Pck51bGwoKSlcbiAgcHJvY2Vzcy5leGl0KGV4aXRDb2RlKVxufVxuXG4vKipcbiAqIElkcyBvZiBqb2JzIGN1cnJlbnRseSBydW5uaW5nIGluIHRoaXMgY2hpbGQuIEEgcG9vbGVkIGNoaWxkIHJ1bnMgdXAgdG9cbiAqIGBwb29sZWRSdW5uZXJDb25jdXJyZW5jeWAgam9icyBhdCBvbmNlICh0aGUgd29ya2VyIG9ubHkgZGlzcGF0Y2hlcyB3aXRoaW4gdGhhdFxuICogYm91bmQpOyB0aGUgc2V0IGRlZHVwZXMgYSByZWRlbGl2ZXJlZCBqb2IgaWQgYW5kIGxldHMgZWFjaCBqb2Igc2V0dGxlXG4gKiBpbmRlcGVuZGVudGx5LlxuICogQHR5cGUge1NldDxzdHJpbmc+fVxuICovXG5jb25zdCBydW5uaW5nSm9iSWRzID0gbmV3IFNldCgpXG5cbi8qKlxuICogU2V0cyBhbiBhZ2dyZWdhdGUgcHJvY2VzcyB0aXRsZSBmcm9tIHRoZSBjdXJyZW50IGluLWZsaWdodCBjb3VudC4gQSBjaGlsZCBydW5zXG4gKiBqb2JzIGNvbmN1cnJlbnRseSwgc28gYSBwZXItam9iIHRpdGxlICh3aGljaCBgcnVuSm9iUGF5bG9hZGAgd291bGQgc25hcHNob3QgYW5kXG4gKiByZXN0b3JlIGFyb3VuZCBhIHNpbmdsZSBqb2IpIGNhbm5vdCByZXByZXNlbnQgdGhlIHByb2Nlc3Mg4oCUIGludGVybGVhdmVkXG4gKiBjb21wbGV0aW9ucyB3b3VsZCBsZWF2ZSBhIHN0YWxlIGxhYmVsLiBSZWNvbXB1dGluZyBmcm9tIGBydW5uaW5nSm9iSWRzLnNpemVgIGlzXG4gKiBjb25jdXJyZW5jeS1zYWZlIGFuZCBob25lc3Q6IGBwc2AvYHRvcGAgc2hvdyBob3cgbWFueSBqb2JzIHRoZSBjaGlsZCBpcyBydW5uaW5nLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVByb2Nlc3NUaXRsZSgpIHtcbiAgY29uc3QgY291bnQgPSBydW5uaW5nSm9iSWRzLnNpemVcblxuICBwcm9jZXNzLnRpdGxlID0gY291bnQgPiAwID8gYCR7QkFTRV9QUk9DRVNTX1RJVExFfTogJHtjb3VudH0gJHtjb3VudCA9PT0gMSA/IFwiam9iXCIgOiBcImpvYnNcIn1gIDogQkFTRV9QUk9DRVNTX1RJVExFXG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYW4gSVBDIHZhbHVlIGlzIGEgcnVubmFibGUgcG9vbGVkIGpvYiBtZXNzYWdlLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gbWVzc2FnZSAtIElQQyBtZXNzYWdlLlxuICogQHJldHVybnMge21lc3NhZ2UgaXMge3R5cGU6IFwiam9iXCIsIHBheWxvYWQ6IGltcG9ydChcIi4vdHlwZXMuanNcIikuQmFja2dyb3VuZEpvYlBheWxvYWQgJiB7aWQ6IHN0cmluZ319fSAtIFdoZXRoZXIgdGhpcyBpcyBhIHZhbGlkIGpvYiBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiBpc0pvYk1lc3NhZ2UobWVzc2FnZSkge1xuICBpZiAoIW1lc3NhZ2UgfHwgdHlwZW9mIG1lc3NhZ2UgIT09IFwib2JqZWN0XCIpIHJldHVybiBmYWxzZVxuICBjb25zdCByZWNvcmQgPSAvKiogQHR5cGUge3t0eXBlPzogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIHBheWxvYWQ/OiBSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn19ICovIChtZXNzYWdlKVxuXG4gIHJldHVybiByZWNvcmQudHlwZSA9PT0gXCJqb2JcIiAmJiAhIXJlY29yZC5wYXlsb2FkICYmIHR5cGVvZiByZWNvcmQucGF5bG9hZCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcmVjb3JkLnBheWxvYWQuaWQgPT09IFwic3RyaW5nXCJcbn1cblxuLyoqXG4gKiBTZW5kcyB0aGUgdGVybWluYWwgb3V0Y29tZSBhZnRlciB0aGUgbWFpbi9EQiByZXBvcnQgaGFzIGJlZW4gYWNrbm93bGVkZ2VkIG9yIHJlamVjdGVkLlxuICogQHBhcmFtIHtvYmplY3R9IGFyZ3MgLSBPdXRjb21lLlxuICogQHBhcmFtIHtzdHJpbmd9IGFyZ3Muam9iSWQgLSBKb2IgaWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IGFyZ3MuYWNrbm93bGVkZ2VkIC0gV2hldGhlciB0aGUgdGVybWluYWwgcmVwb3J0IHdhcyBhY2tub3dsZWRnZWQuXG4gKiBAcGFyYW0ge1wiY29tcGxldGVkXCIgfCBcImZhaWxlZFwiIHwgXCJyZXNjaGVkdWxlZFwifSBbYXJncy5zdGF0dXNdIC0gQWNrbm93bGVkZ2VkIG91dGNvbWUuXG4gKiBAcGFyYW0ge0Vycm9yfSBbYXJncy5lcnJvcl0gLSBSZXBvcnRpbmcgZXJyb3Igd2hlbiBhY2tub3dsZWRnZW1lbnQgd2FzIG5vdCBvYnRhaW5lZC5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fSAtIFJlc29sdmVzIGFmdGVyIElQQyBhY2NlcHRzIHRoZSBtZXNzYWdlLlxuICovXG5mdW5jdGlvbiBzZW5kT3V0Y29tZSh7am9iSWQsIGFja25vd2xlZGdlZCwgc3RhdHVzLCBlcnJvcn0pIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7XG4gICAgaWYgKCFwcm9jZXNzLnNlbmQpIHtcbiAgICAgIHJlc29sdmUodW5kZWZpbmVkKVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgcHJvY2Vzcy5zZW5kKHtcbiAgICAgIHR5cGU6IFwiam9iLW91dGNvbWVcIixcbiAgICAgIGpvYklkLFxuICAgICAgYWNrbm93bGVkZ2VkLFxuICAgICAgc3RhdHVzLFxuICAgICAgcnNzQnl0ZXM6IHByb2Nlc3MubWVtb3J5VXNhZ2UoKS5yc3MsXG4gICAgICBlcnJvcjogZXJyb3I/Lm1lc3NhZ2VcbiAgICB9LCAoKSA9PiByZXNvbHZlKHVuZGVmaW5lZCkpXG4gIH0pXG59XG5cbi8qKlxuICogUnVucyBvbmUgam9iIGNvbmN1cnJlbnRseSB3aXRoIGFueSBzaWJsaW5ncyBhbmQgcmVwb3J0cyBpdHMgb3duIHRlcm1pbmFsXG4gKiBvdXRjb21lLiBBIHNpbmdsZSBqb2IncyB1bmV4cGVjdGVkIGZhaWx1cmUgcmVwb3J0cyB0aGF0IGpvYiBmb3IgcmVjbGFtYXRpb25cbiAqIChgYWNrbm93bGVkZ2VkOiBmYWxzZWApIGJ1dCBkb2VzIE5PVCB0YWtlIGRvd24gdGhlIGNoaWxkIOKAlCBpdHMgY29uY3VycmVudFxuICogc2libGluZ3Mga2VlcCBydW5uaW5nLiBPbmx5IGEgcHJvY2Vzcy1sZXZlbCBmYXVsdCAod2hpY2ggZXNjYXBlcyBldmVyeVxuICogcGVyLWpvYiB0cnkvY2F0Y2gpIGVuZHMgdGhlIGNoaWxkLCB3aGljaCB0aGUgd29ya2VyIHNlZXMgYXMgYW4gZXhpdCBhbmRcbiAqIHJlY2xhaW1zIGZvciB0aGUgd2hvbGUgaW4tZmxpZ2h0IHNldC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi90eXBlcy5qc1wiKS5CYWNrZ3JvdW5kSm9iUGF5bG9hZCAmIHtpZDogc3RyaW5nfX0gcGF5bG9hZCAtIEpvYiBwYXlsb2FkLlxuICogQHJldHVybnMge1Byb21pc2U8dm9pZD59IC0gUmVzb2x2ZXMgYWZ0ZXIgcmVwb3J0aW5nLlxuICovXG5hc3luYyBmdW5jdGlvbiBydW5Kb2IocGF5bG9hZCkge1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHJ1bkpvYlBheWxvYWQocGF5bG9hZCwge2Nsb3NlQ29ubmVjdGlvbnM6IGZhbHNlLCBtYW5hZ2VQcm9jZXNzVGl0bGU6IGZhbHNlfSlcbiAgICBhd2FpdCBzZW5kT3V0Y29tZSh7am9iSWQ6IHBheWxvYWQuaWQsIGFja25vd2xlZGdlZDogdHJ1ZSwgc3RhdHVzfSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBCYWNrZ3JvdW5kSm9iUGVyZm9ybWVkRmFpbHVyZSkge1xuICAgICAgYXdhaXQgc2VuZE91dGNvbWUoe2pvYklkOiBwYXlsb2FkLmlkLCBhY2tub3dsZWRnZWQ6IHRydWUsIHN0YXR1czogXCJmYWlsZWRcIn0pXG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbnN0IHJlcG9ydEVycm9yID0gZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yIDogbmV3IEVycm9yKFN0cmluZyhlcnJvcikpXG4gICAgICBjb25zb2xlLmVycm9yKFwiUG9vbGVkIGJhY2tncm91bmQgam9iIHJ1bm5lciBmYWlsZWQgYmVmb3JlIHRlcm1pbmFsIGFja25vd2xlZGdlbWVudDpcIiwgcmVwb3J0RXJyb3IpXG4gICAgICBhd2FpdCBzZW5kT3V0Y29tZSh7am9iSWQ6IHBheWxvYWQuaWQsIGFja25vd2xlZGdlZDogZmFsc2UsIGVycm9yOiByZXBvcnRFcnJvcn0pXG4gICAgfVxuICB9IGZpbmFsbHkge1xuICAgIHJ1bm5pbmdKb2JJZHMuZGVsZXRlKHBheWxvYWQuaWQpXG4gICAgdXBkYXRlUHJvY2Vzc1RpdGxlKClcbiAgfVxufVxuXG4vKipcbiAqIEhhbmRsZXMgYSBqb2IgbWVzc2FnZSwgc3RhcnRpbmcgaXQgYWxvbmdzaWRlIGFueSBjb25jdXJyZW50IHNpYmxpbmdzLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gbWVzc2FnZSAtIElQQyBtZXNzYWdlLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIGhhbmRsZU1lc3NhZ2UobWVzc2FnZSkge1xuICBpZiAoIWlzSm9iTWVzc2FnZShtZXNzYWdlKSB8fCBydW5uaW5nSm9iSWRzLmhhcyhtZXNzYWdlLnBheWxvYWQuaWQpKSByZXR1cm5cblxuICBydW5uaW5nSm9iSWRzLmFkZChtZXNzYWdlLnBheWxvYWQuaWQpXG4gIHVwZGF0ZVByb2Nlc3NUaXRsZSgpXG4gIHZvaWQgcnVuSm9iKG1lc3NhZ2UucGF5bG9hZClcbn1cblxucHJvY2Vzcy5vbihcIm1lc3NhZ2VcIiwgKG1lc3NhZ2UpID0+IGhhbmRsZU1lc3NhZ2UobWVzc2FnZSkpXG5wcm9jZXNzLm9uY2UoXCJkaXNjb25uZWN0XCIsICgpID0+IHZvaWQgc2h1dGRvd25SdW5uZXIoMCkpXG5mb3IgKGNvbnN0IHNpZ25hbCBvZiBbXCJTSUdURVJNXCIsIFwiU0lHSU5UXCJdKSBwcm9jZXNzLm9uY2Uoc2lnbmFsLCAoKSA9PiB2b2lkIHNodXRkb3duUnVubmVyKDEpKVxuIl19
|
|
134
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicG9vbGVkLXJ1bm5lci1jaGlsZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9iYWNrZ3JvdW5kLWpvYnMvcG9vbGVkLXJ1bm5lci1jaGlsZC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVosT0FBTyxhQUFhLEVBQUUsRUFBRSw2QkFBNkIsRUFBRSxNQUFNLGlCQUFpQixDQUFBO0FBQzlFLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLCtCQUErQixDQUFBO0FBQ2xHLE9BQU8scUJBQXFCLE1BQU0sMkJBQTJCLENBQUE7QUFDN0QsT0FBTywwQkFBMEIsTUFBTSxvQ0FBb0MsQ0FBQTtBQUMzRSxPQUFPLEVBQUUsb0NBQW9DLEVBQUUsTUFBTSwrQ0FBK0MsQ0FBQTtBQUVwRyxNQUFNLGtCQUFrQixHQUFHLGtDQUFrQyxDQUFBO0FBRTdELHFCQUFxQixFQUFFLENBQUE7QUFFdkIsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFBO0FBRXhCOzs7Ozs7R0FNRztBQUNILEtBQUssVUFBVSxjQUFjLENBQUMsUUFBUTtJQUNwQyxJQUFJLFlBQVk7UUFBRSxPQUFNO0lBQ3hCLFlBQVksR0FBRyxJQUFJLENBQUE7SUFFbkIsTUFBTSxzQkFBc0IsQ0FBQywwQkFBMEIsRUFBRSxDQUFDLENBQUE7SUFDMUQsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtBQUN4QixDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxhQUFhLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtBQUMvQixNQUFNLGNBQWMsR0FBRyxJQUFJLDBCQUEwQixDQUFDO0lBQ3BELGdCQUFnQixFQUFFLEtBQUssSUFBSSxFQUFFLENBQUMsTUFBTSxzQkFBc0IsQ0FBQywwQkFBMEIsRUFBRSxDQUFDO0NBQ3pGLENBQUMsQ0FBQTtBQUVGOzs7Ozs7O0dBT0c7QUFDSCxTQUFTLGtCQUFrQjtJQUN6QixNQUFNLEtBQUss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aW1wb3J0IHJ1bkpvYlBheWxvYWQsIHsgQmFja2dyb3VuZEpvYlBlcmZvcm1lZEZhaWx1cmUgfSBmcm9tIFwiLi9qb2ItcnVubmVyLmpzXCJcbmltcG9ydCB7IGNsb3NlUnVubmVyQ29ubmVjdGlvbnMsIGN1cnJlbnRDb25maWd1cmF0aW9uT3JOdWxsIH0gZnJvbSBcIi4vcnVubmVyLWdyYWNlZnVsLXNodXRkb3duLmpzXCJcbmltcG9ydCBzZXRSdW5uZXJQcm9jZXNzVGl0bGUgZnJvbSBcIi4vcnVubmVyLXByb2Nlc3MtdGl0bGUuanNcIlxuaW1wb3J0IFBvb2xlZFJ1bm5lckJyb2tlcklkZW50aXR5IGZyb20gXCIuL3Bvb2xlZC1ydW5uZXItYnJva2VyLWlkZW50aXR5LmpzXCJcbmltcG9ydCB7IHJ1bldpdGhTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZyB9IGZyb20gXCIuLi90ZXN0aW5nL3NoYXJlZC10cmFuc2FjdGlvbi1wcm94eS1kcml2ZXIuanNcIlxuXG5jb25zdCBCQVNFX1BST0NFU1NfVElUTEUgPSBcInZlbG9jaW91cyBiYWNrZ3JvdW5kLWpvYnMtcnVubmVyXCJcblxuc2V0UnVubmVyUHJvY2Vzc1RpdGxlKClcblxubGV0IHNodXR0aW5nRG93biA9IGZhbHNlXG5cbi8qKlxuICogQ2xvc2VzIHRoZSBydW5uZXIncyBjb25uZWN0aW9ucyDigJQgcmVsZWFzaW5nIGFueSBhZHZpc29yeSBsb2NrIGEga2lsbGVkLW1pZC1wYXNzXG4gKiBqb2Igc3RpbGwgaG9sZHMg4oCUIGJlZm9yZSBleGl0aW5nLCBpbnN0ZWFkIG9mIGxlYXZpbmcgYSBoYWxmLW9wZW4gc2Vzc2lvbiB0aGF0XG4gKiBrZWVwcyB0aGUgbG9jayB1bnRpbCB0aGUgREIgc2VydmVyJ3MgYHdhaXRfdGltZW91dGAuXG4gKiBAcGFyYW0ge251bWJlcn0gZXhpdENvZGUgLSBQcm9jZXNzIGV4aXQgY29kZS5cbiAqIEByZXR1cm5zIHtQcm9taXNlPHZvaWQ+fVxuICovXG5hc3luYyBmdW5jdGlvbiBzaHV0ZG93blJ1bm5lcihleGl0Q29kZSkge1xuICBpZiAoc2h1dHRpbmdEb3duKSByZXR1cm5cbiAgc2h1dHRpbmdEb3duID0gdHJ1ZVxuXG4gIGF3YWl0IGNsb3NlUnVubmVyQ29ubmVjdGlvbnMoY3VycmVudENvbmZpZ3VyYXRpb25Pck51bGwoKSlcbiAgcHJvY2Vzcy5leGl0KGV4aXRDb2RlKVxufVxuXG4vKipcbiAqIElkcyBvZiBqb2JzIGN1cnJlbnRseSBydW5uaW5nIGluIHRoaXMgY2hpbGQuIEEgcG9vbGVkIGNoaWxkIHJ1bnMgdXAgdG9cbiAqIGBwb29sZWRSdW5uZXJDb25jdXJyZW5jeWAgam9icyBhdCBvbmNlICh0aGUgd29ya2VyIG9ubHkgZGlzcGF0Y2hlcyB3aXRoaW4gdGhhdFxuICogYm91bmQpOyB0aGUgc2V0IGRlZHVwZXMgYSByZWRlbGl2ZXJlZCBqb2IgaWQgYW5kIGxldHMgZWFjaCBqb2Igc2V0dGxlXG4gKiBpbmRlcGVuZGVudGx5LlxuICogQHR5cGUge1NldDxzdHJpbmc+fVxuICovXG5jb25zdCBydW5uaW5nSm9iSWRzID0gbmV3IFNldCgpXG5jb25zdCBicm9rZXJJZGVudGl0eSA9IG5ldyBQb29sZWRSdW5uZXJCcm9rZXJJZGVudGl0eSh7XG4gIGNsb3NlQ29ubmVjdGlvbnM6IGFzeW5jICgpID0+IGF3YWl0IGNsb3NlUnVubmVyQ29ubmVjdGlvbnMoY3VycmVudENvbmZpZ3VyYXRpb25Pck51bGwoKSlcbn0pXG5cbi8qKlxuICogU2V0cyBhbiBhZ2dyZWdhdGUgcHJvY2VzcyB0aXRsZSBmcm9tIHRoZSBjdXJyZW50IGluLWZsaWdodCBjb3VudC4gQSBjaGlsZCBydW5zXG4gKiBqb2JzIGNvbmN1cnJlbnRseSwgc28gYSBwZXItam9iIHRpdGxlICh3aGljaCBgcnVuSm9iUGF5bG9hZGAgd291bGQgc25hcHNob3QgYW5kXG4gKiByZXN0b3JlIGFyb3VuZCBhIHNpbmdsZSBqb2IpIGNhbm5vdCByZXByZXNlbnQgdGhlIHByb2Nlc3Mg4oCUIGludGVybGVhdmVkXG4gKiBjb21wbGV0aW9ucyB3b3VsZCBsZWF2ZSBhIHN0YWxlIGxhYmVsLiBSZWNvbXB1dGluZyBmcm9tIGBydW5uaW5nSm9iSWRzLnNpemVgIGlzXG4gKiBjb25jdXJyZW5jeS1zYWZlIGFuZCBob25lc3Q6IGBwc2AvYHRvcGAgc2hvdyBob3cgbWFueSBqb2JzIHRoZSBjaGlsZCBpcyBydW5uaW5nLlxuICogQHJldHVybnMge3ZvaWR9XG4gKi9cbmZ1bmN0aW9uIHVwZGF0ZVByb2Nlc3NUaXRsZSgpIHtcbiAgY29uc3QgY291bnQgPSBydW5uaW5nSm9iSWRzLnNpemVcblxuICBwcm9jZXNzLnRpdGxlID0gY291bnQgPiAwID8gYCR7QkFTRV9QUk9DRVNTX1RJVExFfTogJHtjb3VudH0gJHtjb3VudCA9PT0gMSA/IFwiam9iXCIgOiBcImpvYnNcIn1gIDogQkFTRV9QUk9DRVNTX1RJVExFXG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgYW4gSVBDIHZhbHVlIGlzIGEgcnVubmFibGUgcG9vbGVkIGpvYiBtZXNzYWdlLlxuICogQHBhcmFtIHtSZXR1cm5UeXBlPHR5cGVvZiBKU09OLnBhcnNlPn0gbWVzc2FnZSAtIElQQyBtZXNzYWdlLlxuICogQHJldHVybnMge21lc3NhZ2UgaXMge3R5cGU6IFwiam9iXCIsIHBheWxvYWQ6IGltcG9ydChcIi4vdHlwZXMuanNcIikuQmFja2dyb3VuZEpvYlBheWxvYWQgJiB7aWQ6IHN0cmluZ30sIHNoYXJlZFRyYW5zYWN0aW9uQnJva2VyPzogaW1wb3J0KFwiLi4vdGVzdGluZy9zaGFyZWQtdHJhbnNhY3Rpb24tcHJveHktZHJpdmVyLmpzXCIpLlNoYXJlZFRyYW5zYWN0aW9uQnJva2VySm9iQ29uZmlnfX0gLSBXaGV0aGVyIHRoaXMgaXMgYSB2YWxpZCBqb2IgbWVzc2FnZS5cbiAqL1xuZnVuY3Rpb24gaXNKb2JNZXNzYWdlKG1lc3NhZ2UpIHtcbiAgaWYgKCFtZXNzYWdlIHx8IHR5cGVvZiBtZXNzYWdlICE9PSBcIm9iamVjdFwiKSByZXR1cm4gZmFsc2VcbiAgY29uc3QgcmVjb3JkID0gLyoqIEB0eXBlIHt7dHlwZT86IFJldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+LCBwYXlsb2FkPzogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT4sIHNoYXJlZFRyYW5zYWN0aW9uQnJva2VyPzogUmV0dXJuVHlwZTx0eXBlb2YgSlNPTi5wYXJzZT59fSAqLyAobWVzc2FnZSlcblxuICByZXR1cm4gcmVjb3JkLnR5cGUgPT09IFwiam9iXCIgJiYgISFyZWNvcmQucGF5bG9hZCAmJiB0eXBlb2YgcmVjb3JkLnBheWxvYWQgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIHJlY29yZC5wYXlsb2FkLmlkID09PSBcInN0cmluZ1wiXG59XG5cbi8qKlxuICogU2VuZHMgdGhlIHRlcm1pbmFsIG91dGNvbWUgYWZ0ZXIgdGhlIG1haW4vREIgcmVwb3J0IGhhcyBiZWVuIGFja25vd2xlZGdlZCBvciByZWplY3RlZC5cbiAqIEBwYXJhbSB7b2JqZWN0fSBhcmdzIC0gT3V0Y29tZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSBhcmdzLmpvYklkIC0gSm9iIGlkLlxuICogQHBhcmFtIHtib29sZWFufSBhcmdzLmFja25vd2xlZGdlZCAtIFdoZXRoZXIgdGhlIHRlcm1pbmFsIHJlcG9ydCB3YXMgYWNrbm93bGVkZ2VkLlxuICogQHBhcmFtIHtcImNvbXBsZXRlZFwiIHwgXCJmYWlsZWRcIiB8IFwicmVzY2hlZHVsZWRcIn0gW2FyZ3Muc3RhdHVzXSAtIEFja25vd2xlZGdlZCBvdXRjb21lLlxuICogQHBhcmFtIHtFcnJvcn0gW2FyZ3MuZXJyb3JdIC0gUmVwb3J0aW5nIGVycm9yIHdoZW4gYWNrbm93bGVkZ2VtZW50IHdhcyBub3Qgb2J0YWluZWQuXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciBJUEMgYWNjZXB0cyB0aGUgbWVzc2FnZS5cbiAqL1xuZnVuY3Rpb24gc2VuZE91dGNvbWUoe2pvYklkLCBhY2tub3dsZWRnZWQsIHN0YXR1cywgZXJyb3J9KSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4ge1xuICAgIGlmICghcHJvY2Vzcy5zZW5kKSB7XG4gICAgICByZXNvbHZlKHVuZGVmaW5lZClcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHByb2Nlc3Muc2VuZCh7XG4gICAgICB0eXBlOiBcImpvYi1vdXRjb21lXCIsXG4gICAgICBqb2JJZCxcbiAgICAgIGFja25vd2xlZGdlZCxcbiAgICAgIHN0YXR1cyxcbiAgICAgIHJzc0J5dGVzOiBwcm9jZXNzLm1lbW9yeVVzYWdlKCkucnNzLFxuICAgICAgZXJyb3I6IGVycm9yPy5tZXNzYWdlXG4gICAgfSwgKCkgPT4gcmVzb2x2ZSh1bmRlZmluZWQpKVxuICB9KVxufVxuXG4vKipcbiAqIFJ1bnMgb25lIGpvYiBjb25jdXJyZW50bHkgd2l0aCBhbnkgc2libGluZ3MgYW5kIHJlcG9ydHMgaXRzIG93biB0ZXJtaW5hbFxuICogb3V0Y29tZS4gQSBzaW5nbGUgam9iJ3MgdW5leHBlY3RlZCBmYWlsdXJlIHJlcG9ydHMgdGhhdCBqb2IgZm9yIHJlY2xhbWF0aW9uXG4gKiAoYGFja25vd2xlZGdlZDogZmFsc2VgKSBidXQgZG9lcyBOT1QgdGFrZSBkb3duIHRoZSBjaGlsZCDigJQgaXRzIGNvbmN1cnJlbnRcbiAqIHNpYmxpbmdzIGtlZXAgcnVubmluZy4gT25seSBhIHByb2Nlc3MtbGV2ZWwgZmF1bHQgKHdoaWNoIGVzY2FwZXMgZXZlcnlcbiAqIHBlci1qb2IgdHJ5L2NhdGNoKSBlbmRzIHRoZSBjaGlsZCwgd2hpY2ggdGhlIHdvcmtlciBzZWVzIGFzIGFuIGV4aXQgYW5kXG4gKiByZWNsYWltcyBmb3IgdGhlIHdob2xlIGluLWZsaWdodCBzZXQuXG4gKiBAcGFyYW0ge2ltcG9ydChcIi4vdHlwZXMuanNcIikuQmFja2dyb3VuZEpvYlBheWxvYWQgJiB7aWQ6IHN0cmluZ319IHBheWxvYWQgLSBKb2IgcGF5bG9hZC5cbiAqIEBwYXJhbSB7aW1wb3J0KFwiLi4vdGVzdGluZy9zaGFyZWQtdHJhbnNhY3Rpb24tcHJveHktZHJpdmVyLmpzXCIpLlNoYXJlZFRyYW5zYWN0aW9uQnJva2VySm9iQ29uZmlnfSBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlciAtIFBlci1qb2IgYnJva2VyIGNvbmZpZ3VyYXRpb24uXG4gKiBAcmV0dXJucyB7UHJvbWlzZTx2b2lkPn0gLSBSZXNvbHZlcyBhZnRlciByZXBvcnRpbmcuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJ1bkpvYihwYXlsb2FkLCBzaGFyZWRUcmFuc2FjdGlvbkJyb2tlcikge1xuICB0cnkge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IHJ1bldpdGhTaGFyZWRUcmFuc2FjdGlvbkJyb2tlckNvbmZpZyhzaGFyZWRUcmFuc2FjdGlvbkJyb2tlciwgYXN5bmMgKCkgPT4ge1xuICAgICAgcmV0dXJuIGF3YWl0IGJyb2tlcklkZW50aXR5LnJ1bihzaGFyZWRUcmFuc2FjdGlvbkJyb2tlciwgYXN5bmMgKCkgPT4ge1xuICAgICAgICByZXR1cm4gYXdhaXQgcnVuSm9iUGF5bG9hZChwYXlsb2FkLCB7Y2xvc2VDb25uZWN0aW9uczogZmFsc2UsIG1hbmFnZVByb2Nlc3NUaXRsZTogZmFsc2V9KVxuICAgICAgfSlcbiAgICB9KVxuICAgIGF3YWl0IHNlbmRPdXRjb21lKHtqb2JJZDogcGF5bG9hZC5pZCwgYWNrbm93bGVkZ2VkOiB0cnVlLCBzdGF0dXN9KVxuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIEJhY2tncm91bmRKb2JQZXJmb3JtZWRGYWlsdXJlKSB7XG4gICAgICBhd2FpdCBzZW5kT3V0Y29tZSh7am9iSWQ6IHBheWxvYWQuaWQsIGFja25vd2xlZGdlZDogdHJ1ZSwgc3RhdHVzOiBcImZhaWxlZFwifSlcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcmVwb3J0RXJyb3IgPSBlcnJvciBpbnN0YW5jZW9mIEVycm9yID8gZXJyb3IgOiBuZXcgRXJyb3IoU3RyaW5nKGVycm9yKSlcbiAgICAgIGNvbnNvbGUuZXJyb3IoXCJQb29sZWQgYmFja2dyb3VuZCBqb2IgcnVubmVyIGZhaWxlZCBiZWZvcmUgdGVybWluYWwgYWNrbm93bGVkZ2VtZW50OlwiLCByZXBvcnRFcnJvcilcbiAgICAgIGF3YWl0IHNlbmRPdXRjb21lKHtqb2JJZDogcGF5bG9hZC5pZCwgYWNrbm93bGVkZ2VkOiBmYWxzZSwgZXJyb3I6IHJlcG9ydEVycm9yfSlcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgcnVubmluZ0pvYklkcy5kZWxldGUocGF5bG9hZC5pZClcbiAgICB1cGRhdGVQcm9jZXNzVGl0bGUoKVxuICB9XG59XG5cbi8qKlxuICogSGFuZGxlcyBhIGpvYiBtZXNzYWdlLCBzdGFydGluZyBpdCBhbG9uZ3NpZGUgYW55IGNvbmN1cnJlbnQgc2libGluZ3MuXG4gKiBAcGFyYW0ge1JldHVyblR5cGU8dHlwZW9mIEpTT04ucGFyc2U+fSBtZXNzYWdlIC0gSVBDIG1lc3NhZ2UuXG4gKiBAcmV0dXJucyB7dm9pZH1cbiAqL1xuZnVuY3Rpb24gaGFuZGxlTWVzc2FnZShtZXNzYWdlKSB7XG4gIGlmICghaXNKb2JNZXNzYWdlKG1lc3NhZ2UpIHx8IHJ1bm5pbmdKb2JJZHMuaGFzKG1lc3NhZ2UucGF5bG9hZC5pZCkpIHJldHVyblxuXG4gIHJ1bm5pbmdKb2JJZHMuYWRkKG1lc3NhZ2UucGF5bG9hZC5pZClcbiAgdXBkYXRlUHJvY2Vzc1RpdGxlKClcbiAgdm9pZCBydW5Kb2IobWVzc2FnZS5wYXlsb2FkLCBtZXNzYWdlLnNoYXJlZFRyYW5zYWN0aW9uQnJva2VyIHx8IHtleHBlY3RlZDogZmFsc2V9KVxufVxuXG5wcm9jZXNzLm9uKFwibWVzc2FnZVwiLCAobWVzc2FnZSkgPT4gaGFuZGxlTWVzc2FnZShtZXNzYWdlKSlcbnByb2Nlc3Mub25jZShcImRpc2Nvbm5lY3RcIiwgKCkgPT4gdm9pZCBzaHV0ZG93blJ1bm5lcigwKSlcbmZvciAoY29uc3Qgc2lnbmFsIG9mIFtcIlNJR1RFUk1cIiwgXCJTSUdJTlRcIl0pIHByb2Nlc3Mub25jZShzaWduYWwsICgpID0+IHZvaWQgc2h1dGRvd25SdW5uZXIoMSkpXG4iXX0=
|