Skip to content

Commit 27669bd

Browse files
committed
Fixed connection pool management to correctly handle database names
Thanks to that pongoClient.close can close connection pools without needing to call endAllPools. PongoClient will track opened dbClients and close them all.
1 parent 9477b33 commit 27669bd

File tree

11 files changed

+120
-20
lines changed

11 files changed

+120
-20
lines changed

src/package-lock.json

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"@types/mongodb": "^4.0.7",
7070
"@types/node": "20.11.30",
7171
"@types/pg": "^8.11.6",
72+
"@types/pg-connection-string": "^2.0.0",
7273
"@types/pg-format": "^1.0.5",
7374
"@types/uuid": "9.0.8",
7475
"@typescript-eslint/eslint-plugin": "7.9.0",
@@ -89,6 +90,7 @@
8990
},
9091
"peerDependencies": {
9192
"pg": "^8.12.0",
93+
"pg-connection-string": "^2.6.4",
9294
"pg-format": "^1.0.4",
9395
"testcontainers": "^10.10.1"
9496
},

src/packages/dumbo/package.json

+6-1
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,19 @@
4747
"dist"
4848
],
4949
"peerDependencies": {
50-
"@types/uuid": "^9.0.8",
5150
"@types/pg": "^8.11.6",
51+
"@types/pg-connection-string": "^2.0.0",
5252
"@types/pg-format": "^1.0.5",
53+
"@types/uuid": "^9.0.8",
5354
"pg": "^8.12.0",
55+
"pg-connection-string": "^2.6.4",
5456
"pg-format": "^1.0.4",
5557
"uuid": "^9.0.1"
5658
},
5759
"devDependencies": {
5860
"@types/node": "20.11.30"
61+
},
62+
"dependencies": {
63+
"@event-driven-io/dumbo": "^0.1.0"
5964
}
6065
}

