[BE] Fixes #39: Spawn a connection on every request rather than having a db pool
This commit is contained in:
parent
778b0b9b95
commit
8fa36e00ec
1
backend/.gitignore
vendored
1
backend/.gitignore
vendored
@ -4,3 +4,4 @@ aulavirtual
|
||||
scraps
|
||||
request-logs
|
||||
.idea
|
||||
.directory
|
||||
|
@ -12,8 +12,8 @@ use rocket::{http::Status, serde::json::Json};
|
||||
|
||||
mod courses;
|
||||
|
||||
pub use courses::disenroll_user_options;
|
||||
pub use courses::disenroll_user;
|
||||
pub use courses::disenroll_user_options;
|
||||
|
||||
#[options("/classroom/user")]
|
||||
pub fn create_user_options() -> Status {
|
||||
|
@ -4,6 +4,7 @@ use log::{error, info};
|
||||
use reqwest::Client;
|
||||
use rocket::http::Status;
|
||||
use rocket::serde::json::Json;
|
||||
use sqlx::Connection;
|
||||
|
||||
use crate::json_result::JsonResult;
|
||||
use crate::model::person::{PersonCreate, PersonLink};
|
||||
|
@ -1,7 +1,8 @@
|
||||
use cors::Cors;
|
||||
use once_cell::sync::OnceCell;
|
||||
use sqlx::mysql::MySqlPoolOptions;
|
||||
use sqlx::Connection;
|
||||
use sqlx::MySql;
|
||||
use sqlx::MySqlConnection;
|
||||
use sqlx::Pool;
|
||||
use std::env;
|
||||
use std::time::Instant;
|
||||
@ -20,13 +21,13 @@ static DB: OnceCell<Pool<MySql>> = OnceCell::new();
|
||||
|
||||
/// Opens & returns a connection to the database
|
||||
///
|
||||
/// We don't use a connection pool because it often times out,
|
||||
/// we don't have a lot of traffic and reiniting the pool would
|
||||
/// require to change a lot of code in multiple places.
|
||||
pub async fn db() -> Result<&'static Pool<MySql>, String> {
|
||||
/// We don't use a connection pool because on some days, on the afternoon,
|
||||
/// the connections die and the user has to wait for all 5 connections
|
||||
/// in the pool to die and then wait for the new connections to be created.
|
||||
pub async fn db() -> Result<MySqlConnection, String> {
|
||||
/*
|
||||
Init DB and set it as a global variable
|
||||
* /
|
||||
*/
|
||||
let db_url = match env::var("DATABASE_URL") {
|
||||
Ok(url) => url,
|
||||
Err(_) => return Err("env DATABASE_URL not found".to_string()),
|
||||
@ -43,73 +44,6 @@ pub async fn db() -> Result<&'static Pool<MySql>, String> {
|
||||
Err("Error connecting to DB".to_string())
|
||||
}
|
||||
}
|
||||
// */
|
||||
|
||||
let attempts = 3;
|
||||
|
||||
for _ in 0..attempts {
|
||||
match DB.get() {
|
||||
Some(db) => {
|
||||
log::info!("DB active connections: {}", db.size());
|
||||
log::info!("DB num_idle connections: {}", db.num_idle());
|
||||
|
||||
return Ok(db);
|
||||
}
|
||||
None => {
|
||||
log::info!("DB not initialized, initializing from db()");
|
||||
let _ = init_db().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::error!("Failed to initialize DB after {} attempts", attempts);
|
||||
Err("Failed to initialize DB".to_string())
|
||||
}
|
||||
|
||||
pub async fn init_db() -> Result<(), String> {
|
||||
/*
|
||||
Init DB and set it as a global variable
|
||||
*/
|
||||
let db_url = match env::var("DATABASE_URL") {
|
||||
Ok(url) => url,
|
||||
Err(_) => return Err("env DATABASE_URL not found".to_string()),
|
||||
};
|
||||
|
||||
let start = Instant::now();
|
||||
let pool = MySqlPoolOptions::new()
|
||||
.max_connections(5)
|
||||
/*
|
||||
On some afternoons for some god forsaken reason the idle connections
|
||||
to the db stay alive, but stop responding.
|
||||
When this happens, we must restart the server, or wait for all
|
||||
the active connections to timeout.
|
||||
Here are some measures to circumvent that:
|
||||
*/
|
||||
// Set the maximum wait time for connections to 10 seconds
|
||||
// In practice, the slowest connections take 1.5 seconds to connect
|
||||
.acquire_timeout(std::time::Duration::from_secs(10))
|
||||
// Set the maximum idle time for connections to 10 minutes
|
||||
.idle_timeout(std::time::Duration::from_secs(10 * 60))
|
||||
.connect(db_url.as_str())
|
||||
.await;
|
||||
log::info!(
|
||||
"DB Pool connection took: {:?} ms",
|
||||
start.elapsed().as_millis()
|
||||
);
|
||||
|
||||
match pool {
|
||||
Ok(pool) => match DB.set(pool) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => {
|
||||
log::error!("Failed to set DB global variable");
|
||||
Err("Failed to set DB".to_string())
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::error!("Error connecting to DB: {}", e);
|
||||
Err("Error connecting to DB".to_string())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[launch]
|
||||
|
@ -35,7 +35,7 @@ impl Course {
|
||||
}
|
||||
};
|
||||
|
||||
let results = sqlx::query!("SELECT * FROM course").fetch_all(db).await;
|
||||
let results = sqlx::query!("SELECT * FROM course").fetch_all(&mut db).await;
|
||||
|
||||
let results = match results {
|
||||
Ok(res) => res,
|
||||
@ -71,7 +71,7 @@ impl Course {
|
||||
"SELECT course_name FROM course WHERE course_id = ?",
|
||||
course_id
|
||||
)
|
||||
.fetch_one(db)
|
||||
.fetch_one(&mut db)
|
||||
.await;
|
||||
|
||||
match res {
|
||||
|
@ -20,7 +20,7 @@ impl CustomLabel {
|
||||
FROM custom_label
|
||||
"#,
|
||||
)
|
||||
.fetch_all(db)
|
||||
.fetch_all(&mut db)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
@ -42,7 +42,7 @@ impl CustomLabel {
|
||||
"SELECT custom_label_id FROM custom_label WHERE custom_label_value = ?",
|
||||
value
|
||||
)
|
||||
.fetch_all(db)
|
||||
.fetch_all(&mut db)
|
||||
.await;
|
||||
|
||||
let result = match result {
|
||||
@ -72,7 +72,7 @@ impl CustomLabel {
|
||||
"INSERT INTO custom_label (custom_label_value) VALUES (?)",
|
||||
value
|
||||
)
|
||||
.execute(db)
|
||||
.execute(&mut db)
|
||||
.await;
|
||||
|
||||
if let Err(err) = result {
|
||||
|
@ -36,14 +36,14 @@ pub struct Person {
|
||||
|
||||
impl Person {
|
||||
pub async fn get_by_dni(dni: i32) -> Result<Person, DBError> {
|
||||
let db = match db().await {
|
||||
let mut db = match db().await {
|
||||
Ok(db) => db,
|
||||
Err(reason) => return Err(DBError::Str(reason)),
|
||||
};
|
||||
|
||||
let start = Instant::now();
|
||||
let result = sqlx::query_as!(Person, "SELECT * FROM person WHERE person_dni = ?", dni)
|
||||
.fetch_one(db)
|
||||
.fetch_one(&mut db)
|
||||
.await;
|
||||
log::info!(
|
||||
"DB query (person by dni) took: {:?} ms",
|
||||
@ -82,7 +82,7 @@ impl PersonCreate {
|
||||
self.person_paternal_surname,
|
||||
self.person_maternal_surname,
|
||||
)
|
||||
.execute(db)
|
||||
.execute(&mut db)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
@ -116,7 +116,7 @@ impl PersonLink {
|
||||
self.person_classroom_username,
|
||||
self.person_id,
|
||||
)
|
||||
.execute(db)
|
||||
.execute(&mut db)
|
||||
.await;
|
||||
|
||||
match res {
|
||||
|
@ -83,7 +83,7 @@ impl RegisterCreate {
|
||||
self.person_id,
|
||||
self.course_id
|
||||
)
|
||||
.execute(db)
|
||||
.execute(&mut db)
|
||||
.await;
|
||||
|
||||
match result {
|
||||
@ -107,7 +107,7 @@ impl RegisterCreate {
|
||||
WHERE register_course_id IN
|
||||
(SELECT course_id FROM course WHERE course_name LIKE 'Matpel%')",
|
||||
)
|
||||
.fetch_one(db)
|
||||
.fetch_one(&mut db)
|
||||
.await;
|
||||
|
||||
match res {
|
||||
@ -126,7 +126,7 @@ impl RegisterCreate {
|
||||
WHERE register_course_id=?",
|
||||
course_id
|
||||
)
|
||||
.fetch_one(db)
|
||||
.fetch_one(&mut db)
|
||||
.await;
|
||||
|
||||
match res {
|
||||
@ -345,7 +345,7 @@ impl Register {
|
||||
WHERE register_person_id = (SELECT person_id FROM person WHERE person_dni = ?)",
|
||||
dni
|
||||
)
|
||||
.fetch_all(db)
|
||||
.fetch_all(&mut db)
|
||||
.await;
|
||||
log::info!(
|
||||
"DB (get register by id) took: {:?} ms",
|
||||
@ -381,7 +381,7 @@ impl Register {
|
||||
let mut db = db().await?;
|
||||
|
||||
let res = sqlx::query!("DELETE FROM register WHERE register_id = ?", register_id)
|
||||
.execute(db)
|
||||
.execute(&mut db)
|
||||
.await;
|
||||
|
||||
match res {
|
||||
|
@ -3,7 +3,7 @@
|
||||
--c-on-error: #690005;
|
||||
--c-error-container: #93000a;
|
||||
--c-on-error-container: #ffdad6;
|
||||
|
||||
|
||||
--c-outline-50: rgba(143, 144, 154, 0.5);
|
||||
}
|
||||
|
||||
@ -32,20 +32,22 @@ body {
|
||||
|
||||
.progress {
|
||||
animation: progress 1s infinite linear;
|
||||
}
|
||||
|
||||
.left-right {
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
@keyframes progress {
|
||||
0% {
|
||||
transform: translateX(0) scaleX(0);
|
||||
}
|
||||
40% {
|
||||
transform: translateX(0) scaleX(0.4);
|
||||
}
|
||||
100% {
|
||||
transform: translateX(100%) scaleX(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.left-right {
|
||||
transform-origin: 0% 50%;
|
||||
}
|
||||
|
||||
@keyframes progress {
|
||||
0% {
|
||||
transform: translateX(0) scaleX(0);
|
||||
}
|
||||
|
||||
40% {
|
||||
transform: translateX(0) scaleX(0.4);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%) scaleX(0.5);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user