Skip to content

Commit 5fd3849

Browse files
committed
chore: Improve PostgreSQL connection pool error handling with specific error codes and logging
1 parent 8de215d commit 5fd3849

File tree

1 file changed

+49
-2
lines changed

1 file changed

+49
-2
lines changed

packages/hocuspocus.server/src/lib/prisma.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const poolConfig = {
4646
query_timeout: parseInt(process.env.DB_QUERY_TIMEOUT || '30000', 10),
4747
// Allow pool to create connections on-demand (pg Pool doesn't support min, but this helps)
4848
// Connections are created lazily when needed and kept alive longer
49+
// The pool automatically removes dead connections and creates new ones as needed
4950
}
5051

5152
// Create PostgreSQL connection pool
@@ -81,8 +82,54 @@ pool.on('acquire', () => {
8182
}
8283
})
8384

84-
pool.on('error', (err) => {
85-
dbLogger.error({ err }, 'Unexpected database pool error')
85+
pool.on('error', (err: any) => {
86+
// Handle specific PostgreSQL error codes
87+
const errorCode = err.code
88+
89+
// 57P01: terminating connection due to administrator command
90+
// This is normal during database restarts/maintenance - don't log as error
91+
if (errorCode === '57P01') {
92+
dbLogger.debug({
93+
code: errorCode,
94+
message: 'Database connection terminated (likely during maintenance/restart)'
95+
}, 'Connection terminated by database - will be automatically replaced')
96+
return
97+
}
98+
99+
// 57P02: terminating connection due to administrator command (alternative)
100+
if (errorCode === '57P02') {
101+
dbLogger.debug({
102+
code: errorCode,
103+
message: 'Database connection terminated'
104+
}, 'Connection terminated - will be automatically replaced')
105+
return
106+
}
107+
108+
// 57P03: cannot connect now (database startup/shutdown)
109+
if (errorCode === '57P03') {
110+
dbLogger.warn({
111+
code: errorCode,
112+
message: 'Database temporarily unavailable - connection will retry'
113+
}, 'Database connection unavailable')
114+
return
115+
}
116+
117+
// Connection errors that are recoverable
118+
const recoverableErrors = ['ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND']
119+
if (recoverableErrors.some(code => err.code === code || err.message?.includes(code))) {
120+
dbLogger.warn({
121+
code: err.code,
122+
message: err.message
123+
}, 'Database connection error - will retry automatically')
124+
return
125+
}
126+
127+
// Log other errors as actual errors
128+
dbLogger.error({
129+
err,
130+
code: errorCode,
131+
message: err.message
132+
}, 'Unexpected database pool error')
86133
})
87134

88135
pool.on('remove', () => {

0 commit comments

Comments
 (0)