Skip to content
This repository was archived by the owner on Sep 20, 2024. It is now read-only.

Commit ac35b18

Browse files
committed
test database connection
1 parent 957ff1f commit ac35b18

File tree

5 files changed

+112
-8
lines changed

5 files changed

+112
-8
lines changed

Cargo.lock

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ authors = ["Espresso Systems <[email protected]>"]
55
edition = "2021"
66
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
77

8+
[dev-dependencies]
9+
hotshot-query-service = { git = "https://github.com/EspressoSystems/hotshot-query-service", tag = "rc-0.1.44" }
10+
811
[dependencies]
912
anyhow = "1"
1013
async-compatibility-layer = { version = "1.1", default-features = false, features = [
@@ -21,7 +24,7 @@ hotshot-events-service = { git = "https://github.com/EspressoSystems/hotshot-eve
2124
hotshot-types = { git = "https://github.com/EspressoSystems/HotShot.git", tag = "rc-0.5.61" }
2225
serde = { version = "1.0", features = ["derive"] }
2326
snafu = "0.8"
24-
sqlx = { version = "0.7.4", features = [ "postgres"] }
27+
sqlx = { version = "0.7.4", features = [ "postgres", "macros" ] }
2528
surf-disco = "0.9"
2629
tide-disco = "0.9"
2730
toml = "0.8.14"

migration/test.sql

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
CREATE TABLE test (
2-
id SERIAL PRIMARY KEY,
3-
);
2+
id SERIAL PRIMARY KEY,
3+
str text NOT NULL
4+
);

src/database.rs

+85-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
use sqlx::{pool::PoolConnection, postgres::PgPoolOptions, Error, PgPool, Postgres};
1+
use anyhow::Context;
2+
use sqlx::{
3+
pool::PoolConnection,
4+
postgres::{PgConnectOptions, PgPoolOptions},
5+
ConnectOptions, Error, PgPool, Postgres,
6+
};
7+
use tide_disco::Url;
28

39
use crate::DatabaseOptions;
410

@@ -8,13 +14,41 @@ impl PostgresClient {
814
pub async fn connect(opts: DatabaseOptions) -> anyhow::Result<Self> {
915
let DatabaseOptions {
1016
url,
17+
host,
18+
port,
19+
db_name,
20+
username,
21+
password,
1122
max_connections,
1223
acquire_timeout,
1324
migrations,
1425
} = opts;
1526

1627
let mut options = PgPoolOptions::new();
1728

29+
let postgres_url: Url = match url {
30+
Some(url) => url.parse()?,
31+
None => {
32+
let host = host.context("host not provided")?;
33+
let port = port.context("port not provided")?;
34+
let mut connect_opts = PgConnectOptions::new().host(&host).port(port);
35+
36+
if let Some(username) = username {
37+
connect_opts = connect_opts.username(&username);
38+
}
39+
40+
if let Some(password) = password {
41+
connect_opts = connect_opts.password(&password);
42+
}
43+
44+
if let Some(db_name) = db_name {
45+
connect_opts = connect_opts.database(&db_name);
46+
}
47+
48+
connect_opts.to_url_lossy()
49+
}
50+
};
51+
1852
if let Some(max_connections) = max_connections {
1953
options = options.max_connections(max_connections);
2054
}
@@ -23,7 +57,7 @@ impl PostgresClient {
2357
options = options.acquire_timeout(acquire_timeout);
2458
}
2559

26-
let connection = options.connect(&url).await?;
60+
let connection = options.connect(postgres_url.as_str()).await?;
2761

2862
if migrations {
2963
sqlx::migrate!("./migration").run(&connection).await?;
@@ -32,7 +66,56 @@ impl PostgresClient {
3266
Ok(Self(connection))
3367
}
3468

69+
pub fn pool(&self) -> &PgPool {
70+
&self.0
71+
}
72+
3573
pub async fn acquire(&self) -> Result<PoolConnection<Postgres>, Error> {
3674
self.0.acquire().await
3775
}
3876
}
77+
78+
#[cfg(all(test, not(target_os = "windows")))]
79+
mod test {
80+
use hotshot_query_service::data_source::sql::testing::TmpDb;
81+
82+
use super::PostgresClient;
83+
use crate::DatabaseOptions;
84+
85+
#[async_std::test]
86+
async fn test_database_connection() {
87+
let db = TmpDb::init().await;
88+
let host = db.host();
89+
let port = db.port();
90+
91+
let opts = DatabaseOptions {
92+
url: None,
93+
host: Some(host),
94+
port: Some(port),
95+
db_name: None,
96+
username: Some("postgres".to_string()),
97+
password: Some("password".to_string()),
98+
max_connections: Some(100),
99+
acquire_timeout: None,
100+
migrations: true,
101+
};
102+
103+
let client = PostgresClient::connect(opts)
104+
.await
105+
.expect("failed to connect to database");
106+
107+
let pool = client.pool();
108+
109+
sqlx::query("INSERT INTO test (str) VALUES ('testing');")
110+
.execute(pool)
111+
.await
112+
.unwrap();
113+
114+
let result: i64 = sqlx::query_scalar("Select id from test where str = 'testing';")
115+
.fetch_one(pool)
116+
.await
117+
.unwrap();
118+
119+
assert_eq!(result, 1);
120+
}
121+
}

src/options.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,26 @@ pub struct Options {
1616
/// Arguments for establishing a database connection
1717
#[derive(Clone, Debug, Parser)]
1818
pub struct DatabaseOptions {
19-
#[clap(long, env = "MARKETPLACE_SOLVER_DATABASE_URL")]
20-
pub url: String,
19+
// Postgres URL connection string
20+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_URL")]
21+
pub url: Option<String>,
2122

22-
#[clap(long, env = "MARKETPLACE_SOLVER_DATABASE_MAX_CONNECTIONS")]
23+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_HOST")]
24+
pub host: Option<String>,
25+
26+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_PORT")]
27+
pub port: Option<u16>,
28+
29+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_DATABASE_NAME")]
30+
pub db_name: Option<String>,
31+
32+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_USERNAME")]
33+
pub username: Option<String>,
34+
35+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_PASSWORD")]
36+
pub password: Option<String>,
37+
38+
#[clap(long, env = "MARKETPLACE_SOLVER_POSTGRES_MAX_CONNECTIONS")]
2339
pub max_connections: Option<u32>,
2440

2541
#[clap(long,value_parser = parse_duration, env = "MARKETPLACE_SOLVER_DATABASE_ACQUIRE_TIMEOUT")]

0 commit comments

Comments
 (0)