@slonik/driver 48.12.3 → 48.13.1
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 +1 -1
- package/dist/Logger.js +2 -2
- package/dist/factories/createDriverFactory.d.ts +17 -17
- package/dist/factories/createDriverFactory.d.ts.map +1 -1
- package/dist/factories/createDriverFactory.js +91 -68
- package/dist/factories/createDriverFactory.js.map +1 -1
- package/dist/factories/createDriverFactory.test.js +50 -3
- package/dist/factories/createDriverFactory.test.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +37 -41
- package/src/Logger.ts +2 -2
- package/src/factories/createDriverFactory.test.ts +57 -3
- package/src/factories/createDriverFactory.ts +118 -99
- package/src/index.ts +1 -1
package/README.md
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
|
|
3
3
|
Slonik driver is an abstraction layer that provides a consistent API for interacting using different PostgreSQL clients.
|
|
4
4
|
|
|
5
|
-
This package is made available for developers who wish to create their own Slonik driver.
|
|
5
|
+
This package is made available for developers who wish to create their own Slonik driver.
|
package/dist/Logger.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type { Field } from
|
|
2
|
-
import EventEmitter from
|
|
3
|
-
import type { Readable } from
|
|
4
|
-
import type { ConnectionOptions as TlsConnectionOptions } from
|
|
5
|
-
import type { StrictEventEmitter } from
|
|
1
|
+
import type { Field } from "@slonik/types";
|
|
2
|
+
import EventEmitter from "node:events";
|
|
3
|
+
import type { Readable } from "node:stream";
|
|
4
|
+
import type { ConnectionOptions as TlsConnectionOptions } from "node:tls";
|
|
5
|
+
import type { StrictEventEmitter } from "strict-event-emitter-types";
|
|
6
6
|
export type Driver = {
|
|
7
7
|
createClient: () => Promise<DriverClient>;
|
|
8
8
|
};
|
|
@@ -10,11 +10,11 @@ export type DriverClient = {
|
|
|
10
10
|
acquire: () => void;
|
|
11
11
|
destroy: () => Promise<void>;
|
|
12
12
|
id: () => string;
|
|
13
|
-
off: DriverClientEventEmitter[
|
|
14
|
-
on: DriverClientEventEmitter[
|
|
13
|
+
off: DriverClientEventEmitter["off"];
|
|
14
|
+
on: DriverClientEventEmitter["on"];
|
|
15
15
|
query: (query: string, values?: unknown[], queryOptions?: DriverQueryOptions) => Promise<DriverQueryResult>;
|
|
16
16
|
release: () => Promise<void>;
|
|
17
|
-
removeListener: DriverClientEventEmitter[
|
|
17
|
+
removeListener: DriverClientEventEmitter["removeListener"];
|
|
18
18
|
state: () => DriverClientState;
|
|
19
19
|
stream: (query: string, values?: unknown[]) => DriverStream<DriverStreamResult>;
|
|
20
20
|
};
|
|
@@ -25,20 +25,20 @@ export type DriverClientEventEmitter = StrictEventEmitter<EventEmitter, {
|
|
|
25
25
|
notice: (event: DriverNotice) => void;
|
|
26
26
|
release: () => void;
|
|
27
27
|
}>;
|
|
28
|
-
export type DriverClientState =
|
|
29
|
-
export type DriverCommand =
|
|
28
|
+
export type DriverClientState = "ACQUIRED" | "DESTROYED" | "IDLE" | "PENDING_DESTROY" | "PENDING_RELEASE";
|
|
29
|
+
export type DriverCommand = "COPY" | "DELETE" | "INSERT" | "SELECT" | "UPDATE";
|
|
30
30
|
export type DriverConfiguration = {
|
|
31
|
-
readonly connectionTimeout:
|
|
31
|
+
readonly connectionTimeout: "DISABLE_TIMEOUT" | number;
|
|
32
32
|
readonly connectionUri: string;
|
|
33
33
|
readonly gracefulTerminationTimeout?: number;
|
|
34
|
-
readonly idleInTransactionSessionTimeout:
|
|
35
|
-
readonly idleTimeout?:
|
|
36
|
-
readonly maximumConnectionAge?: number;
|
|
34
|
+
readonly idleInTransactionSessionTimeout: "DISABLE_TIMEOUT" | number;
|
|
35
|
+
readonly idleTimeout?: "DISABLE_TIMEOUT" | number;
|
|
36
|
+
readonly maximumConnectionAge?: "DISABLE_TIMEOUT" | number;
|
|
37
37
|
readonly maximumPoolSize?: number;
|
|
38
38
|
readonly minimumPoolSize?: number;
|
|
39
39
|
readonly resetConnection?: (connection: BasicConnection) => Promise<void>;
|
|
40
40
|
readonly ssl?: TlsConnectionOptions;
|
|
41
|
-
readonly statementTimeout:
|
|
41
|
+
readonly statementTimeout: "DISABLE_TIMEOUT" | number;
|
|
42
42
|
readonly typeParsers: readonly DriverTypeParser[];
|
|
43
43
|
};
|
|
44
44
|
export type DriverEventEmitter = StrictEventEmitter<EventEmitter, {
|
|
@@ -64,9 +64,9 @@ export type DriverQueryResult = {
|
|
|
64
64
|
readonly rowCount: null | number;
|
|
65
65
|
readonly rows: Array<Record<string, unknown>>;
|
|
66
66
|
};
|
|
67
|
-
export interface DriverStream<T> extends Omit<Readable,
|
|
67
|
+
export interface DriverStream<T> extends Omit<Readable, "on" | typeof Symbol.asyncIterator> {
|
|
68
68
|
[Symbol.asyncIterator]: () => AsyncIterableIterator<StreamDataEvent<T>>;
|
|
69
|
-
on: ((event:
|
|
69
|
+
on: ((event: "data", listener: (chunk: StreamDataEvent<T>) => void) => this) & ((event: string | symbol, listener: (...args: any[]) => void) => this);
|
|
70
70
|
}
|
|
71
71
|
export type DriverStreamResult = {
|
|
72
72
|
readonly fields: DriverField[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDriverFactory.d.ts","sourceRoot":"","sources":["../../src/factories/createDriverFactory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,YAAY,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,IAAI,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAE1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAQrE,MAAM,MAAM,MAAM,GAAG;IACnB,YAAY,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,EAAE,EAAE,MAAM,MAAM,CAAC;IACjB,GAAG,EAAE,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACrC,EAAE,EAAE,wBAAwB,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,EAAE,CACL,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,YAAY,CAAC,EAAE,kBAAkB,KAC9B,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,cAAc,EAAE,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;IAC3D,KAAK,EAAE,MAAM,iBAAiB,CAAC;IAC/B,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"createDriverFactory.d.ts","sourceRoot":"","sources":["../../src/factories/createDriverFactory.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,YAAY,MAAM,aAAa,CAAC;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,iBAAiB,IAAI,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAE1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAQrE,MAAM,MAAM,MAAM,GAAG;IACnB,YAAY,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,EAAE,EAAE,MAAM,MAAM,CAAC;IACjB,GAAG,EAAE,wBAAwB,CAAC,KAAK,CAAC,CAAC;IACrC,EAAE,EAAE,wBAAwB,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,EAAE,CACL,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,YAAY,CAAC,EAAE,kBAAkB,KAC9B,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,cAAc,EAAE,wBAAwB,CAAC,gBAAgB,CAAC,CAAC;IAC3D,KAAK,EAAE,MAAM,iBAAiB,CAAC;IAC/B,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,YAAY,CAAC,kBAAkB,CAAC,CAAC;CACjF,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,kBAAkB,CACvD,YAAY,EACZ;IACE,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,MAAM,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CACF,CAAC;AAEF,MAAM,MAAM,iBAAiB,GACzB,UAAU,GACV,WAAW,GACX,MAAM,GACN,iBAAiB,GACjB,iBAAiB,CAAC;AAEtB,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAE/E,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,0BAA0B,CAAC,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,+BAA+B,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACrE,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IAClD,QAAQ,CAAC,oBAAoB,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC;IAC3D,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1E,QAAQ,CAAC,GAAG,CAAC,EAAE,oBAAoB,CAAC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,iBAAiB,GAAG,MAAM,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,SAAS,gBAAgB,EAAE,CAAC;CACnD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,kBAAkB,CACjD,YAAY,EACZ;IACE,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B,CACF,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,EAC3B,mBAAmB,GACpB,EAAE;IACD,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAEtB,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAC;IACjC,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAC/C,CAAC;AAEF,MAAM,WAAW,YAAY,CAAC,CAAC,CAAE,SAAQ,IAAI,CAAC,QAAQ,EAAE,IAAI,GAAG,OAAO,MAAM,CAAC,aAAa,CAAC;IACzF,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC,GAC1E,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,KAAK,IAAI,CAAC,CAAC;CAC1E;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,CAAC,MAAM,EAAE,WAAW,EAAE,CAAC;IAC/B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,GAAG,OAAO,IAAI;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;CACtC,CAAC;AAEF,KAAK,eAAe,GAAG;IACrB,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD,CAAC;AAEF,KAAK,WAAW,GAAG;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,WAAW,GAAG,CAAC,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,EAAE;IACD,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,kBAAkB,EAAE,kBAAkB,CAAC;CACxC,KAAK,OAAO,CAAC,yBAAyB,CAAC,CAAC;AAEzC;;;;GAIG;AACH,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,GAAG,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,KAAK,EAAE,CACL,KAAK,EAAE,MAAM,EACb,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,YAAY,CAAC,EAAE,kBAAkB,KAC9B,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,KAAK,YAAY,CAAC,kBAAkB,CAAC,CAAC;CACjF,CAAC;AAEF,KAAK,yBAAyB,GAAG;IAC/B,gBAAgB,EAAE,CAAC,EACjB,kBAAkB,GACnB,EAAE;QACD,kBAAkB,EAAE,wBAAwB,CAAC;KAC9C,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,eAAe,CAAC,CAAC,IAAI;IAAE,IAAI,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;CAAE,CAAC;AAEhE,eAAO,MAAM,mBAAmB,GAAI,OAAO,WAAW,KAAG,aA0UxD,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
|
2
|
-
import { Logger } from
|
|
3
|
-
import { generateUid } from
|
|
4
|
-
import EventEmitter from
|
|
5
|
-
import { serializeError } from
|
|
2
|
+
import { Logger } from "../Logger.js";
|
|
3
|
+
import { generateUid } from "@slonik/utilities";
|
|
4
|
+
import EventEmitter from "node:events";
|
|
5
|
+
import { serializeError } from "serialize-error";
|
|
6
6
|
const delay = (ms) => new Promise((resolve) => {
|
|
7
7
|
const timer = setTimeout(resolve, ms);
|
|
8
8
|
timer.unref();
|
|
@@ -30,10 +30,10 @@ export const createDriverFactory = (setup) => {
|
|
|
30
30
|
}
|
|
31
31
|
Logger.warn({
|
|
32
32
|
error: serializeError(error),
|
|
33
|
-
namespace:
|
|
34
|
-
},
|
|
33
|
+
namespace: "driverClient",
|
|
34
|
+
}, "unhandled driver client error");
|
|
35
35
|
};
|
|
36
|
-
clientEventEmitter.on(
|
|
36
|
+
clientEventEmitter.on("error", onError);
|
|
37
37
|
const { connect, end, query, stream } = await createPoolClient({
|
|
38
38
|
clientEventEmitter,
|
|
39
39
|
});
|
|
@@ -52,26 +52,26 @@ export const createDriverFactory = (setup) => {
|
|
|
52
52
|
};
|
|
53
53
|
const state = () => {
|
|
54
54
|
if (destroyPromise) {
|
|
55
|
-
return
|
|
55
|
+
return "PENDING_DESTROY";
|
|
56
56
|
}
|
|
57
57
|
if (releasePromise) {
|
|
58
|
-
return
|
|
58
|
+
return "PENDING_RELEASE";
|
|
59
59
|
}
|
|
60
60
|
if (isDestroyed) {
|
|
61
|
-
return
|
|
61
|
+
return "DESTROYED";
|
|
62
62
|
}
|
|
63
63
|
if (isAcquired) {
|
|
64
|
-
return
|
|
64
|
+
return "ACQUIRED";
|
|
65
65
|
}
|
|
66
|
-
return
|
|
66
|
+
return "IDLE";
|
|
67
67
|
};
|
|
68
68
|
const internalDestroy = async () => {
|
|
69
69
|
const currentState = state();
|
|
70
|
-
if (currentState ===
|
|
71
|
-
throw new Error(
|
|
70
|
+
if (currentState === "PENDING_DESTROY") {
|
|
71
|
+
throw new Error("Client is pending destroy.");
|
|
72
72
|
}
|
|
73
|
-
if (currentState ===
|
|
74
|
-
throw new Error(
|
|
73
|
+
if (currentState === "DESTROYED") {
|
|
74
|
+
throw new Error("Client is destroyed.");
|
|
75
75
|
}
|
|
76
76
|
clearIdleTimeout();
|
|
77
77
|
// activeQueryPromise and releasePromise are mutually exclusive
|
|
@@ -81,23 +81,28 @@ export const createDriverFactory = (setup) => {
|
|
|
81
81
|
// maximumPoolSize, which blocks the pool from creating new connections.
|
|
82
82
|
const pendingOperation = activeQueryPromise ?? releasePromise;
|
|
83
83
|
if (pendingOperation) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
try {
|
|
85
|
+
await Promise.race([
|
|
86
|
+
delay(driverConfiguration.gracefulTerminationTimeout),
|
|
87
|
+
pendingOperation,
|
|
88
|
+
]);
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
Logger.warn({
|
|
92
|
+
error: serializeError(error),
|
|
93
|
+
namespace: "driverClient",
|
|
94
|
+
}, "pending driver operation failed while destroying client");
|
|
95
|
+
}
|
|
88
96
|
}
|
|
89
97
|
isDestroyed = true;
|
|
90
|
-
clientEventEmitter.emit(
|
|
98
|
+
clientEventEmitter.emit("destroy");
|
|
91
99
|
// end() calls pg client.end() which sends a termination message and
|
|
92
100
|
// waits for the TCP connection to close. On broken connections (half-open
|
|
93
101
|
// TCP, network partition) this can hang indefinitely. Apply the same
|
|
94
102
|
// graceful termination timeout to prevent leaked promises that block
|
|
95
103
|
// pool.end() and callers awaiting connection.destroy().
|
|
96
|
-
await Promise.race([
|
|
97
|
-
|
|
98
|
-
delay(driverConfiguration.gracefulTerminationTimeout),
|
|
99
|
-
]);
|
|
100
|
-
clientEventEmitter.off('error', onError);
|
|
104
|
+
await Promise.race([end(), delay(driverConfiguration.gracefulTerminationTimeout)]);
|
|
105
|
+
clientEventEmitter.off("error", onError);
|
|
101
106
|
};
|
|
102
107
|
destroy = async () => {
|
|
103
108
|
if (destroyPromise) {
|
|
@@ -108,26 +113,44 @@ export const createDriverFactory = (setup) => {
|
|
|
108
113
|
};
|
|
109
114
|
const internalRelease = async () => {
|
|
110
115
|
const currentState = state();
|
|
111
|
-
if (currentState ===
|
|
112
|
-
throw new Error(
|
|
116
|
+
if (currentState === "PENDING_DESTROY") {
|
|
117
|
+
throw new Error("Client is pending destroy.");
|
|
113
118
|
}
|
|
114
|
-
if (currentState ===
|
|
115
|
-
throw new Error(
|
|
119
|
+
if (currentState === "DESTROYED") {
|
|
120
|
+
throw new Error("Client is destroyed.");
|
|
116
121
|
}
|
|
117
|
-
if (currentState !==
|
|
118
|
-
throw new Error(
|
|
122
|
+
if (currentState !== "ACQUIRED") {
|
|
123
|
+
throw new Error("Client is not acquired.");
|
|
119
124
|
}
|
|
120
125
|
if (activeQueryPromise) {
|
|
121
|
-
throw new Error(
|
|
126
|
+
throw new Error("Client has an active query.");
|
|
122
127
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
128
|
+
try {
|
|
129
|
+
if (resetConnection) {
|
|
130
|
+
await resetConnection({
|
|
131
|
+
query: async (sql) => {
|
|
132
|
+
await query(sql);
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
// A failed reset leaves the session state unknown, so the client
|
|
139
|
+
// must not be returned to the pool.
|
|
140
|
+
releasePromise = null;
|
|
141
|
+
try {
|
|
142
|
+
await destroy();
|
|
143
|
+
}
|
|
144
|
+
catch (destroyError) {
|
|
145
|
+
Logger.warn({
|
|
146
|
+
destroyError: serializeError(destroyError),
|
|
147
|
+
error: serializeError(error),
|
|
148
|
+
namespace: "driverClient",
|
|
149
|
+
}, "failed to destroy client after resetConnection error");
|
|
150
|
+
}
|
|
151
|
+
throw error;
|
|
129
152
|
}
|
|
130
|
-
if (driverConfiguration.idleTimeout !==
|
|
153
|
+
if (driverConfiguration.idleTimeout !== "DISABLE_TIMEOUT") {
|
|
131
154
|
clearIdleTimeout();
|
|
132
155
|
idleTimeout = setTimeout(() => {
|
|
133
156
|
void destroy();
|
|
@@ -136,7 +159,7 @@ export const createDriverFactory = (setup) => {
|
|
|
136
159
|
}
|
|
137
160
|
isAcquired = false;
|
|
138
161
|
releasePromise = null;
|
|
139
|
-
clientEventEmitter.emit(
|
|
162
|
+
clientEventEmitter.emit("release");
|
|
140
163
|
};
|
|
141
164
|
const release = () => {
|
|
142
165
|
if (destroyPromise) {
|
|
@@ -151,21 +174,21 @@ export const createDriverFactory = (setup) => {
|
|
|
151
174
|
const client = {
|
|
152
175
|
acquire: () => {
|
|
153
176
|
const currentState = state();
|
|
154
|
-
if (currentState ===
|
|
155
|
-
throw new Error(
|
|
177
|
+
if (currentState === "PENDING_DESTROY") {
|
|
178
|
+
throw new Error("Client is pending destroy.");
|
|
156
179
|
}
|
|
157
|
-
if (currentState ===
|
|
158
|
-
throw new Error(
|
|
180
|
+
if (currentState === "PENDING_RELEASE") {
|
|
181
|
+
throw new Error("Client is pending release.");
|
|
159
182
|
}
|
|
160
|
-
if (currentState ===
|
|
161
|
-
throw new Error(
|
|
183
|
+
if (currentState === "DESTROYED") {
|
|
184
|
+
throw new Error("Client is destroyed.");
|
|
162
185
|
}
|
|
163
|
-
if (currentState ===
|
|
164
|
-
throw new Error(
|
|
186
|
+
if (currentState === "ACQUIRED") {
|
|
187
|
+
throw new Error("Client is already acquired.");
|
|
165
188
|
}
|
|
166
189
|
clearIdleTimeout();
|
|
167
190
|
isAcquired = true;
|
|
168
|
-
clientEventEmitter.emit(
|
|
191
|
+
clientEventEmitter.emit("acquire");
|
|
169
192
|
},
|
|
170
193
|
destroy,
|
|
171
194
|
id: () => id,
|
|
@@ -177,23 +200,23 @@ export const createDriverFactory = (setup) => {
|
|
|
177
200
|
},
|
|
178
201
|
query: async (sql, values, queryOptions) => {
|
|
179
202
|
const currentState = state();
|
|
180
|
-
if (currentState ===
|
|
181
|
-
throw new Error(
|
|
203
|
+
if (currentState === "PENDING_DESTROY") {
|
|
204
|
+
throw new Error("Client is pending destroy.");
|
|
182
205
|
}
|
|
183
|
-
if (currentState ===
|
|
184
|
-
throw new Error(
|
|
206
|
+
if (currentState === "PENDING_RELEASE") {
|
|
207
|
+
throw new Error("Client is pending release.");
|
|
185
208
|
}
|
|
186
|
-
if (currentState ===
|
|
187
|
-
throw new Error(
|
|
209
|
+
if (currentState === "DESTROYED") {
|
|
210
|
+
throw new Error("Client is destroyed.");
|
|
188
211
|
}
|
|
189
|
-
if (currentState !==
|
|
190
|
-
throw new Error(
|
|
212
|
+
if (currentState !== "ACQUIRED") {
|
|
213
|
+
throw new Error("Client is not acquired.");
|
|
191
214
|
}
|
|
192
215
|
try {
|
|
193
216
|
activeQueryPromise = query(sql, values, queryOptions);
|
|
194
217
|
const result = await activeQueryPromise;
|
|
195
218
|
if (!activeQueryPromise) {
|
|
196
|
-
throw new Error(
|
|
219
|
+
throw new Error("Expected `activeQueryPromise` to be set.");
|
|
197
220
|
}
|
|
198
221
|
return result;
|
|
199
222
|
}
|
|
@@ -208,17 +231,17 @@ export const createDriverFactory = (setup) => {
|
|
|
208
231
|
state,
|
|
209
232
|
stream: (sql, values) => {
|
|
210
233
|
const currentState = state();
|
|
211
|
-
if (currentState ===
|
|
212
|
-
throw new Error(
|
|
234
|
+
if (currentState === "PENDING_DESTROY") {
|
|
235
|
+
throw new Error("Client is pending destroy.");
|
|
213
236
|
}
|
|
214
|
-
if (currentState ===
|
|
215
|
-
throw new Error(
|
|
237
|
+
if (currentState === "PENDING_RELEASE") {
|
|
238
|
+
throw new Error("Client is pending release.");
|
|
216
239
|
}
|
|
217
|
-
if (currentState ===
|
|
218
|
-
throw new Error(
|
|
240
|
+
if (currentState === "DESTROYED") {
|
|
241
|
+
throw new Error("Client is destroyed.");
|
|
219
242
|
}
|
|
220
|
-
if (currentState !==
|
|
221
|
-
throw new Error(
|
|
243
|
+
if (currentState !== "ACQUIRED") {
|
|
244
|
+
throw new Error("Client is not acquired.");
|
|
222
245
|
}
|
|
223
246
|
// Note: Stream lifecycle management should be handled by the caller.
|
|
224
247
|
// The client can be released while streaming, but the stream will continue to work.
|
|
@@ -229,7 +252,7 @@ export const createDriverFactory = (setup) => {
|
|
|
229
252
|
await connect();
|
|
230
253
|
}
|
|
231
254
|
catch (error) {
|
|
232
|
-
clientEventEmitter.off(
|
|
255
|
+
clientEventEmitter.off("error", onError);
|
|
233
256
|
throw error;
|
|
234
257
|
}
|
|
235
258
|
return client;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDriverFactory.js","sourceRoot":"","sources":["../../src/factories/createDriverFactory.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,YAAY,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,KAAK,GAAG,CAAC,EAAsB,EAAE,EAAE,CACvC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;IAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACtC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"createDriverFactory.js","sourceRoot":"","sources":["../../src/factories/createDriverFactory.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,YAAY,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,MAAM,KAAK,GAAG,CAAC,EAAsB,EAAE,EAAE,CACvC,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;IAC5B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACtC,KAAK,CAAC,KAAK,EAAE,CAAC;AAChB,CAAC,CAAC,CAAC;AAyJL,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAkB,EAAiB,EAAE;IACvE,OAAO,KAAK,EAAE,EAAE,mBAAmB,EAAE,EAAmB,EAAE;QACxD,MAAM,EAAE,eAAe,EAAE,GAAG,mBAAmB,CAAC;QAEhD,MAAM,kBAAkB,GAAuB,IAAI,YAAY,EAAE,CAAC;QAElE,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,KAAK,CAAC;YACvC,mBAAmB;YACnB,kBAAkB;SACnB,CAAC,CAAC;QAEH,OAAO;YACL,YAAY,EAAE,KAAK,IAAI,EAAE;gBACvB,MAAM,kBAAkB,GAA6B,IAAI,YAAY,EAAE,CAAC;gBAExE,wCAAwC;gBACxC,IAAI,OAA4B,CAAC;gBAEjC,MAAM,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE;oBAC/B,IAAI,OAAO,EAAE,CAAC;wBACZ,wDAAwD;wBACxD,KAAK,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;4BACxB,kDAAkD;4BAClD,qDAAqD;wBACvD,CAAC,CAAC,CAAC;oBACL,CAAC;oBAED,MAAM,CAAC,IAAI,CACT;wBACE,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC;wBAC5B,SAAS,EAAE,cAAc;qBAC1B,EACD,+BAA+B,CAChC,CAAC;gBACJ,CAAC,CAAC;gBAEF,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAExC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,gBAAgB,CAAC;oBAC7D,kBAAkB;iBACnB,CAAC,CAAC;gBAEH,IAAI,UAAU,GAAG,KAAK,CAAC;gBACvB,IAAI,WAAW,GAAG,KAAK,CAAC;gBACxB,IAAI,WAAW,GAA0B,IAAI,CAAC;gBAE9C,IAAI,kBAAkB,GAAsC,IAAI,CAAC;gBACjE,IAAI,cAAc,GAAyB,IAAI,CAAC;gBAChD,IAAI,cAAc,GAAyB,IAAI,CAAC;gBAEhD,MAAM,EAAE,GAAG,WAAW,EAAE,CAAC;gBAEzB,MAAM,gBAAgB,GAAG,GAAG,EAAE;oBAC5B,IAAI,WAAW,EAAE,CAAC;wBAChB,YAAY,CAAC,WAAW,CAAC,CAAC;wBAE1B,WAAW,GAAG,IAAI,CAAC;oBACrB,CAAC;gBACH,CAAC,CAAC;gBAEF,MAAM,KAAK,GAAG,GAAG,EAAE;oBACjB,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,iBAAiB,CAAC;oBAC3B,CAAC;oBAED,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,iBAAiB,CAAC;oBAC3B,CAAC;oBAED,IAAI,WAAW,EAAE,CAAC;wBAChB,OAAO,WAAW,CAAC;oBACrB,CAAC;oBAED,IAAI,UAAU,EAAE,CAAC;wBACf,OAAO,UAAU,CAAC;oBACpB,CAAC;oBAED,OAAO,MAAM,CAAC;gBAChB,CAAC,CAAC;gBAEF,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;oBACjC,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;oBAE7B,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;wBACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;oBAChD,CAAC;oBAED,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;wBACjC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;oBAC1C,CAAC;oBAED,gBAAgB,EAAE,CAAC;oBAEnB,+DAA+D;oBAC/D,oEAAoE;oBACpE,qEAAqE;oBACrE,6DAA6D;oBAC7D,wEAAwE;oBACxE,MAAM,gBAAgB,GAAG,kBAAkB,IAAI,cAAc,CAAC;oBAE9D,IAAI,gBAAgB,EAAE,CAAC;wBACrB,IAAI,CAAC;4BACH,MAAM,OAAO,CAAC,IAAI,CAAC;gCACjB,KAAK,CAAC,mBAAmB,CAAC,0BAA0B,CAAC;gCACrD,gBAAgB;6BACjB,CAAC,CAAC;wBACL,CAAC;wBAAC,OAAO,KAAK,EAAE,CAAC;4BACf,MAAM,CAAC,IAAI,CACT;gCACE,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC;gCAC5B,SAAS,EAAE,cAAc;6BAC1B,EACD,yDAAyD,CAC1D,CAAC;wBACJ,CAAC;oBACH,CAAC;oBAED,WAAW,GAAG,IAAI,CAAC;oBAEnB,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBAEnC,oEAAoE;oBACpE,0EAA0E;oBAC1E,qEAAqE;oBACrE,qEAAqE;oBACrE,wDAAwD;oBACxD,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,mBAAmB,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC;oBAEnF,kBAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBAC3C,CAAC,CAAC;gBAEF,OAAO,GAAG,KAAK,IAAI,EAAE;oBACnB,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,cAAc,CAAC;oBACxB,CAAC;oBAED,cAAc,GAAG,eAAe,EAAE,CAAC;oBAEnC,OAAO,cAAc,CAAC;gBACxB,CAAC,CAAC;gBAEF,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;oBACjC,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;oBAE7B,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;wBACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;oBAChD,CAAC;oBAED,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;wBACjC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;oBAC1C,CAAC;oBAED,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;wBAChC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;oBAC7C,CAAC;oBAED,IAAI,kBAAkB,EAAE,CAAC;wBACvB,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;oBACjD,CAAC;oBAED,IAAI,CAAC;wBACH,IAAI,eAAe,EAAE,CAAC;4BACpB,MAAM,eAAe,CAAC;gCACpB,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;oCACnB,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;gCACnB,CAAC;6BACF,CAAC,CAAC;wBACL,CAAC;oBACH,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,iEAAiE;wBACjE,oCAAoC;wBACpC,cAAc,GAAG,IAAI,CAAC;wBAEtB,IAAI,CAAC;4BACH,MAAM,OAAO,EAAE,CAAC;wBAClB,CAAC;wBAAC,OAAO,YAAY,EAAE,CAAC;4BACtB,MAAM,CAAC,IAAI,CACT;gCACE,YAAY,EAAE,cAAc,CAAC,YAAY,CAAC;gCAC1C,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC;gCAC5B,SAAS,EAAE,cAAc;6BAC1B,EACD,sDAAsD,CACvD,CAAC;wBACJ,CAAC;wBAED,MAAM,KAAK,CAAC;oBACd,CAAC;oBAED,IAAI,mBAAmB,CAAC,WAAW,KAAK,iBAAiB,EAAE,CAAC;wBAC1D,gBAAgB,EAAE,CAAC;wBAEnB,WAAW,GAAG,UAAU,CAAC,GAAG,EAAE;4BAC5B,KAAK,OAAO,EAAE,CAAC;4BAEf,WAAW,GAAG,IAAI,CAAC;wBACrB,CAAC,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;oBAChD,CAAC;oBAED,UAAU,GAAG,KAAK,CAAC;oBAEnB,cAAc,GAAG,IAAI,CAAC;oBAEtB,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACrC,CAAC,CAAC;gBAEF,MAAM,OAAO,GAAG,GAAG,EAAE;oBACnB,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,cAAc,CAAC;oBACxB,CAAC;oBAED,IAAI,cAAc,EAAE,CAAC;wBACnB,OAAO,cAAc,CAAC;oBACxB,CAAC;oBAED,cAAc,GAAG,eAAe,EAAE,CAAC;oBAEnC,OAAO,cAAc,CAAC;gBACxB,CAAC,CAAC;gBAEF,MAAM,MAAM,GAAG;oBACb,OAAO,EAAE,GAAG,EAAE;wBACZ,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;wBAE7B,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAChD,CAAC;wBAED,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAChD,CAAC;wBAED,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;4BACjC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;wBAC1C,CAAC;wBAED,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;4BAChC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;wBACjD,CAAC;wBAED,gBAAgB,EAAE,CAAC;wBAEnB,UAAU,GAAG,IAAI,CAAC;wBAElB,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACrC,CAAC;oBACD,OAAO;oBACP,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE;oBACZ,GAAG,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;wBACvB,OAAO,kBAAkB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;oBACjD,CAAC;oBACD,EAAE,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;wBACtB,OAAO,kBAAkB,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;oBAChD,CAAC;oBACD,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,EAAE;wBACzC,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;wBAE7B,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAChD,CAAC;wBAED,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAChD,CAAC;wBAED,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;4BACjC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;wBAC1C,CAAC;wBAED,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;4BAChC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;wBAC7C,CAAC;wBAED,IAAI,CAAC;4BACH,kBAAkB,GAAG,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;4BAEtD,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC;4BAExC,IAAI,CAAC,kBAAkB,EAAE,CAAC;gCACxB,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;4BAC9D,CAAC;4BAED,OAAO,MAAM,CAAC;wBAChB,CAAC;gCAAS,CAAC;4BACT,kBAAkB,GAAG,IAAI,CAAC;wBAC5B,CAAC;oBACH,CAAC;oBACD,OAAO;oBACP,cAAc,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE;wBAClC,OAAO,kBAAkB,CAAC,cAAc,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;oBAC5D,CAAC;oBACD,KAAK;oBACL,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;wBACtB,MAAM,YAAY,GAAG,KAAK,EAAE,CAAC;wBAE7B,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAChD,CAAC;wBAED,IAAI,YAAY,KAAK,iBAAiB,EAAE,CAAC;4BACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;wBAChD,CAAC;wBAED,IAAI,YAAY,KAAK,WAAW,EAAE,CAAC;4BACjC,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;wBAC1C,CAAC;wBAED,IAAI,YAAY,KAAK,UAAU,EAAE,CAAC;4BAChC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;wBAC7C,CAAC;wBAED,qEAAqE;wBACrE,oFAAoF;wBAEpF,OAAO,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;oBAC7B,CAAC;iBACF,CAAC;gBAEF,IAAI,CAAC;oBACH,MAAM,OAAO,EAAE,CAAC;gBAClB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,kBAAkB,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;oBAEzC,MAAM,KAAK,CAAC;gBACd,CAAC;gBAED,OAAO,MAAM,CAAC;YAChB,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -1,5 +1,52 @@
|
|
|
1
|
-
import
|
|
2
|
-
test
|
|
3
|
-
|
|
1
|
+
import { createDriverFactory } from "./createDriverFactory.js";
|
|
2
|
+
import test from "ava";
|
|
3
|
+
test("destroys client when resetConnection fails during release", async (t) => {
|
|
4
|
+
let resetCallCount = 0;
|
|
5
|
+
const driverFactory = createDriverFactory(async () => {
|
|
6
|
+
return {
|
|
7
|
+
createPoolClient: async () => {
|
|
8
|
+
return {
|
|
9
|
+
connect: async () => { },
|
|
10
|
+
end: async () => { },
|
|
11
|
+
query: async () => {
|
|
12
|
+
return {
|
|
13
|
+
command: "SELECT",
|
|
14
|
+
fields: [],
|
|
15
|
+
rowCount: 0,
|
|
16
|
+
rows: [],
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
stream: () => {
|
|
20
|
+
throw new Error("stream is not implemented in this test driver");
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
const driver = await driverFactory({
|
|
27
|
+
driverConfiguration: {
|
|
28
|
+
connectionTimeout: 1_000,
|
|
29
|
+
connectionUri: "postgresql://",
|
|
30
|
+
gracefulTerminationTimeout: 100,
|
|
31
|
+
idleInTransactionSessionTimeout: "DISABLE_TIMEOUT",
|
|
32
|
+
idleTimeout: "DISABLE_TIMEOUT",
|
|
33
|
+
maximumConnectionAge: "DISABLE_TIMEOUT",
|
|
34
|
+
maximumPoolSize: 1,
|
|
35
|
+
minimumPoolSize: 0,
|
|
36
|
+
resetConnection: async () => {
|
|
37
|
+
resetCallCount++;
|
|
38
|
+
if (resetCallCount === 1) {
|
|
39
|
+
throw new Error("reset failed");
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
statementTimeout: "DISABLE_TIMEOUT",
|
|
43
|
+
typeParsers: [],
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
const client = await driver.createClient();
|
|
47
|
+
client.acquire();
|
|
48
|
+
const error = await t.throwsAsync(client.release());
|
|
49
|
+
t.is(error?.message, "reset failed");
|
|
50
|
+
t.is(client.state(), "PENDING_DESTROY");
|
|
4
51
|
});
|
|
5
52
|
//# sourceMappingURL=createDriverFactory.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createDriverFactory.test.js","sourceRoot":"","sources":["../../src/factories/createDriverFactory.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,KAAK,CAAC;AAEvB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"createDriverFactory.test.js","sourceRoot":"","sources":["../../src/factories/createDriverFactory.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,IAAI,MAAM,KAAK,CAAC;AAEvB,IAAI,CAAC,2DAA2D,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE;IAC5E,IAAI,cAAc,GAAG,CAAC,CAAC;IAEvB,MAAM,aAAa,GAAG,mBAAmB,CAAC,KAAK,IAAI,EAAE;QACnD,OAAO;YACL,gBAAgB,EAAE,KAAK,IAAI,EAAE;gBAC3B,OAAO;oBACL,OAAO,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;oBACvB,GAAG,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;oBACnB,KAAK,EAAE,KAAK,IAAI,EAAE;wBAChB,OAAO;4BACL,OAAO,EAAE,QAAiB;4BAC1B,MAAM,EAAE,EAAE;4BACV,QAAQ,EAAE,CAAC;4BACX,IAAI,EAAE,EAAE;yBACT,CAAC;oBACJ,CAAC;oBACD,MAAM,EAAE,GAAG,EAAE;wBACX,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;oBACnE,CAAC;iBACF,CAAC;YACJ,CAAC;SACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;QACjC,mBAAmB,EAAE;YACnB,iBAAiB,EAAE,KAAK;YACxB,aAAa,EAAE,eAAe;YAC9B,0BAA0B,EAAE,GAAG;YAC/B,+BAA+B,EAAE,iBAAiB;YAClD,WAAW,EAAE,iBAAiB;YAC9B,oBAAoB,EAAE,iBAAiB;YACvC,eAAe,EAAE,CAAC;YAClB,eAAe,EAAE,CAAC;YAClB,eAAe,EAAE,KAAK,IAAI,EAAE;gBAC1B,cAAc,EAAE,CAAC;gBAEjB,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;gBAClC,CAAC;YACH,CAAC;YACD,gBAAgB,EAAE,iBAAiB;YACnC,WAAW,EAAE,EAAE;SAChB;KACF,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,EAAE,CAAC;IAE3C,MAAM,CAAC,OAAO,EAAE,CAAC;IAEjB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IAEpD,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;IACrC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createDriverFactory, type Driver, type DriverClient, type DriverClientEventEmitter, type DriverClientState, type DriverCommand, type DriverConfiguration, type DriverEventEmitter, type DriverFactory, type DriverNotice, type DriverQueryOptions, type DriverQueryResult, type DriverStream, type DriverStreamResult, type DriverTypeParser, } from
|
|
1
|
+
export { createDriverFactory, type Driver, type DriverClient, type DriverClientEventEmitter, type DriverClientState, type DriverCommand, type DriverConfiguration, type DriverEventEmitter, type DriverFactory, type DriverNotice, type DriverQueryOptions, type DriverQueryResult, type DriverStream, type DriverStreamResult, type DriverTypeParser, } from "./factories/createDriverFactory.js";
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { createDriverFactory, } from
|
|
1
|
+
export { createDriverFactory, } from "./factories/createDriverFactory.js";
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,68 +1,64 @@
|
|
|
1
1
|
{
|
|
2
|
+
"name": "@slonik/driver",
|
|
3
|
+
"version": "48.13.1",
|
|
4
|
+
"description": "A Node.js PostgreSQL client with strict types, detailed logging and assertions.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"postgresql",
|
|
7
|
+
"promise",
|
|
8
|
+
"types"
|
|
9
|
+
],
|
|
10
|
+
"license": "BSD-3-Clause",
|
|
2
11
|
"author": {
|
|
3
|
-
"email": "gajus@gajus.com",
|
|
4
12
|
"name": "Gajus Kuizinas",
|
|
13
|
+
"email": "gajus@gajus.com",
|
|
5
14
|
"url": "http://gajus.com"
|
|
6
15
|
},
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
],
|
|
11
|
-
"files": [
|
|
12
|
-
"src/**/*.test.ts"
|
|
13
|
-
],
|
|
14
|
-
"nodeArguments": [
|
|
15
|
-
"--import=tsimp"
|
|
16
|
-
]
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/gajus/slonik"
|
|
17
19
|
},
|
|
20
|
+
"files": [
|
|
21
|
+
"./src",
|
|
22
|
+
"./dist"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
18
27
|
"dependencies": {
|
|
19
|
-
"@slonik/types": "^48.
|
|
20
|
-
"@slonik/utilities": "^48.
|
|
28
|
+
"@slonik/types": "^48.13.1",
|
|
29
|
+
"@slonik/utilities": "^48.13.1",
|
|
21
30
|
"roarr": "^7.21.4",
|
|
22
31
|
"serialize-error": "^12.0.0",
|
|
23
32
|
"strict-event-emitter-types": "^2.0.0"
|
|
24
33
|
},
|
|
25
|
-
"description": "A Node.js PostgreSQL client with strict types, detailed logging and assertions.",
|
|
26
34
|
"devDependencies": {
|
|
27
35
|
"@types/node": "^24.10.13",
|
|
28
36
|
"ava": "^6.4.1",
|
|
29
37
|
"cspell": "^9.6.4",
|
|
30
|
-
"eslint": "9.39.2",
|
|
31
38
|
"tsimp": "^2.0.12",
|
|
32
|
-
"typescript": "^5.9.3"
|
|
33
|
-
"typescript-eslint": "^8.55.0",
|
|
34
|
-
"@slonik/eslint-config": "^48.12.3"
|
|
35
|
-
},
|
|
36
|
-
"engines": {
|
|
37
|
-
"node": ">=24"
|
|
39
|
+
"typescript": "^5.9.3"
|
|
38
40
|
},
|
|
39
|
-
"files": [
|
|
40
|
-
"./src",
|
|
41
|
-
"./dist"
|
|
42
|
-
],
|
|
43
|
-
"keywords": [
|
|
44
|
-
"postgresql",
|
|
45
|
-
"promise",
|
|
46
|
-
"types"
|
|
47
|
-
],
|
|
48
|
-
"license": "BSD-3-Clause",
|
|
49
|
-
"main": "./dist/index.js",
|
|
50
|
-
"name": "@slonik/driver",
|
|
51
41
|
"peerDependencies": {
|
|
52
42
|
"zod": "^3.25 || ^4"
|
|
53
43
|
},
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
|
|
44
|
+
"ava": {
|
|
45
|
+
"extensions": [
|
|
46
|
+
"ts"
|
|
47
|
+
],
|
|
48
|
+
"files": [
|
|
49
|
+
"src/**/*.test.ts"
|
|
50
|
+
],
|
|
51
|
+
"nodeArguments": [
|
|
52
|
+
"--import=tsimp"
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
"engines": {
|
|
56
|
+
"node": ">=24"
|
|
57
57
|
},
|
|
58
|
-
"type": "module",
|
|
59
|
-
"types": "./dist/index.d.ts",
|
|
60
|
-
"version": "48.12.3",
|
|
61
58
|
"scripts": {
|
|
62
59
|
"build": "rm -fr ./dist && tsc --project ./tsconfig.json",
|
|
63
|
-
"lint": "npm run lint:cspell && npm run lint:
|
|
60
|
+
"lint": "npm run lint:cspell && npm run lint:tsc",
|
|
64
61
|
"lint:cspell": "cspell . --no-progress --gitignore",
|
|
65
|
-
"lint:eslint": "eslint --cache ./src",
|
|
66
62
|
"lint:tsc": "tsc --noEmit",
|
|
67
63
|
"test": "ava --verbose --serial"
|
|
68
64
|
}
|
package/src/Logger.ts
CHANGED
|
@@ -1,5 +1,59 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { createDriverFactory } from "./createDriverFactory.js";
|
|
2
|
+
import test from "ava";
|
|
2
3
|
|
|
3
|
-
test(
|
|
4
|
-
|
|
4
|
+
test("destroys client when resetConnection fails during release", async (t) => {
|
|
5
|
+
let resetCallCount = 0;
|
|
6
|
+
|
|
7
|
+
const driverFactory = createDriverFactory(async () => {
|
|
8
|
+
return {
|
|
9
|
+
createPoolClient: async () => {
|
|
10
|
+
return {
|
|
11
|
+
connect: async () => {},
|
|
12
|
+
end: async () => {},
|
|
13
|
+
query: async () => {
|
|
14
|
+
return {
|
|
15
|
+
command: "SELECT" as const,
|
|
16
|
+
fields: [],
|
|
17
|
+
rowCount: 0,
|
|
18
|
+
rows: [],
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
stream: () => {
|
|
22
|
+
throw new Error("stream is not implemented in this test driver");
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const driver = await driverFactory({
|
|
30
|
+
driverConfiguration: {
|
|
31
|
+
connectionTimeout: 1_000,
|
|
32
|
+
connectionUri: "postgresql://",
|
|
33
|
+
gracefulTerminationTimeout: 100,
|
|
34
|
+
idleInTransactionSessionTimeout: "DISABLE_TIMEOUT",
|
|
35
|
+
idleTimeout: "DISABLE_TIMEOUT",
|
|
36
|
+
maximumConnectionAge: "DISABLE_TIMEOUT",
|
|
37
|
+
maximumPoolSize: 1,
|
|
38
|
+
minimumPoolSize: 0,
|
|
39
|
+
resetConnection: async () => {
|
|
40
|
+
resetCallCount++;
|
|
41
|
+
|
|
42
|
+
if (resetCallCount === 1) {
|
|
43
|
+
throw new Error("reset failed");
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
statementTimeout: "DISABLE_TIMEOUT",
|
|
47
|
+
typeParsers: [],
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
const client = await driver.createClient();
|
|
52
|
+
|
|
53
|
+
client.acquire();
|
|
54
|
+
|
|
55
|
+
const error = await t.throwsAsync(client.release());
|
|
56
|
+
|
|
57
|
+
t.is(error?.message, "reset failed");
|
|
58
|
+
t.is(client.state(), "PENDING_DESTROY");
|
|
5
59
|
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/consistent-type-definitions */
|
|
2
|
-
import { Logger } from
|
|
3
|
-
import type { Field } from
|
|
4
|
-
import { generateUid } from
|
|
5
|
-
import EventEmitter from
|
|
6
|
-
import type { Readable } from
|
|
7
|
-
import type { ConnectionOptions as TlsConnectionOptions } from
|
|
8
|
-
import { serializeError } from
|
|
9
|
-
import type { StrictEventEmitter } from
|
|
2
|
+
import { Logger } from "../Logger.js";
|
|
3
|
+
import type { Field } from "@slonik/types";
|
|
4
|
+
import { generateUid } from "@slonik/utilities";
|
|
5
|
+
import EventEmitter from "node:events";
|
|
6
|
+
import type { Readable } from "node:stream";
|
|
7
|
+
import type { ConnectionOptions as TlsConnectionOptions } from "node:tls";
|
|
8
|
+
import { serializeError } from "serialize-error";
|
|
9
|
+
import type { StrictEventEmitter } from "strict-event-emitter-types";
|
|
10
10
|
|
|
11
11
|
const delay = (ms: number | undefined) =>
|
|
12
12
|
new Promise<void>((resolve) => {
|
|
@@ -22,20 +22,17 @@ export type DriverClient = {
|
|
|
22
22
|
acquire: () => void;
|
|
23
23
|
destroy: () => Promise<void>;
|
|
24
24
|
id: () => string;
|
|
25
|
-
off: DriverClientEventEmitter[
|
|
26
|
-
on: DriverClientEventEmitter[
|
|
25
|
+
off: DriverClientEventEmitter["off"];
|
|
26
|
+
on: DriverClientEventEmitter["on"];
|
|
27
27
|
query: (
|
|
28
28
|
query: string,
|
|
29
29
|
values?: unknown[],
|
|
30
30
|
queryOptions?: DriverQueryOptions,
|
|
31
31
|
) => Promise<DriverQueryResult>;
|
|
32
32
|
release: () => Promise<void>;
|
|
33
|
-
removeListener: DriverClientEventEmitter[
|
|
33
|
+
removeListener: DriverClientEventEmitter["removeListener"];
|
|
34
34
|
state: () => DriverClientState;
|
|
35
|
-
stream: (
|
|
36
|
-
query: string,
|
|
37
|
-
values?: unknown[],
|
|
38
|
-
) => DriverStream<DriverStreamResult>;
|
|
35
|
+
stream: (query: string, values?: unknown[]) => DriverStream<DriverStreamResult>;
|
|
39
36
|
};
|
|
40
37
|
|
|
41
38
|
export type DriverClientEventEmitter = StrictEventEmitter<
|
|
@@ -50,26 +47,26 @@ export type DriverClientEventEmitter = StrictEventEmitter<
|
|
|
50
47
|
>;
|
|
51
48
|
|
|
52
49
|
export type DriverClientState =
|
|
53
|
-
|
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
50
|
+
| "ACQUIRED"
|
|
51
|
+
| "DESTROYED"
|
|
52
|
+
| "IDLE"
|
|
53
|
+
| "PENDING_DESTROY"
|
|
54
|
+
| "PENDING_RELEASE";
|
|
58
55
|
|
|
59
|
-
export type DriverCommand =
|
|
56
|
+
export type DriverCommand = "COPY" | "DELETE" | "INSERT" | "SELECT" | "UPDATE";
|
|
60
57
|
|
|
61
58
|
export type DriverConfiguration = {
|
|
62
|
-
readonly connectionTimeout:
|
|
59
|
+
readonly connectionTimeout: "DISABLE_TIMEOUT" | number;
|
|
63
60
|
readonly connectionUri: string;
|
|
64
61
|
readonly gracefulTerminationTimeout?: number;
|
|
65
|
-
readonly idleInTransactionSessionTimeout:
|
|
66
|
-
readonly idleTimeout?:
|
|
67
|
-
readonly maximumConnectionAge?: number;
|
|
62
|
+
readonly idleInTransactionSessionTimeout: "DISABLE_TIMEOUT" | number;
|
|
63
|
+
readonly idleTimeout?: "DISABLE_TIMEOUT" | number;
|
|
64
|
+
readonly maximumConnectionAge?: "DISABLE_TIMEOUT" | number;
|
|
68
65
|
readonly maximumPoolSize?: number;
|
|
69
66
|
readonly minimumPoolSize?: number;
|
|
70
67
|
readonly resetConnection?: (connection: BasicConnection) => Promise<void>;
|
|
71
68
|
readonly ssl?: TlsConnectionOptions;
|
|
72
|
-
readonly statementTimeout:
|
|
69
|
+
readonly statementTimeout: "DISABLE_TIMEOUT" | number;
|
|
73
70
|
readonly typeParsers: readonly DriverTypeParser[];
|
|
74
71
|
};
|
|
75
72
|
|
|
@@ -106,12 +103,9 @@ export type DriverQueryResult = {
|
|
|
106
103
|
readonly rows: Array<Record<string, unknown>>;
|
|
107
104
|
};
|
|
108
105
|
|
|
109
|
-
export interface DriverStream<T> extends Omit<
|
|
110
|
-
Readable,
|
|
111
|
-
'on' | typeof Symbol.asyncIterator
|
|
112
|
-
> {
|
|
106
|
+
export interface DriverStream<T> extends Omit<Readable, "on" | typeof Symbol.asyncIterator> {
|
|
113
107
|
[Symbol.asyncIterator]: () => AsyncIterableIterator<StreamDataEvent<T>>;
|
|
114
|
-
on: ((event:
|
|
108
|
+
on: ((event: "data", listener: (chunk: StreamDataEvent<T>) => void) => this) &
|
|
115
109
|
((event: string | symbol, listener: (...args: any[]) => void) => this);
|
|
116
110
|
}
|
|
117
111
|
|
|
@@ -158,10 +152,7 @@ type InternalPoolClient = {
|
|
|
158
152
|
values?: unknown[],
|
|
159
153
|
queryOptions?: DriverQueryOptions,
|
|
160
154
|
) => Promise<DriverQueryResult>;
|
|
161
|
-
stream: (
|
|
162
|
-
query: string,
|
|
163
|
-
values?: unknown[],
|
|
164
|
-
) => DriverStream<DriverStreamResult>;
|
|
155
|
+
stream: (query: string, values?: unknown[]) => DriverStream<DriverStreamResult>;
|
|
165
156
|
};
|
|
166
157
|
|
|
167
158
|
type InternalPoolClientFactory = {
|
|
@@ -204,13 +195,13 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
204
195
|
Logger.warn(
|
|
205
196
|
{
|
|
206
197
|
error: serializeError(error),
|
|
207
|
-
namespace:
|
|
198
|
+
namespace: "driverClient",
|
|
208
199
|
},
|
|
209
|
-
|
|
200
|
+
"unhandled driver client error",
|
|
210
201
|
);
|
|
211
202
|
};
|
|
212
203
|
|
|
213
|
-
clientEventEmitter.on(
|
|
204
|
+
clientEventEmitter.on("error", onError);
|
|
214
205
|
|
|
215
206
|
const { connect, end, query, stream } = await createPoolClient({
|
|
216
207
|
clientEventEmitter,
|
|
@@ -236,33 +227,33 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
236
227
|
|
|
237
228
|
const state = () => {
|
|
238
229
|
if (destroyPromise) {
|
|
239
|
-
return
|
|
230
|
+
return "PENDING_DESTROY";
|
|
240
231
|
}
|
|
241
232
|
|
|
242
233
|
if (releasePromise) {
|
|
243
|
-
return
|
|
234
|
+
return "PENDING_RELEASE";
|
|
244
235
|
}
|
|
245
236
|
|
|
246
237
|
if (isDestroyed) {
|
|
247
|
-
return
|
|
238
|
+
return "DESTROYED";
|
|
248
239
|
}
|
|
249
240
|
|
|
250
241
|
if (isAcquired) {
|
|
251
|
-
return
|
|
242
|
+
return "ACQUIRED";
|
|
252
243
|
}
|
|
253
244
|
|
|
254
|
-
return
|
|
245
|
+
return "IDLE";
|
|
255
246
|
};
|
|
256
247
|
|
|
257
248
|
const internalDestroy = async () => {
|
|
258
249
|
const currentState = state();
|
|
259
250
|
|
|
260
|
-
if (currentState ===
|
|
261
|
-
throw new Error(
|
|
251
|
+
if (currentState === "PENDING_DESTROY") {
|
|
252
|
+
throw new Error("Client is pending destroy.");
|
|
262
253
|
}
|
|
263
254
|
|
|
264
|
-
if (currentState ===
|
|
265
|
-
throw new Error(
|
|
255
|
+
if (currentState === "DESTROYED") {
|
|
256
|
+
throw new Error("Client is destroyed.");
|
|
266
257
|
}
|
|
267
258
|
|
|
268
259
|
clearIdleTimeout();
|
|
@@ -275,27 +266,34 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
275
266
|
const pendingOperation = activeQueryPromise ?? releasePromise;
|
|
276
267
|
|
|
277
268
|
if (pendingOperation) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
269
|
+
try {
|
|
270
|
+
await Promise.race([
|
|
271
|
+
delay(driverConfiguration.gracefulTerminationTimeout),
|
|
272
|
+
pendingOperation,
|
|
273
|
+
]);
|
|
274
|
+
} catch (error) {
|
|
275
|
+
Logger.warn(
|
|
276
|
+
{
|
|
277
|
+
error: serializeError(error),
|
|
278
|
+
namespace: "driverClient",
|
|
279
|
+
},
|
|
280
|
+
"pending driver operation failed while destroying client",
|
|
281
|
+
);
|
|
282
|
+
}
|
|
282
283
|
}
|
|
283
284
|
|
|
284
285
|
isDestroyed = true;
|
|
285
286
|
|
|
286
|
-
clientEventEmitter.emit(
|
|
287
|
+
clientEventEmitter.emit("destroy");
|
|
287
288
|
|
|
288
289
|
// end() calls pg client.end() which sends a termination message and
|
|
289
290
|
// waits for the TCP connection to close. On broken connections (half-open
|
|
290
291
|
// TCP, network partition) this can hang indefinitely. Apply the same
|
|
291
292
|
// graceful termination timeout to prevent leaked promises that block
|
|
292
293
|
// pool.end() and callers awaiting connection.destroy().
|
|
293
|
-
await Promise.race([
|
|
294
|
-
end(),
|
|
295
|
-
delay(driverConfiguration.gracefulTerminationTimeout),
|
|
296
|
-
]);
|
|
294
|
+
await Promise.race([end(), delay(driverConfiguration.gracefulTerminationTimeout)]);
|
|
297
295
|
|
|
298
|
-
clientEventEmitter.off(
|
|
296
|
+
clientEventEmitter.off("error", onError);
|
|
299
297
|
};
|
|
300
298
|
|
|
301
299
|
destroy = async () => {
|
|
@@ -311,31 +309,52 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
311
309
|
const internalRelease = async () => {
|
|
312
310
|
const currentState = state();
|
|
313
311
|
|
|
314
|
-
if (currentState ===
|
|
315
|
-
throw new Error(
|
|
312
|
+
if (currentState === "PENDING_DESTROY") {
|
|
313
|
+
throw new Error("Client is pending destroy.");
|
|
316
314
|
}
|
|
317
315
|
|
|
318
|
-
if (currentState ===
|
|
319
|
-
throw new Error(
|
|
316
|
+
if (currentState === "DESTROYED") {
|
|
317
|
+
throw new Error("Client is destroyed.");
|
|
320
318
|
}
|
|
321
319
|
|
|
322
|
-
if (currentState !==
|
|
323
|
-
throw new Error(
|
|
320
|
+
if (currentState !== "ACQUIRED") {
|
|
321
|
+
throw new Error("Client is not acquired.");
|
|
324
322
|
}
|
|
325
323
|
|
|
326
324
|
if (activeQueryPromise) {
|
|
327
|
-
throw new Error(
|
|
325
|
+
throw new Error("Client has an active query.");
|
|
328
326
|
}
|
|
329
327
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
328
|
+
try {
|
|
329
|
+
if (resetConnection) {
|
|
330
|
+
await resetConnection({
|
|
331
|
+
query: async (sql) => {
|
|
332
|
+
await query(sql);
|
|
333
|
+
},
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
} catch (error) {
|
|
337
|
+
// A failed reset leaves the session state unknown, so the client
|
|
338
|
+
// must not be returned to the pool.
|
|
339
|
+
releasePromise = null;
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
await destroy();
|
|
343
|
+
} catch (destroyError) {
|
|
344
|
+
Logger.warn(
|
|
345
|
+
{
|
|
346
|
+
destroyError: serializeError(destroyError),
|
|
347
|
+
error: serializeError(error),
|
|
348
|
+
namespace: "driverClient",
|
|
349
|
+
},
|
|
350
|
+
"failed to destroy client after resetConnection error",
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
throw error;
|
|
336
355
|
}
|
|
337
356
|
|
|
338
|
-
if (driverConfiguration.idleTimeout !==
|
|
357
|
+
if (driverConfiguration.idleTimeout !== "DISABLE_TIMEOUT") {
|
|
339
358
|
clearIdleTimeout();
|
|
340
359
|
|
|
341
360
|
idleTimeout = setTimeout(() => {
|
|
@@ -349,7 +368,7 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
349
368
|
|
|
350
369
|
releasePromise = null;
|
|
351
370
|
|
|
352
|
-
clientEventEmitter.emit(
|
|
371
|
+
clientEventEmitter.emit("release");
|
|
353
372
|
};
|
|
354
373
|
|
|
355
374
|
const release = () => {
|
|
@@ -370,27 +389,27 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
370
389
|
acquire: () => {
|
|
371
390
|
const currentState = state();
|
|
372
391
|
|
|
373
|
-
if (currentState ===
|
|
374
|
-
throw new Error(
|
|
392
|
+
if (currentState === "PENDING_DESTROY") {
|
|
393
|
+
throw new Error("Client is pending destroy.");
|
|
375
394
|
}
|
|
376
395
|
|
|
377
|
-
if (currentState ===
|
|
378
|
-
throw new Error(
|
|
396
|
+
if (currentState === "PENDING_RELEASE") {
|
|
397
|
+
throw new Error("Client is pending release.");
|
|
379
398
|
}
|
|
380
399
|
|
|
381
|
-
if (currentState ===
|
|
382
|
-
throw new Error(
|
|
400
|
+
if (currentState === "DESTROYED") {
|
|
401
|
+
throw new Error("Client is destroyed.");
|
|
383
402
|
}
|
|
384
403
|
|
|
385
|
-
if (currentState ===
|
|
386
|
-
throw new Error(
|
|
404
|
+
if (currentState === "ACQUIRED") {
|
|
405
|
+
throw new Error("Client is already acquired.");
|
|
387
406
|
}
|
|
388
407
|
|
|
389
408
|
clearIdleTimeout();
|
|
390
409
|
|
|
391
410
|
isAcquired = true;
|
|
392
411
|
|
|
393
|
-
clientEventEmitter.emit(
|
|
412
|
+
clientEventEmitter.emit("acquire");
|
|
394
413
|
},
|
|
395
414
|
destroy,
|
|
396
415
|
id: () => id,
|
|
@@ -403,20 +422,20 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
403
422
|
query: async (sql, values, queryOptions) => {
|
|
404
423
|
const currentState = state();
|
|
405
424
|
|
|
406
|
-
if (currentState ===
|
|
407
|
-
throw new Error(
|
|
425
|
+
if (currentState === "PENDING_DESTROY") {
|
|
426
|
+
throw new Error("Client is pending destroy.");
|
|
408
427
|
}
|
|
409
428
|
|
|
410
|
-
if (currentState ===
|
|
411
|
-
throw new Error(
|
|
429
|
+
if (currentState === "PENDING_RELEASE") {
|
|
430
|
+
throw new Error("Client is pending release.");
|
|
412
431
|
}
|
|
413
432
|
|
|
414
|
-
if (currentState ===
|
|
415
|
-
throw new Error(
|
|
433
|
+
if (currentState === "DESTROYED") {
|
|
434
|
+
throw new Error("Client is destroyed.");
|
|
416
435
|
}
|
|
417
436
|
|
|
418
|
-
if (currentState !==
|
|
419
|
-
throw new Error(
|
|
437
|
+
if (currentState !== "ACQUIRED") {
|
|
438
|
+
throw new Error("Client is not acquired.");
|
|
420
439
|
}
|
|
421
440
|
|
|
422
441
|
try {
|
|
@@ -425,7 +444,7 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
425
444
|
const result = await activeQueryPromise;
|
|
426
445
|
|
|
427
446
|
if (!activeQueryPromise) {
|
|
428
|
-
throw new Error(
|
|
447
|
+
throw new Error("Expected `activeQueryPromise` to be set.");
|
|
429
448
|
}
|
|
430
449
|
|
|
431
450
|
return result;
|
|
@@ -441,20 +460,20 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
441
460
|
stream: (sql, values) => {
|
|
442
461
|
const currentState = state();
|
|
443
462
|
|
|
444
|
-
if (currentState ===
|
|
445
|
-
throw new Error(
|
|
463
|
+
if (currentState === "PENDING_DESTROY") {
|
|
464
|
+
throw new Error("Client is pending destroy.");
|
|
446
465
|
}
|
|
447
466
|
|
|
448
|
-
if (currentState ===
|
|
449
|
-
throw new Error(
|
|
467
|
+
if (currentState === "PENDING_RELEASE") {
|
|
468
|
+
throw new Error("Client is pending release.");
|
|
450
469
|
}
|
|
451
470
|
|
|
452
|
-
if (currentState ===
|
|
453
|
-
throw new Error(
|
|
471
|
+
if (currentState === "DESTROYED") {
|
|
472
|
+
throw new Error("Client is destroyed.");
|
|
454
473
|
}
|
|
455
474
|
|
|
456
|
-
if (currentState !==
|
|
457
|
-
throw new Error(
|
|
475
|
+
if (currentState !== "ACQUIRED") {
|
|
476
|
+
throw new Error("Client is not acquired.");
|
|
458
477
|
}
|
|
459
478
|
|
|
460
479
|
// Note: Stream lifecycle management should be handled by the caller.
|
|
@@ -467,7 +486,7 @@ export const createDriverFactory = (setup: DriverSetup): DriverFactory => {
|
|
|
467
486
|
try {
|
|
468
487
|
await connect();
|
|
469
488
|
} catch (error) {
|
|
470
|
-
clientEventEmitter.off(
|
|
489
|
+
clientEventEmitter.off("error", onError);
|
|
471
490
|
|
|
472
491
|
throw error;
|
|
473
492
|
}
|
package/src/index.ts
CHANGED