Skip to content

Commit 23d6602

Browse files
authored
fix: retry getting transaction when pool reaches max_num_connection (#348)
1 parent 4cd4bd9 commit 23d6602

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

package-lock.json

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"@tus/s3-store": "https://gitpkg.now.sh/supabase/tus-node-server/packages/s3-store/dist?build",
3838
"@tus/server": "https://gitpkg.now.sh/supabase/tus-node-server/packages/server/dist?build",
3939
"agentkeepalive": "^4.2.1",
40+
"async-retry": "^1.3.3",
4041
"axios": "^0.27.2",
4142
"axios-retry": "^3.3.1",
4243
"connection-string": "^4.3.6",

src/database/connection.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import pg from 'pg'
1+
import pg, { DatabaseError } from 'pg'
22
import { Knex, knex } from 'knex'
33
import { JwtPayload } from 'jsonwebtoken'
4+
import retry from 'async-retry'
45
import { getConfig } from '../config'
56
import { DbActiveConnection, DbActivePool } from '../monitoring/metrics'
7+
import { StorageBackendError } from '../storage'
68

79
// https://github.com/knex/knex/issues/387#issuecomment-51554522
810
pg.types.setTypeParser(20, 'text', parseInt)
@@ -115,12 +117,40 @@ export class TenantConnection {
115117
}
116118

117119
async transaction(instance?: Knex) {
118-
const pool = instance || this.pool
119-
const tnx = await pool.transaction()
120+
const tnx = await retry(
121+
async (bail) => {
122+
try {
123+
const pool = instance || this.pool
124+
return await pool.transaction()
125+
} catch (e) {
126+
if (
127+
e instanceof DatabaseError &&
128+
e.code === '08P01' &&
129+
e.message.includes('no more connections allowed')
130+
) {
131+
throw e
132+
}
133+
134+
bail(e as Error)
135+
return
136+
}
137+
},
138+
{
139+
minTimeout: 50,
140+
maxTimeout: 500,
141+
maxRetryTime: 2000,
142+
retries: 10,
143+
}
144+
)
145+
146+
if (!tnx) {
147+
throw new StorageBackendError('Could not create transaction', 500, 'transaction_failed')
148+
}
120149

121150
if (!instance && this.options.isExternalPool) {
122151
await tnx.raw(`SELECT set_config('search_path', ?, true)`, [searchPath.join(', ')])
123152
}
153+
124154
return tnx
125155
}
126156

0 commit comments

Comments
 (0)