Skip to content

Commit 7bed5a3

Browse files
authored
Merge pull request #11167 from Turbo87/create-database-pool
Use same database pool creation code for API server and background worker
2 parents b3bc86b + 9c7e6ce commit 7bed5a3

File tree

6 files changed

+71
-89
lines changed

6 files changed

+71
-89
lines changed

src/app.rs

+21-45
Original file line numberDiff line numberDiff line change
@@ -94,51 +94,8 @@ impl<S: app_builder::State> AppBuilder<S> {
9494
S::PrimaryDatabase: app_builder::IsUnset,
9595
S::ReplicaDatabase: app_builder::IsUnset,
9696
{
97-
let primary_database = {
98-
use secrecy::ExposeSecret;
99-
100-
let primary_db_connection_config = ConnectionConfig {
101-
statement_timeout: config.statement_timeout,
102-
read_only: config.primary.read_only_mode,
103-
};
104-
105-
let url = connection_url(config, config.primary.url.expose_secret());
106-
let manager_config = make_manager_config(config.enforce_tls);
107-
let manager = AsyncDieselConnectionManager::new_with_config(url, manager_config);
108-
109-
DeadpoolPool::builder(manager)
110-
.runtime(Runtime::Tokio1)
111-
.max_size(config.primary.pool_size)
112-
.wait_timeout(Some(config.connection_timeout))
113-
.post_create(primary_db_connection_config)
114-
.build()
115-
.unwrap()
116-
};
117-
118-
let replica_database = if let Some(pool_config) = config.replica.as_ref() {
119-
use secrecy::ExposeSecret;
120-
121-
let replica_db_connection_config = ConnectionConfig {
122-
statement_timeout: config.statement_timeout,
123-
read_only: pool_config.read_only_mode,
124-
};
125-
126-
let url = connection_url(config, pool_config.url.expose_secret());
127-
let manager_config = make_manager_config(config.enforce_tls);
128-
let manager = AsyncDieselConnectionManager::new_with_config(url, manager_config);
129-
130-
let pool = DeadpoolPool::builder(manager)
131-
.runtime(Runtime::Tokio1)
132-
.max_size(pool_config.pool_size)
133-
.wait_timeout(Some(config.connection_timeout))
134-
.post_create(replica_db_connection_config)
135-
.build()
136-
.unwrap();
137-
138-
Some(pool)
139-
} else {
140-
None
141-
};
97+
let primary_database = create_database_pool(&config.primary);
98+
let replica_database = config.replica.as_ref().map(create_database_pool);
14299

143100
self.primary_database(primary_database)
144101
.maybe_replica_database(replica_database)
@@ -165,6 +122,25 @@ impl<S: app_builder::State> AppBuilder<S> {
165122
}
166123
}
167124

125+
pub fn create_database_pool(config: &config::DbPoolConfig) -> DeadpoolPool<AsyncPgConnection> {
126+
let connection_config = ConnectionConfig {
127+
statement_timeout: config.statement_timeout,
128+
read_only: config.read_only_mode,
129+
};
130+
131+
let url = connection_url(config);
132+
let manager_config = make_manager_config(config.enforce_tls);
133+
let manager = AsyncDieselConnectionManager::new_with_config(url, manager_config);
134+
135+
DeadpoolPool::builder(manager)
136+
.runtime(Runtime::Tokio1)
137+
.max_size(config.pool_size)
138+
.wait_timeout(Some(config.connection_timeout))
139+
.post_create(connection_config)
140+
.build()
141+
.unwrap()
142+
}
143+
168144
impl App {
169145
/// A unique key to generate signed cookies
170146
pub fn session_key(&self) -> &cookie::Key {

src/bin/background-worker.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,19 @@
1414
extern crate tracing;
1515

1616
use anyhow::Context;
17+
use crates_io::app::create_database_pool;
1718
use crates_io::cloudfront::CloudFront;
18-
use crates_io::db::make_manager_config;
1919
use crates_io::fastly::Fastly;
20+
use crates_io::ssh;
2021
use crates_io::storage::Storage;
2122
use crates_io::worker::{Environment, RunnerExt};
2223
use crates_io::{Emails, config};
23-
use crates_io::{db, ssh};
2424
use crates_io_env_vars::var;
2525
use crates_io_index::RepositoryConfig;
2626
use crates_io_team_repo::TeamRepoImpl;
2727
use crates_io_worker::Runner;
28-
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
29-
use diesel_async::pooled_connection::deadpool::Pool;
3028
use object_store::prefix::PrefixStore;
3129
use reqwest::Client;
32-
use secrecy::ExposeSecret;
3330
use std::sync::Arc;
3431
use std::thread::sleep;
3532
use std::time::Duration;
@@ -44,7 +41,10 @@ fn main() -> anyhow::Result<()> {
4441

4542
info!("Booting runner");
4643

47-
let config = config::Server::from_environment()?;
44+
let mut config = config::Server::from_environment()?;
45+
46+
// Override the pool size to 10 for the background worker
47+
config.db.primary.pool_size = 10;
4848

4949
let runtime = tokio::runtime::Builder::new_multi_thread()
5050
.enable_all()
@@ -61,8 +61,6 @@ fn main() -> anyhow::Result<()> {
6161
}
6262
}
6363

64-
let db_url = db::connection_url(&config.db, config.db.primary.url.expose_secret());
65-
6664
if var("HEROKU")?.is_some() {
6765
ssh::write_known_hosts_file()?;
6866
}
@@ -84,9 +82,7 @@ fn main() -> anyhow::Result<()> {
8482
let fastly = Fastly::from_environment(client.clone());
8583
let team_repo = TeamRepoImpl::default();
8684

87-
let manager_config = make_manager_config(config.db.enforce_tls);
88-
let manager = AsyncDieselConnectionManager::new_with_config(db_url, manager_config);
89-
let deadpool = Pool::builder(manager).max_size(10).build()?;
85+
let deadpool = create_database_pool(&config.db.primary);
9086

9187
let environment = Environment::builder()
9288
.config(Arc::new(config))

src/config/database_pools.rs

+28-23
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ pub struct DatabasePools {
2424
pub primary: DbPoolConfig,
2525
/// An optional follower database. Always read-only.
2626
pub replica: Option<DbPoolConfig>,
27+
}
28+
29+
#[derive(Debug)]
30+
pub struct DbPoolConfig {
31+
pub url: SecretString,
32+
pub read_only_mode: bool,
33+
pub pool_size: usize,
34+
pub min_idle: Option<u32>,
2735
/// Number of seconds to wait for unacknowledged TCP packets before treating the connection as
2836
/// broken. This value will determine how long crates.io stays unavailable in case of full
2937
/// packet loss between the application and the database: setting it too high will result in an
@@ -43,14 +51,6 @@ pub struct DatabasePools {
4351
pub enforce_tls: bool,
4452
}
4553

46-
#[derive(Debug)]
47-
pub struct DbPoolConfig {
48-
pub url: SecretString,
49-
pub read_only_mode: bool,
50-
pub pool_size: usize,
51-
pub min_idle: Option<u32>,
52-
}
53-
5454
impl DatabasePools {
5555
pub fn are_all_read_only(&self) -> bool {
5656
self.primary.read_only_mode
@@ -102,13 +102,13 @@ impl DatabasePools {
102102
read_only_mode: true,
103103
pool_size: primary_async_pool_size,
104104
min_idle: primary_min_idle,
105+
tcp_timeout_ms,
106+
connection_timeout,
107+
statement_timeout,
108+
helper_threads,
109+
enforce_tls,
105110
},
106111
replica: None,
107-
tcp_timeout_ms,
108-
connection_timeout,
109-
statement_timeout,
110-
helper_threads,
111-
enforce_tls,
112112
},
113113
// The follower is down, don't configure the replica.
114114
Some("follower") => Self {
@@ -117,20 +117,25 @@ impl DatabasePools {
117117
read_only_mode,
118118
pool_size: primary_async_pool_size,
119119
min_idle: primary_min_idle,
120+
tcp_timeout_ms,
121+
connection_timeout,
122+
statement_timeout,
123+
helper_threads,
124+
enforce_tls,
120125
},
121126
replica: None,
122-
tcp_timeout_ms,
123-
connection_timeout,
124-
statement_timeout,
125-
helper_threads,
126-
enforce_tls,
127127
},
128128
_ => Self {
129129
primary: DbPoolConfig {
130130
url: leader_url,
131131
read_only_mode,
132132
pool_size: primary_async_pool_size,
133133
min_idle: primary_min_idle,
134+
tcp_timeout_ms,
135+
connection_timeout,
136+
statement_timeout,
137+
helper_threads,
138+
enforce_tls,
134139
},
135140
replica: follower_url.map(|url| DbPoolConfig {
136141
url,
@@ -140,12 +145,12 @@ impl DatabasePools {
140145
read_only_mode: true,
141146
pool_size: replica_async_pool_size,
142147
min_idle: replica_min_idle,
148+
tcp_timeout_ms,
149+
connection_timeout,
150+
statement_timeout,
151+
helper_threads,
152+
enforce_tls,
143153
}),
144-
tcp_timeout_ms,
145-
connection_timeout,
146-
statement_timeout,
147-
helper_threads,
148-
enforce_tls,
149154
},
150155
})
151156
}

src/db.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,17 @@ use crate::config;
1414
pub async fn oneoff_connection_with_config(
1515
config: &config::DatabasePools,
1616
) -> ConnectionResult<AsyncPgConnection> {
17-
let url = connection_url(config, config.primary.url.expose_secret());
18-
establish_async_connection(&url, config.enforce_tls).await
17+
let url = connection_url(&config.primary);
18+
establish_async_connection(&url, config.primary.enforce_tls).await
1919
}
2020

2121
pub async fn oneoff_connection() -> anyhow::Result<AsyncPgConnection> {
2222
let config = config::DatabasePools::full_from_environment(&config::Base::from_environment()?)?;
2323
Ok(oneoff_connection_with_config(&config).await?)
2424
}
2525

26-
pub fn connection_url(config: &config::DatabasePools, url: &str) -> String {
27-
let mut url = Url::parse(url).expect("Invalid database URL");
26+
pub fn connection_url(config: &config::DbPoolConfig) -> String {
27+
let mut url = Url::parse(config.url.expose_secret()).expect("Invalid database URL");
2828

2929
if config.enforce_tls {
3030
maybe_append_url_param(&mut url, "sslmode", "require");

src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use tikv_jemallocator::Jemalloc;
2525
#[global_allocator]
2626
static ALLOC: Jemalloc = Jemalloc;
2727

28-
mod app;
28+
pub mod app;
2929
pub mod auth;
3030
pub mod boot;
3131
pub mod certs;

src/tests/util/test_app.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,11 @@ impl TestAppBuilder {
401401
read_only_mode: true,
402402
pool_size: primary.pool_size,
403403
min_idle: primary.min_idle,
404+
tcp_timeout_ms: primary.tcp_timeout_ms,
405+
connection_timeout: primary.connection_timeout,
406+
statement_timeout: primary.statement_timeout,
407+
helper_threads: primary.helper_threads,
408+
enforce_tls: primary.enforce_tls,
404409
});
405410

406411
self
@@ -419,13 +424,13 @@ fn simple_config() -> config::Server {
419424
read_only_mode: false,
420425
pool_size: 5,
421426
min_idle: None,
427+
tcp_timeout_ms: 1000, // 1 second
428+
connection_timeout: Duration::from_secs(1),
429+
statement_timeout: Duration::from_secs(1),
430+
helper_threads: 1,
431+
enforce_tls: false,
422432
},
423433
replica: None,
424-
tcp_timeout_ms: 1000, // 1 second
425-
connection_timeout: Duration::from_secs(1),
426-
statement_timeout: Duration::from_secs(1),
427-
helper_threads: 1,
428-
enforce_tls: false,
429434
};
430435

431436
let mut storage = StorageConfig::in_memory();

0 commit comments

Comments
 (0)