Skip to content

Commit 4560b0a

Browse files
authored
feat(cat-gateway): dynamic postgres config (#2281)
* feat(dynamic config): postgres max conns max idle conn timeout min idle * refactor(env var settings and cleanup): event db * refactor(env var settings and cleanup): event db
1 parent 13d0e57 commit 4560b0a

File tree

4 files changed

+152
-25
lines changed

4 files changed

+152
-25
lines changed

catalyst-gateway/bin/src/db/event/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ impl EventDB {
240240
/// The env var "`DATABASE_URL`" can be set directly as an anv var, or in a
241241
/// `.env` file.
242242
pub fn establish_connection() {
243-
let (url, user, pass) = Settings::event_db_settings();
243+
let (url, user, pass, max_connections, max_lifetime, min_idle, connection_timeout) =
244+
Settings::event_db_settings();
244245

245246
// This was pre-validated and can't fail, but provide default in the impossible case it
246247
// does.
@@ -257,7 +258,12 @@ pub fn establish_connection() {
257258

258259
let pg_mgr = PostgresConnectionManager::new(config, tokio_postgres::NoTls);
259260

260-
let pool = Pool::builder().build_unchecked(pg_mgr);
261+
let pool = Pool::builder()
262+
.max_size(max_connections)
263+
.max_lifetime(Some(core::time::Duration::from_secs(max_lifetime.into())))
264+
.min_idle(min_idle)
265+
.connection_timeout(core::time::Duration::from_secs(connection_timeout.into()))
266+
.build_unchecked(pg_mgr);
261267

262268
if EVENT_DB_POOL.set(Arc::new(pool)).is_err() {
263269
error!("Failed to set event db pool. Called Twice?");
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//! Command line and environment variable settings for the service
2+
3+
use super::str_env_var::StringEnvVar;
4+
5+
/// Sets the maximum number of connections managed by the pool.
6+
/// Defaults to 100.
7+
const EVENT_DB_MAX_CONNECTIONS: u32 = 100;
8+
9+
/// Sets the maximum lifetime of connections in the pool.
10+
/// Defaults to 30 minutes.
11+
const EVENT_DB_MAX_LIFETIME: u32 = 30;
12+
13+
/// Sets the minimum idle connection count maintained by the pool.
14+
/// Defaults to 0.
15+
const EVENT_DB_MIN_IDLE: u32 = 0;
16+
17+
/// Sets the connection timeout used by the pool.
18+
/// Defaults to 300 seconds.
19+
const EVENT_DB_CONN_TIMEOUT: u32 = 300;
20+
21+
/// Default Event DB URL.
22+
const EVENT_DB_URL_DEFAULT: &str =
23+
"postgresql://postgres:postgres@localhost/catalyst_events?sslmode=disable";
24+
25+
/// Configuration for event db.
26+
#[derive(Clone)]
27+
pub(crate) struct EnvVars {
28+
/// The Address of the Event DB.
29+
pub(crate) url: StringEnvVar,
30+
31+
/// The `UserName` to use for the Event DB.
32+
pub(crate) username: Option<StringEnvVar>,
33+
34+
/// The Address of the Event DB.
35+
pub(crate) password: Option<StringEnvVar>,
36+
37+
/// Sets the maximum number of connections managed by the pool.
38+
/// Defaults to 10.
39+
pub(crate) max_connections: u32,
40+
41+
/// Sets the maximum lifetime of connections in the pool.
42+
/// Defaults to 30 minutes.
43+
pub(crate) max_lifetime: u32,
44+
45+
/// Sets the minimum idle connection count maintained by the pool.
46+
/// Defaults to None.
47+
pub(crate) min_idle: u32,
48+
49+
/// Sets the connection timeout used by the pool.
50+
/// Defaults to 30 seconds.
51+
pub(crate) connection_timeout: u32,
52+
}
53+
54+
impl EnvVars {
55+
/// Create a config for event db.
56+
pub(super) fn new() -> Self {
57+
Self {
58+
url: StringEnvVar::new("EVENT_DB_URL", EVENT_DB_URL_DEFAULT.into()),
59+
username: StringEnvVar::new_optional("EVENT_DB_USERNAME", false),
60+
password: StringEnvVar::new_optional("EVENT_DB_PASSWORD", true),
61+
max_connections: StringEnvVar::new_as_int(
62+
"EVENT_DB_MAX_CONNECTIONS",
63+
EVENT_DB_MAX_CONNECTIONS,
64+
0,
65+
u32::MAX,
66+
),
67+
max_lifetime: StringEnvVar::new_as_int(
68+
"EVENT_DB_MAX_LIFETIME",
69+
EVENT_DB_MAX_LIFETIME,
70+
0,
71+
u32::MAX,
72+
),
73+
min_idle: StringEnvVar::new_as_int("EVENT_DB_MIN_IDLE", EVENT_DB_MIN_IDLE, 0, u32::MAX),
74+
connection_timeout: StringEnvVar::new_as_int(
75+
"EVENT_DB_CONN_TIMEOUT",
76+
EVENT_DB_CONN_TIMEOUT,
77+
0,
78+
u32::MAX,
79+
),
80+
}
81+
}
82+
}

catalyst-gateway/bin/src/settings/mod.rs

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use crate::{
2323

2424
pub(crate) mod cassandra_db;
2525
pub(crate) mod chain_follower;
26+
pub(crate) mod event_db;
2627
pub(crate) mod signed_doc;
2728
mod str_env_var;
2829

@@ -53,10 +54,6 @@ const METRICS_MEMORY_INTERVAL_DEFAULT: Duration = Duration::from_secs(1);
5354
/// Default `METRICS_FOLLOWER_INTERVAL`, 1 second.
5455
const METRICS_FOLLOWER_INTERVAL_DEFAULT: Duration = Duration::from_secs(1);
5556

56-
/// Default Event DB URL.
57-
const EVENT_DB_URL_DEFAULT: &str =
58-
"postgresql://postgres:postgres@localhost/catalyst_events?sslmode=disable";
59-
6057
/// Default number of slots used as overlap when purging Live Index data.
6158
const PURGE_BACKWARD_SLOT_BUFFER_DEFAULT: u64 = 100;
6259

@@ -119,15 +116,6 @@ struct EnvVars {
119116
/// The base path the API is served at.
120117
api_url_prefix: StringEnvVar,
121118

122-
/// The Address of the Event DB.
123-
event_db_url: StringEnvVar,
124-
125-
/// The `UserName` to use for the Event DB.
126-
event_db_username: Option<StringEnvVar>,
127-
128-
/// The Address of the Event DB.
129-
event_db_password: Option<StringEnvVar>,
130-
131119
/// The Config of the Persistent Cassandra DB.
132120
cassandra_persistent_db: cassandra_db::EnvVars,
133121

@@ -137,6 +125,9 @@ struct EnvVars {
137125
/// The Chain Follower configuration
138126
chain_follower: chain_follower::EnvVars,
139127

128+
/// The event db configuration
129+
event_db: event_db::EnvVars,
130+
140131
/// The Catalyst Signed Documents configuration
141132
signed_doc: signed_doc::EnvVars,
142133

@@ -203,9 +194,7 @@ static ENV_VARS: LazyLock<EnvVars> = LazyLock::new(|| {
203194
client_id_key: StringEnvVar::new("CLIENT_ID_KEY", CLIENT_ID_KEY_DEFAULT.into()),
204195
api_host_names: StringEnvVar::new_optional("API_HOST_NAMES", false),
205196
api_url_prefix: StringEnvVar::new("API_URL_PREFIX", API_URL_PREFIX_DEFAULT.into()),
206-
event_db_url: StringEnvVar::new("EVENT_DB_URL", EVENT_DB_URL_DEFAULT.into()),
207-
event_db_username: StringEnvVar::new_optional("EVENT_DB_USERNAME", false),
208-
event_db_password: StringEnvVar::new_optional("EVENT_DB_PASSWORD", true),
197+
209198
cassandra_persistent_db: cassandra_db::EnvVars::new(
210199
cassandra_db::PERSISTENT_URL_DEFAULT,
211200
cassandra_db::PERSISTENT_NAMESPACE_DEFAULT,
@@ -215,6 +204,7 @@ static ENV_VARS: LazyLock<EnvVars> = LazyLock::new(|| {
215204
cassandra_db::VOLATILE_NAMESPACE_DEFAULT,
216205
),
217206
chain_follower: chain_follower::EnvVars::new(),
207+
event_db: event_db::EnvVars::new(),
218208
signed_doc: signed_doc::EnvVars::new(),
219209
internal_api_key: StringEnvVar::new_optional("INTERNAL_API_KEY", true),
220210
check_config_tick: StringEnvVar::new_as_duration(
@@ -248,7 +238,7 @@ impl EnvVars {
248238
pub(crate) fn validate() -> anyhow::Result<()> {
249239
let mut status = Ok(());
250240

251-
let url = ENV_VARS.event_db_url.as_str();
241+
let url = ENV_VARS.event_db.url.as_str();
252242
if let Err(error) = tokio_postgres::config::Config::from_str(url) {
253243
error!(error=%error, url=url, "Invalid Postgres DB URL.");
254244
status = Err(anyhow!("Environment Variable Validation Error."));
@@ -284,19 +274,44 @@ impl Settings {
284274
}
285275

286276
/// Get the current Event DB settings for this service.
287-
pub(crate) fn event_db_settings() -> (&'static str, Option<&'static str>, Option<&'static str>)
288-
{
289-
let url = ENV_VARS.event_db_url.as_str();
277+
pub(crate) fn event_db_settings() -> (
278+
&'static str,
279+
Option<&'static str>,
280+
Option<&'static str>,
281+
u32,
282+
u32,
283+
u32,
284+
u32,
285+
) {
286+
let url = ENV_VARS.event_db.url.as_str();
290287
let user = ENV_VARS
291-
.event_db_username
288+
.event_db
289+
.username
292290
.as_ref()
293291
.map(StringEnvVar::as_str);
294292
let pass = ENV_VARS
295-
.event_db_password
293+
.event_db
294+
.password
296295
.as_ref()
297296
.map(StringEnvVar::as_str);
298297

299-
(url, user, pass)
298+
let max_connections = ENV_VARS.event_db.max_connections;
299+
300+
let max_lifetime = ENV_VARS.event_db.max_lifetime;
301+
302+
let min_idle = ENV_VARS.event_db.min_idle;
303+
304+
let connection_timeout = ENV_VARS.event_db.connection_timeout;
305+
306+
(
307+
url,
308+
user,
309+
pass,
310+
max_connections,
311+
max_lifetime,
312+
min_idle,
313+
connection_timeout,
314+
)
300315
}
301316

302317
/// Get the Persistent & Volatile Cassandra DB config for this service.

catalyst-gateway/blueprint.cue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,30 @@ project: {
8787
key: "url"
8888
}
8989
}
90+
"EVENT_DB_MAX_CONNECTIONS_SIZE": {
91+
secret: {
92+
name: "db-max-connections"
93+
key: "max-connections"
94+
}
95+
}
96+
"EVENT_DB_MAX_LIFETIME": {
97+
secret: {
98+
name: "db-max-lifetime"
99+
key: "max-lifetime"
100+
}
101+
}
102+
"EVENT_DB_MIN_IDLE": {
103+
secret: {
104+
name: "db-min-idle"
105+
key: "min-idle"
106+
}
107+
}
108+
"EVENT_DB_CONNECTION_TIMEOUT": {
109+
secret: {
110+
name: "db-connection-timeout"
111+
key: "connection-timeout"
112+
}
113+
}
90114
"INTERNAL_API_KEY": {
91115
secret: {
92116
name: "gateway"

0 commit comments

Comments
 (0)