src/packages/dumbo/src/connections/client.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ export const postgresClient = (
1414

1515
return {
1616
connect: () => pool.connect(),
17-
close: () => endPool(connectionString),
17+
close: () => endPool({ connectionString, database }),
1818
};
1919
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import pgcs from 'pg-connection-string';
2+
3+
export const defaultPostgreSqlDatabase = 'postgres';
4+
5+
export const getDatabaseNameOrDefault = (connectionString: string) =>
6+
pgcs.parse(connectionString).database ?? defaultPostgreSqlDatabase;
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './client';
2+
export * from './connectionString';
23
export * from './pool';
+54-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import pg from 'pg';
2+
import {
3+
defaultPostgreSqlDatabase,
4+
getDatabaseNameOrDefault,
5+
} from './connectionString';
26

37
const pools: Map<string, pg.Pool> = new Map();
8+
const usageCounter: Map<string, number> = new Map();
49

510
export const getPool = (
611
connectionStringOrOptions: string | pg.PoolConfig,
@@ -15,22 +20,63 @@ export const getPool = (
1520
? { connectionString }
1621
: connectionStringOrOptions;
1722

18-
//TODO: this should include database name resolution for key
23+
const database =
24+
poolOptions.database ??
25+
(poolOptions.connectionString
26+
? getDatabaseNameOrDefault(poolOptions.connectionString)
27+
: undefined);
28+
29+
const lookupKey = key(connectionString, database);
30+
31+
updatePoolUsageCounter(lookupKey, 1);
32+
1933
return (
20-
pools.get(connectionString) ??
21-
pools.set(connectionString, new pg.Pool(poolOptions)).get(connectionString)!
34+
pools.get(lookupKey) ??
35+
pools.set(lookupKey, new pg.Pool(poolOptions)).get(lookupKey)!
2236
);
2337
};
2438

25-
export const endPool = async (connectionString: string): Promise<void> => {
26-
const pool = pools.get(connectionString);
27-
if (pool) {
39+
export const endPool = async ({
40+
connectionString,
41+
database,
42+
force,
43+
}: {
44+
connectionString: string;
45+
database?: string | undefined;
46+
force?: boolean;
47+
}): Promise<void> => {
48+
database = database ?? getDatabaseNameOrDefault(connectionString);
49+
const lookupKey = key(connectionString, database);
50+
51+
const pool = pools.get(lookupKey);
52+
if (pool && (updatePoolUsageCounter(lookupKey, -1) <= 0 || force === true)) {
53+
await onEndPool(lookupKey, pool);
54+
}
55+
};
56+
57+
export const onEndPool = async (lookupKey: string, pool: pg.Pool) => {
58+
try {
2859
await pool.end();
29-
pools.delete(connectionString);
60+
pools.delete(lookupKey);
61+
} catch (error) {
62+
console.log(`Error while closing the connection pool: ${lookupKey}`);
63+
console.log(error);
3064
}
3165
};
3266

3367
export const endAllPools = () =>
3468
Promise.all(
35-
[...pools.keys()].map((connectionString) => endPool(connectionString)),
69+
[...pools.entries()].map(([lookupKey, pool]) => onEndPool(lookupKey, pool)),
3670
);
71+
72+
const key = (connectionString: string, database: string | undefined) =>
73+
`${connectionString}|${database ?? defaultPostgreSqlDatabase}`;
74+
75+
const updatePoolUsageCounter = (lookupKey: string, by: 1 | -1): number => {
76+
const currentCounter = usageCounter.get(lookupKey) ?? 0;
77+
const newCounter = currentCounter + by;
78+
79+
usageCounter.set(lookupKey, currentCounter + by);
80+
81+
return newCounter;
82+
};

src/packages/pongo/package.json

+7-3
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,20 @@
4747
"dist"
4848
],
4949
"peerDependencies": {
50-
"@types/uuid": "^9.0.8",
50+
"@event-driven-io/dumbo": "^0.1.0",
51+
"@types/mongodb": "^4.0.7",
5152
"@types/pg": "^8.11.6",
5253
"@types/pg-format": "^1.0.5",
53-
"@types/mongodb": "^4.0.7",
54-
"@event-driven-io/dumbo": "^0.1.0",
54+
"@types/uuid": "^9.0.8",
5555
"pg": "^8.12.0",
5656
"pg-format": "^1.0.4",
5757
"uuid": "^9.0.1"
5858
},
5959
"devDependencies": {
6060
"@types/node": "20.11.30"
61+
},
62+
"dependencies": {
63+
"@types/pg-connection-string": "^2.0.0",
64+
"pg-connection-string": "^2.6.4"
6165
}
6266
}

src/packages/pongo/src/e2e/compatibilityTest.e2e.spec.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { endAllPools } from '@event-driven-io/dumbo';
21
import {
32
MongoDBContainer,
43
type StartedMongoDBContainer,
@@ -60,7 +59,7 @@ void describe('MongoDB Compatibility Tests', () => {
6059

6160
after(async () => {
6261
try {
63-
await endAllPools();
62+
await pongoClient.close();
6463
await postgres.stop();
6564
} catch (error) {
6665
console.log(error);

src/packages/pongo/src/main/client.ts

+21-4
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,34 @@
1-
import { getDbClient } from './dbClient';
1+
import { getDatabaseNameOrDefault } from '@event-driven-io/dumbo';
2+
import { getDbClient, type DbClient } from './dbClient';
23
import type { PongoClient, PongoDb } from './typing/operations';
34

45
export const pongoClient = (connectionString: string): PongoClient => {
6+
const defaultDbName = getDatabaseNameOrDefault(connectionString);
7+
const dbClients: Map<string, DbClient> = new Map();
8+
59
const dbClient = getDbClient(connectionString);
10+
dbClients.set(defaultDbName, dbClient);
611

712
const pongoClient: PongoClient = {
813
connect: async () => {
914
await dbClient.connect();
1015
return pongoClient;
1116
},
12-
close: () => dbClient.close(),
13-
db: (dbName?: string): PongoDb =>
14-
dbName ? getDbClient(connectionString, dbName) : dbClient,
17+
close: async () => {
18+
for (const db of dbClients.values()) {
19+
await db.close();
20+
}
21+
},
22+
db: (dbName?: string): PongoDb => {
23+
if (!dbName) return dbClient;
24+
25+
return (
26+
dbClients.get(dbName) ??
27+
dbClients
28+
.set(dbName, getDbClient(connectionString, dbName))
29+
.get(dbName)!
30+
);
31+
},
1532
};
1633

1734
return pongoClient;

src/packages/pongo/src/postgres/client.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const postgresClient = (
1010

1111
return {
1212
connect: () => Promise.resolve(),
13-
close: () => endPool(connectionString),
13+
close: () => endPool({ connectionString, database }),
1414
collection: <T>(name: string) => postgresCollection<T>(name, pool),
1515
};
1616
};

0 commit comments

Comments
 (0)