@cosmicdrift/kumiko-framework 0.383.0 → 0.383.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/dist/db/connection.d.ts +5 -1
- package/dist/db/connection.js +29 -9
- package/dist/db/statement-timeout.js +2 -2
- package/package.json +3 -3
- package/src/changes.json +6 -0
package/dist/db/connection.d.ts
CHANGED
|
@@ -22,7 +22,11 @@ export type DbConnectionHandle = {
|
|
|
22
22
|
close: () => Promise<void>;
|
|
23
23
|
};
|
|
24
24
|
export declare const DEFAULT_DB_CLOSE_TIMEOUT_SECONDS = 5;
|
|
25
|
-
export
|
|
25
|
+
export type UnboundedSiblingPool = {
|
|
26
|
+
readonly client: PgClient;
|
|
27
|
+
readonly close: (timeoutSeconds: number) => Promise<void>;
|
|
28
|
+
};
|
|
29
|
+
export declare function openUnboundedSiblingPool(db: unknown): UnboundedSiblingPool | undefined;
|
|
26
30
|
export declare function createDbConnection({ url, ...options }: CreateDbConnectionOptions): DbConnectionHandle;
|
|
27
31
|
export declare function dbConnectionOptionsFromEnv(env?: Readonly<Record<string, string | undefined>>): DbConnectionOptions;
|
|
28
32
|
export declare const DEFAULT_SERVER_STATEMENT_TIMEOUT_MS = 60000;
|
package/dist/db/connection.js
CHANGED
|
@@ -38,18 +38,38 @@ export function createDbConnection({ url, ...options }) {
|
|
|
38
38
|
if (Object.keys(serverParameters).length > 0)
|
|
39
39
|
pgOptions.connection = serverParameters;
|
|
40
40
|
const client = postgres(url, pgOptions);
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
// A run that never settles (a caller gave up on it via its own timeout) never reaches the
|
|
42
|
+
// sibling's own close; close() ends it so shutdown and DROP DATABASE are not blocked by it.
|
|
43
|
+
const openSiblings = new Set();
|
|
44
|
+
unboundedSiblingFactories.set(client, () => {
|
|
45
|
+
// Two connections are enough for lock-in-tx plus DDL; the cap keeps parallel rebuilds from exhausting max_connections.
|
|
46
|
+
const sibling = postgres(url, {
|
|
47
|
+
...pgOptions,
|
|
48
|
+
max: 4,
|
|
49
|
+
connection: { ...pgOptions.connection, statement_timeout: 0 },
|
|
50
|
+
});
|
|
51
|
+
openSiblings.add(sibling);
|
|
52
|
+
return {
|
|
53
|
+
client: sibling,
|
|
54
|
+
close: async (timeoutSeconds) => {
|
|
55
|
+
openSiblings.delete(sibling);
|
|
56
|
+
await sibling.end({ timeout: timeoutSeconds });
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
});
|
|
47
60
|
return {
|
|
48
61
|
db: client,
|
|
49
62
|
client,
|
|
50
|
-
close: () =>
|
|
51
|
-
timeout
|
|
52
|
-
|
|
63
|
+
close: async () => {
|
|
64
|
+
const timeout = options.closeTimeoutSeconds ?? DEFAULT_DB_CLOSE_TIMEOUT_SECONDS;
|
|
65
|
+
unboundedSiblingFactories.delete(client);
|
|
66
|
+
const pools = [client, ...openSiblings];
|
|
67
|
+
openSiblings.clear();
|
|
68
|
+
const results = await Promise.allSettled(pools.map((pool) => pool.end({ timeout })));
|
|
69
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
70
|
+
if (failure !== undefined)
|
|
71
|
+
throw failure.reason;
|
|
72
|
+
},
|
|
53
73
|
};
|
|
54
74
|
}
|
|
55
75
|
// DB_PROVIDER=bun selected the removed Bun.SQL driver; ignoring it would boot
|
|
@@ -10,9 +10,9 @@ export async function withoutStatementTimeout(db, run) {
|
|
|
10
10
|
if (unbounded === undefined)
|
|
11
11
|
return run(db);
|
|
12
12
|
try {
|
|
13
|
-
return await run(unbounded);
|
|
13
|
+
return await run(unbounded.client);
|
|
14
14
|
}
|
|
15
15
|
finally {
|
|
16
|
-
await unbounded.
|
|
16
|
+
await unbounded.close(UNBOUNDED_POOL_CLOSE_TIMEOUT_SECONDS);
|
|
17
17
|
}
|
|
18
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmicdrift/kumiko-framework",
|
|
3
|
-
"version": "0.383.
|
|
3
|
+
"version": "0.383.1",
|
|
4
4
|
"description": "Framework core — engine, pipeline, API, DB, and every other bit that makes Kumiko go.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
|
|
@@ -199,7 +199,7 @@
|
|
|
199
199
|
"./package.json": "./package.json"
|
|
200
200
|
},
|
|
201
201
|
"dependencies": {
|
|
202
|
-
"@cosmicdrift/kumiko-types": "0.383.
|
|
202
|
+
"@cosmicdrift/kumiko-types": "0.383.1",
|
|
203
203
|
"bullmq": "^5.76.7",
|
|
204
204
|
"bun-types": "^1.3.13",
|
|
205
205
|
"hono": "^4.13.1",
|
|
@@ -215,7 +215,7 @@
|
|
|
215
215
|
"zod": "^4.4.3"
|
|
216
216
|
},
|
|
217
217
|
"devDependencies": {
|
|
218
|
-
"@cosmicdrift/kumiko-testing": "0.383.
|
|
218
|
+
"@cosmicdrift/kumiko-testing": "0.383.1",
|
|
219
219
|
"bun-types": "^1.3.13",
|
|
220
220
|
"pino-pretty": "^13.1.3"
|
|
221
221
|
},
|
package/src/changes.json
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.383.1",
|
|
4
|
+
"type": "fix",
|
|
5
|
+
"title": "close() ends unbounded pools of abandoned long runs",
|
|
6
|
+
"detail": "withoutStatementTimeout (reindexEntity, PII backfill, projection and multi-stream rebuilds, event-store index builds) runs on its own pool without statement_timeout and closes it when the run settles. A run that never settles, such as a reindex a boot rebuild gave up on via its own timeout, kept that pool connected, so DROP DATABASE in test cleanup failed with \"is being accessed by other users\". The connection handle's close() now ends these pools too. A rebuild that is still running when close() is called is ended after the same close timeout instead of keeping shutdown waiting."
|
|
7
|
+
},
|
|
2
8
|
{
|
|
3
9
|
"version": "0.383.0",
|
|
4
10
|
"type": "breaking",
|