Skip to content

Commit

Permalink
Force db initialization on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
DimiDumo committed Sep 17, 2024
1 parent 547e6c4 commit 4e3b27d
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 12 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 32 additions & 1 deletion packages/relayer/src/database.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,19 @@ pub struct Database {

impl Database {
pub async fn open(path: &str) -> Result<Self> {
println!("Callin open database");
let res = Self {
db: PgPool::connect(path)
.await
.map_err(|e| anyhow::anyhow!(e))?,
};

println!("calling setup_database");

res.setup_database().await?;

println!("setup_database done");

Ok(res)
}

Expand Down Expand Up @@ -73,6 +78,31 @@ impl Database {
Ok(())
}

// This is a hacky way to make all subsequent uses of "pub static ref DB" work
// Since the DB ref will only be connected to the database after it was used once
// -> The first request always times out
pub(crate) async fn test_db_connection(&self) -> Result<()> {
// Try up to 3 times
for i in 1..4 {
match sqlx::query("SELECT 1").execute(&self.db).await {
Ok(_) => {
info!(LOG, "Connected successfully to database");
return Ok(());
}
Err(e) => {
error!(
LOG,
"Failed to initialize connection to the database: {:?}. Retrying...", e
);
tokio::time::sleep(Duration::from_secs(i * i)).await;
}
}
}
Err(anyhow::anyhow!(
"Failed to initialize database connection after 3 attempts"
))
}

pub(crate) async fn get_credentials(&self, account_code: &str) -> Result<Option<Credentials>> {
let row = sqlx::query("SELECT * FROM credentials WHERE account_code = $1")
.bind(account_code)
Expand Down Expand Up @@ -326,6 +356,7 @@ impl Database {
&self,
row: &Request,
) -> std::result::Result<(), DatabaseError> {
let request_id = row.request_id;
let row = sqlx::query(
"INSERT INTO requests (request_id, account_eth_addr, controller_eth_addr, guardian_email_addr, is_for_recovery, template_idx, is_processed, is_success, email_nullifier, account_salt) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *",
)
Expand All @@ -342,7 +373,7 @@ impl Database {
.fetch_one(&self.db)
.await
.map_err(|e| DatabaseError::new("Failed to insert request", e))?;
info!(LOG, "Request inserted");
info!(LOG, "Request inserted with request_id: {}", request_id);
Ok(())
}
}
32 changes: 21 additions & 11 deletions packages/relayer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub use modules::*;
use relayer_utils::LOG;
pub use strings::*;

use tokio::sync::Mutex;
use tokio::sync::{Mutex, OnceCell};

use anyhow::{anyhow, Result};
use dotenv::dotenv;
Expand All @@ -44,17 +44,27 @@ pub static EMAIL_TEMPLATES: OnceLock<String> = OnceLock::new();
pub static RELAYER_EMAIL_ADDRESS: OnceLock<String> = OnceLock::new();
pub static SMTP_SERVER: OnceLock<String> = OnceLock::new();

static DB_CELL: OnceCell<Arc<Database>> = OnceCell::const_new();

struct DBWrapper;

impl DBWrapper {
fn get() -> &'static Arc<Database> {
DB_CELL.get().expect("Database not initialized")
}
}

impl std::ops::Deref for DBWrapper {
type Target = Database;

fn deref(&self) -> &Self::Target {
&**Self::get()
}
}

static DB: DBWrapper = DBWrapper;

lazy_static! {
pub static ref DB: Arc<Database> = {
dotenv().ok();
let db = tokio::task::block_in_place(|| {
tokio::runtime::Runtime::new()
.unwrap()
.block_on(Database::open(&env::var(DATABASE_PATH_KEY).unwrap()))
})
.unwrap();
Arc::new(db)
};
pub static ref CLIENT: Arc<ChainClient> = {
dotenv().ok();
let client = tokio::task::block_in_place(|| {
Expand Down
19 changes: 19 additions & 0 deletions packages/relayer/src/modules/web_server/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,25 @@ use tower_http::cors::{AllowHeaders, AllowMethods, Any, CorsLayer};
pub async fn run_server() -> Result<()> {
let addr = WEB_SERVER_ADDRESS.get().unwrap();

println!("doing lazy_static init");

DB_CELL
.get_or_init(|| async {
dotenv::dotenv().ok();
let db = Database::open(&std::env::var("DATABASE_URL").unwrap())
.await
.unwrap();
Arc::new(db)
})
.await;

info!(LOG, "Testing connection to database");
if let Err(e) = DB.test_db_connection().await {
error!(LOG, "Failed to initialize db with e: {}", e);
panic!("Forcing panic, since connection to DB could not be established");
};
info!(LOG, "Testing connection to database successfull");

let mut app = Router::new()
.route(
"/api/echo",
Expand Down

0 comments on commit 4e3b27d

Please sign in to comment.