velocious 1.0.462 → 1.0.463
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/build/configuration.js +33 -8
- package/build/database/pool/async-tracked-multi-connection.js +66 -1
- package/build/database/pool/base.js +8 -0
- package/build/http-server/client/index.js +1 -1
- package/build/http-server/client/request-runner.js +1 -1
- package/build/http-server/worker-handler/index.js +3 -2
- package/build/routes/resolver.js +1 -1
- package/build/src/configuration.d.ts +13 -0
- package/build/src/configuration.d.ts.map +1 -1
- package/build/src/configuration.js +32 -10
- package/build/src/database/pool/async-tracked-multi-connection.d.ts +18 -0
- package/build/src/database/pool/async-tracked-multi-connection.d.ts.map +1 -1
- package/build/src/database/pool/async-tracked-multi-connection.js +62 -2
- package/build/src/database/pool/base.d.ts +5 -0
- package/build/src/database/pool/base.d.ts.map +1 -1
- package/build/src/database/pool/base.js +8 -1
- package/build/src/http-server/client/index.js +2 -2
- package/build/src/http-server/client/request-runner.js +2 -2
- package/build/src/http-server/worker-handler/index.d.ts.map +1 -1
- package/build/src/http-server/worker-handler/index.js +4 -3
- package/build/src/routes/resolver.d.ts.map +1 -1
- package/build/src/routes/resolver.js +2 -2
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/configuration.js +33 -8
- package/src/database/pool/async-tracked-multi-connection.js +66 -1
- package/src/database/pool/base.js +8 -0
- package/src/http-server/client/index.js +1 -1
- package/src/http-server/client/request-runner.js +1 -1
- package/src/http-server/worker-handler/index.js +3 -2
- package/src/routes/resolver.js +1 -1
- package/build/src/utils/ensure-error.d.ts +0 -7
- package/build/src/utils/ensure-error.d.ts.map +0 -1
- package/build/src/utils/ensure-error.js +0 -15
- package/build/utils/ensure-error.js +0 -15
- package/src/utils/ensure-error.js +0 -15
package/src/configuration.js
CHANGED
|
@@ -2440,10 +2440,26 @@ export default class VelociousConfiguration {
|
|
|
2440
2440
|
* @type {{[key: string]: import("./database/drivers/base.js").default}} */
|
|
2441
2441
|
const dbs = {}
|
|
2442
2442
|
|
|
2443
|
+
return await this.withDatabaseIdentifierConnections({
|
|
2444
|
+
callback: actualWithConnectionsCallback,
|
|
2445
|
+
dbs,
|
|
2446
|
+
identifiers: this.getDatabaseIdentifiers(),
|
|
2447
|
+
name,
|
|
2448
|
+
stackLabel: "withConnections"
|
|
2449
|
+
})
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
/**
|
|
2453
|
+
* Runs callback with database connections for the requested identifiers.
|
|
2454
|
+
* @template T
|
|
2455
|
+
* @param {{callback: WithConnectionsCallbackType<T>, dbs: Record<string, import("./database/drivers/base.js").default>, identifiers: string[], name: string, stackLabel: string}} args - Connection scope details.
|
|
2456
|
+
* @returns {Promise<T>} - Resolves with the callback result.
|
|
2457
|
+
*/
|
|
2458
|
+
async withDatabaseIdentifierConnections({callback, dbs, identifiers, name, stackLabel}) {
|
|
2443
2459
|
const stack = Error().stack
|
|
2444
2460
|
const actualCallback = async () => {
|
|
2445
|
-
return await withTrackedStack(stack ||
|
|
2446
|
-
return await
|
|
2461
|
+
return await withTrackedStack(stack || stackLabel, async () => {
|
|
2462
|
+
return await callback(dbs)
|
|
2447
2463
|
})
|
|
2448
2464
|
}
|
|
2449
2465
|
|
|
@@ -2452,7 +2468,7 @@ export default class VelociousConfiguration {
|
|
|
2452
2468
|
* @type {() => Promise<T>} */
|
|
2453
2469
|
let runRequest = actualCallback
|
|
2454
2470
|
|
|
2455
|
-
for (const identifier of
|
|
2471
|
+
for (const identifier of identifiers) {
|
|
2456
2472
|
let actualRunRequest = runRequest
|
|
2457
2473
|
|
|
2458
2474
|
const nextRunRequest = async () => {
|
|
@@ -2545,14 +2561,23 @@ export default class VelociousConfiguration {
|
|
|
2545
2561
|
if (!actualWithConnectionsCallback) throw new Error("ensureConnections requires a callback")
|
|
2546
2562
|
|
|
2547
2563
|
const dbs = this.getCurrentConnections()
|
|
2548
|
-
const
|
|
2549
|
-
|
|
2564
|
+
const missingIdentifiers = this.getDatabaseIdentifiers().filter((identifier) => {
|
|
2565
|
+
if (!dbs[identifier]) return true
|
|
2566
|
+
|
|
2567
|
+
return !this.getDatabasePool(identifier).hasCurrentConnectionContext()
|
|
2568
|
+
})
|
|
2550
2569
|
|
|
2551
|
-
if (
|
|
2570
|
+
if (missingIdentifiers.length === 0) {
|
|
2552
2571
|
return await actualWithConnectionsCallback(dbs)
|
|
2553
|
-
} else {
|
|
2554
|
-
return await this.withConnections({name}, actualWithConnectionsCallback)
|
|
2555
2572
|
}
|
|
2573
|
+
|
|
2574
|
+
return await this.withDatabaseIdentifierConnections({
|
|
2575
|
+
callback: actualWithConnectionsCallback,
|
|
2576
|
+
dbs,
|
|
2577
|
+
identifiers: missingIdentifiers,
|
|
2578
|
+
name,
|
|
2579
|
+
stackLabel: "ensureConnections"
|
|
2580
|
+
})
|
|
2556
2581
|
}
|
|
2557
2582
|
|
|
2558
2583
|
/**
|
|
@@ -523,8 +523,65 @@ export default class VelociousDatabasePoolAsyncTrackedMultiConnection extends Ba
|
|
|
523
523
|
*/
|
|
524
524
|
pendingCheckoutTimeoutError(checkout) {
|
|
525
525
|
const checkoutName = checkout.options.name ? ` Checkout name: ${JSON.stringify(checkout.options.name)}.` : ""
|
|
526
|
+
const diagnostics = this.pendingCheckoutTimeoutDiagnostics(checkout)
|
|
526
527
|
|
|
527
|
-
return new Error(`Timed out after ${checkout.timeoutMillis}ms waiting for database connection checkout from pool "${this.identifier}".${checkoutName}`)
|
|
528
|
+
return new Error(`Timed out after ${checkout.timeoutMillis}ms waiting for database connection checkout from pool "${this.identifier}".${checkoutName} ${diagnostics}`)
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/**
|
|
532
|
+
* Builds sanitized diagnostics for a checkout timeout.
|
|
533
|
+
* @param {PendingCheckout} checkout - Timed-out checkout.
|
|
534
|
+
* @returns {string} - Pool state summary.
|
|
535
|
+
*/
|
|
536
|
+
pendingCheckoutTimeoutDiagnostics(checkout) {
|
|
537
|
+
const snapshot = this.getDebugSnapshot()
|
|
538
|
+
const connectionSummaries = snapshot.connections
|
|
539
|
+
.map((connection) => this.pendingCheckoutTimeoutConnectionSummary(connection))
|
|
540
|
+
.join(", ")
|
|
541
|
+
const pendingSummaries = (snapshot.pendingCheckouts || [])
|
|
542
|
+
.map((pendingCheckout) => this.pendingCheckoutTimeoutPendingSummary(pendingCheckout))
|
|
543
|
+
.join(", ")
|
|
544
|
+
const waitedForMs = Math.max(0, Date.now() - checkout.enqueuedAt)
|
|
545
|
+
|
|
546
|
+
return `Pool state: max=${this.maxConnections() ?? "unbounded"}, inUse=${snapshot.inUseCount}, idle=${snapshot.idleCount}, pending=${snapshot.pendingCheckoutCount}, spawning=${snapshot.connectionsBeingSpawned}, timedOutWaitingForMs=${waitedForMs}, holders=[${connectionSummaries}], waiting=[${pendingSummaries}].`
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Builds a sanitized connection summary for checkout timeout diagnostics.
|
|
551
|
+
* @param {Record<string, ?>} connection - Connection debug snapshot.
|
|
552
|
+
* @returns {string} - Sanitized connection state.
|
|
553
|
+
*/
|
|
554
|
+
pendingCheckoutTimeoutConnectionSummary(connection) {
|
|
555
|
+
const parts = [`state=${connection.state}`]
|
|
556
|
+
|
|
557
|
+
if (connection.checkoutName) parts.push(`checkout=${JSON.stringify(connection.checkoutName)}`)
|
|
558
|
+
if (typeof connection.checkedOutForMs === "number") parts.push(`checkedOutForMs=${connection.checkedOutForMs}`)
|
|
559
|
+
if (typeof connection.idleForMs === "number") parts.push(`idleForMs=${connection.idleForMs}`)
|
|
560
|
+
if (typeof connection.openTransactions === "number") parts.push(`openTransactions=${connection.openTransactions}`)
|
|
561
|
+
|
|
562
|
+
const activeQuery = connection.activeQuery
|
|
563
|
+
|
|
564
|
+
if (activeQuery && typeof activeQuery === "object" && !Array.isArray(activeQuery)) {
|
|
565
|
+
const runningMs = (/** @type {Record<string, ?>} */ (activeQuery)).runningMs
|
|
566
|
+
|
|
567
|
+
if (typeof runningMs === "number") parts.push(`activeQueryMs=${runningMs}`)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
return `{${parts.join(" ")}}`
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
/**
|
|
574
|
+
* Builds a sanitized pending checkout summary for checkout timeout diagnostics.
|
|
575
|
+
* @param {import("./base.js").DatabasePoolPendingCheckoutDebugSnapshot} pendingCheckout - Waiting checkout snapshot.
|
|
576
|
+
* @returns {string} - Sanitized pending checkout state.
|
|
577
|
+
*/
|
|
578
|
+
pendingCheckoutTimeoutPendingSummary(pendingCheckout) {
|
|
579
|
+
const parts = [`index=${pendingCheckout.index}`, `waitingForMs=${pendingCheckout.waitingForMs}`]
|
|
580
|
+
|
|
581
|
+
if (pendingCheckout.checkoutName) parts.push(`checkout=${JSON.stringify(pendingCheckout.checkoutName)}`)
|
|
582
|
+
if (pendingCheckout.remainingTimeoutMs !== null) parts.push(`remainingTimeoutMs=${pendingCheckout.remainingTimeoutMs}`)
|
|
583
|
+
|
|
584
|
+
return `{${parts.join(" ")}}`
|
|
528
585
|
}
|
|
529
586
|
|
|
530
587
|
/**
|
|
@@ -763,6 +820,14 @@ export default class VelociousDatabasePoolAsyncTrackedMultiConnection extends Ba
|
|
|
763
820
|
return this.getCurrentConnection()
|
|
764
821
|
}
|
|
765
822
|
|
|
823
|
+
/**
|
|
824
|
+
* Returns whether this pool has a real async context for the current connection.
|
|
825
|
+
* @returns {boolean} - Whether nested code can reuse the current connection context.
|
|
826
|
+
*/
|
|
827
|
+
hasCurrentConnectionContext() {
|
|
828
|
+
return this.asyncLocalStorage.getStore() !== undefined
|
|
829
|
+
}
|
|
830
|
+
|
|
766
831
|
/**
|
|
767
832
|
* Runs get debug snapshot.
|
|
768
833
|
* @returns {import("./base.js").DatabasePoolDebugSnapshot} - Diagnostic snapshot for this pool.
|
|
@@ -144,6 +144,14 @@ class VelociousDatabasePoolBase {
|
|
|
144
144
|
return this.getCurrentConnection()
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Returns whether the current connection is pinned to an execution context.
|
|
149
|
+
* @returns {boolean} - Whether the current connection can be reused by nested code.
|
|
150
|
+
*/
|
|
151
|
+
hasCurrentConnectionContext() {
|
|
152
|
+
return true
|
|
153
|
+
}
|
|
154
|
+
|
|
147
155
|
/**
|
|
148
156
|
* Runs without current connection context.
|
|
149
157
|
* @template T
|
|
@@ -4,8 +4,8 @@ import crypto from "crypto"
|
|
|
4
4
|
import fs from "node:fs/promises"
|
|
5
5
|
import {createReadStream} from "node:fs"
|
|
6
6
|
import {digg} from "diggerize"
|
|
7
|
+
import {ensureError} from "typanic"
|
|
7
8
|
import EventEmitter from "../../utils/event-emitter.js"
|
|
8
|
-
import ensureError from "../../utils/ensure-error.js"
|
|
9
9
|
import Logger from "../../logger.js"
|
|
10
10
|
import Request from "./request.js"
|
|
11
11
|
import RequestRunner from "./request-runner.js"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import {ensureError} from "typanic"
|
|
3
4
|
import BacktraceCleaner from "../../utils/backtrace-cleaner-node.js"
|
|
4
|
-
import ensureError from "../../utils/ensure-error.js"
|
|
5
5
|
import EventEmitter from "../../utils/event-emitter.js"
|
|
6
6
|
import Logger from "../../logger.js"
|
|
7
7
|
import RequestTiming from "./request-timing.js"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// @ts-check
|
|
2
2
|
|
|
3
|
+
import {ensureError} from "typanic"
|
|
3
4
|
import Logger from "../../logger.js"
|
|
4
5
|
import {Worker} from "worker_threads"
|
|
5
|
-
import ensureError from "../../utils/ensure-error.js"
|
|
6
6
|
import websocketEventsHost from "../websocket-events-host.js"
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -109,7 +109,8 @@ export default class VelociousHttpServerWorker {
|
|
|
109
109
|
onWorkerError = (error) => {
|
|
110
110
|
this.logger.error(`Velocious worker ${this.workerCount} error`, error)
|
|
111
111
|
void this._closeAllClients()
|
|
112
|
-
|
|
112
|
+
// Preserve Error instances for the original backtrace while wrapping non-Error throwables.
|
|
113
|
+
throw ensureError(error)
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
/**
|
package/src/routes/resolver.js
CHANGED
|
@@ -4,9 +4,9 @@ import {dirname} from "path"
|
|
|
4
4
|
import {fileURLToPath} from "url"
|
|
5
5
|
import fs from "fs/promises"
|
|
6
6
|
import * as inflection from "inflection"
|
|
7
|
+
import {ensureError} from "typanic"
|
|
7
8
|
import Logger from "../logger.js"
|
|
8
9
|
import UploadedFile from "../http-server/client/uploaded-file/uploaded-file.js"
|
|
9
|
-
import ensureError from "../utils/ensure-error.js"
|
|
10
10
|
import toImportSpecifier from "../utils/to-import-specifier.js"
|
|
11
11
|
|
|
12
12
|
/**
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ensure-error.d.ts","sourceRoot":"","sources":["../../../src/utils/ensure-error.js"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,2CAHW,OAAC,GACC,KAAK,CAQjB"}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
/**
|
|
3
|
-
* Runs ensure error.
|
|
4
|
-
* @param {?} error - Error instance.
|
|
5
|
-
* @returns {Error} - The error.
|
|
6
|
-
*/
|
|
7
|
-
export default function ensureError(error) {
|
|
8
|
-
if (error instanceof Error) {
|
|
9
|
-
return error;
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
return new Error(`Unknown error type ${typeof error}: ${error}`);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW5zdXJlLWVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL2Vuc3VyZS1lcnJvci5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZO0FBRVo7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxPQUFPLFVBQVUsV0FBVyxDQUFDLEtBQUs7SUFDdkMsSUFBSSxLQUFLLFlBQVksS0FBSyxFQUFFLENBQUM7UUFDM0IsT0FBTyxLQUFLLENBQUE7SUFDZCxDQUFDO1NBQU0sQ0FBQztRQUNOLE9BQU8sSUFBSSxLQUFLLENBQUMsc0JBQXNCLE9BQU8sS0FBSyxLQUFLLEtBQUssRUFBRSxDQUFDLENBQUE7SUFDbEUsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtY2hlY2tcblxuLyoqXG4gKiBSdW5zIGVuc3VyZSBlcnJvci5cbiAqIEBwYXJhbSB7P30gZXJyb3IgLSBFcnJvciBpbnN0YW5jZS5cbiAqIEByZXR1cm5zIHtFcnJvcn0gLSBUaGUgZXJyb3IuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGVuc3VyZUVycm9yKGVycm9yKSB7XG4gIGlmIChlcnJvciBpbnN0YW5jZW9mIEVycm9yKSB7XG4gICAgcmV0dXJuIGVycm9yXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBFcnJvcihgVW5rbm93biBlcnJvciB0eXBlICR7dHlwZW9mIGVycm9yfTogJHtlcnJvcn1gKVxuICB9XG59XG5cbiJdfQ==
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Runs ensure error.
|
|
5
|
-
* @param {?} error - Error instance.
|
|
6
|
-
* @returns {Error} - The error.
|
|
7
|
-
*/
|
|
8
|
-
export default function ensureError(error) {
|
|
9
|
-
if (error instanceof Error) {
|
|
10
|
-
return error
|
|
11
|
-
} else {
|
|
12
|
-
return new Error(`Unknown error type ${typeof error}: ${error}`)
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Runs ensure error.
|
|
5
|
-
* @param {?} error - Error instance.
|
|
6
|
-
* @returns {Error} - The error.
|
|
7
|
-
*/
|
|
8
|
-
export default function ensureError(error) {
|
|
9
|
-
if (error instanceof Error) {
|
|
10
|
-
return error
|
|
11
|
-
} else {
|
|
12
|
-
return new Error(`Unknown error type ${typeof error}: ${error}`)
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
|