Skip to content

Commit 444f008

Browse files
authored
feat: add ENV configs for DB close and API shutdown timeouts (#1366)
* style: async/await in postgres classes * chore: tag read only pg txs * feat: pg close timeout * feat: force kill timeout env * fix: remaining read only * fix: correct use of scoped sql conns * fix: resolveOrTimeout promise handling
1 parent f15df41 commit 444f008

File tree

7 files changed

+180
-117
lines changed

7 files changed

+180
-117
lines changed

.env

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ PG_SSL=false
99
# PG_IDLE_TIMEOUT=30
1010
# Max connection lifetime in seconds, defaults to 60
1111
# PG_MAX_LIFETIME=60
12+
# Seconds before force-ending running queries on connection close, defaults to 5
13+
# PG_CLOSE_TIMEOUT=5
1214

1315
# Can be any string, use to specify a use case specific to a deployment
1416
PG_APPLICATION_NAME=stacks-blockchain-api
@@ -33,6 +35,7 @@ PG_APPLICATION_NAME=stacks-blockchain-api
3335
# PG_PRIMARY_SSL=
3436
# PG_PRIMARY_IDLE_TIMEOUT=
3537
# PG_PRIMARY_MAX_LIFETIME=
38+
# PG_PRIMARY_CLOSE_TIMEOUT=
3639
# The connection URI below can be used in place of the PG variables above,
3740
# but if enabled it must be defined without others or omitted.
3841
# PG_PRIMARY_CONNECTION_URI=
@@ -84,6 +87,9 @@ STACKS_CORE_RPC_PORT=20443
8487
## configure the chainID/networkID; testnet: 0x80000000, mainnet: 0x00000001
8588
STACKS_CHAIN_ID=0x00000001
8689

90+
# Seconds to allow API components to shut down gracefully before force-killing them, defaults to 60
91+
# STACKS_SHUTDOWN_FORCE_KILL_TIMEOUT=60
92+
8793
BTC_RPC_HOST=http://127.0.0.1
8894
BTC_RPC_PORT=18443
8995
BTC_RPC_USER=btc

src/datastore/connection.ts

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -115,35 +115,42 @@ export async function connectPostgres({
115115
return sql;
116116
}
117117

118+
/**
119+
* Retrieve a postgres ENV value depending on the target database server (read-replica/default or
120+
* primary). We will fall back to read-replica values if a primary value was not given. See the
121+
* `.env` file for more information on these options.
122+
*/
123+
export function getPgConnectionEnvValue(
124+
name: string,
125+
pgServer: PgServer = PgServer.default
126+
): string | undefined {
127+
return pgServer === PgServer.primary
128+
? process.env[`PG_PRIMARY_${name}`] ?? process.env[`PG_${name}`]
129+
: process.env[`PG_${name}`];
130+
}
131+
118132
export function getPostgres({
119133
usageName,
120134
pgServer,
121135
}: {
122136
usageName: string;
123137
pgServer?: PgServer;
124138
}): PgSqlClient {
125-
// Retrieve a postgres ENV value depending on the target database server (read-replica/default or primary).
126-
// We will fall back to read-replica values if a primary value was not given.
127-
// See the `.env` file for more information on these options.
128-
const pgEnvValue = (name: string): string | undefined =>
129-
pgServer === PgServer.primary
130-
? process.env[`PG_PRIMARY_${name}`] ?? process.env[`PG_${name}`]
131-
: process.env[`PG_${name}`];
132139
const pgEnvVars = {
133-
database: pgEnvValue('DATABASE'),
134-
user: pgEnvValue('USER'),
135-
password: pgEnvValue('PASSWORD'),
136-
host: pgEnvValue('HOST'),
137-
port: pgEnvValue('PORT'),
138-
ssl: pgEnvValue('SSL'),
139-
schema: pgEnvValue('SCHEMA'),
140-
applicationName: pgEnvValue('APPLICATION_NAME'),
141-
idleTimeout: parseInt(pgEnvValue('IDLE_TIMEOUT') ?? '30'),
142-
maxLifetime: parseInt(pgEnvValue('MAX_LIFETIME') ?? '60'),
140+
database: getPgConnectionEnvValue('DATABASE', pgServer),
141+
user: getPgConnectionEnvValue('USER', pgServer),
142+
password: getPgConnectionEnvValue('PASSWORD', pgServer),
143+
host: getPgConnectionEnvValue('HOST', pgServer),
144+
port: getPgConnectionEnvValue('PORT', pgServer),
145+
ssl: getPgConnectionEnvValue('SSL', pgServer),
146+
schema: getPgConnectionEnvValue('SCHEMA', pgServer),
147+
applicationName: getPgConnectionEnvValue('APPLICATION_NAME', pgServer),
148+
idleTimeout: parseInt(getPgConnectionEnvValue('IDLE_TIMEOUT', pgServer) ?? '30'),
149+
maxLifetime: parseInt(getPgConnectionEnvValue('MAX_LIFETIME', pgServer) ?? '60'),
143150
poolMax: parseInt(process.env['PG_CONNECTION_POOL_MAX'] ?? '10'),
144151
};
145152
const defaultAppName = 'stacks-blockchain-api';
146-
const pgConnectionUri = pgEnvValue('CONNECTION_URI');
153+
const pgConnectionUri = getPgConnectionEnvValue('CONNECTION_URI', pgServer);
147154
const pgConfigEnvVar = Object.entries(pgEnvVars).find(([, v]) => typeof v === 'string')?.[0];
148155
if (pgConfigEnvVar && pgConnectionUri) {
149156
throw new Error(

0 commit comments

Comments
 (0)