about summary refs log tree commit diff stats
path: root/crates/rocie-server/src/storage/migrate/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/rocie-server/src/storage/migrate/mod.rs')
-rw-r--r--crates/rocie-server/src/storage/migrate/mod.rs72
1 files changed, 62 insertions, 10 deletions
diff --git a/crates/rocie-server/src/storage/migrate/mod.rs b/crates/rocie-server/src/storage/migrate/mod.rs
index ae0732b..5c81580 100644
--- a/crates/rocie-server/src/storage/migrate/mod.rs
+++ b/crates/rocie-server/src/storage/migrate/mod.rs
@@ -7,10 +7,15 @@ use chrono::TimeDelta;
 use log::{debug, info};
 use sqlx::{Sqlite, SqlitePool, Transaction, query};
 
-use crate::app::App;
+use crate::{
+    app::App,
+    storage::sql::{config::Config, get::config},
+};
+
+mod defaults;
 
 macro_rules! make_upgrade {
-    ($app:expr, $old_version:expr, $new_version:expr, $sql_name:expr) => {
+    ($app:expr, $old_version:expr, $new_version:expr, $sql_name:expr) => {{
         let mut tx = $app
             .db
             .begin()
@@ -57,8 +62,8 @@ macro_rules! make_upgrade {
                 new_version: $new_version,
             })?;
 
-        Ok(())
-    };
+        Ok::<_, update::Error>(())
+    }};
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
@@ -135,11 +140,12 @@ impl DbVersion {
     ///
     /// Each update is atomic, so if this function fails you are still guaranteed to have a
     /// database at version `get_version`.
-    #[allow(clippy::too_many_lines)]
     async fn update(self, app: &App) -> Result<(), update::Error> {
         match self {
             Self::Empty => {
-                make_upgrade! {app, Self::Empty, Self::One, "./sql/0->1.sql"}
+                make_upgrade! {app, Self::Empty, Self::One, "./sql/0->1.sql"}?;
+
+                Ok(())
             }
 
             // This is the current_version
@@ -158,7 +164,10 @@ impl Display for DbVersion {
     }
 }
 pub(crate) mod update {
-    use crate::storage::migrate::{DbVersion, db_version_set, get_db_version};
+    use crate::storage::{
+        migrate::{DbVersion, db_version_set, defaults, get_db_version},
+        sql::get::config,
+    };
 
     #[derive(thiserror::Error, Debug)]
     pub(crate) enum Error {
@@ -182,6 +191,11 @@ pub(crate) mod update {
         #[error("Failed to commit the update transaction: {0}")]
         TxnCommit(sqlx::Error),
 
+        #[error("Failed to access the rocie config: {0}")]
+        ConfigGet(#[from] config::get::Error),
+        #[error("Failed to add defaults to the database: {0}")]
+        AddDefaults(#[from] defaults::apply_defaults::Error),
+
         #[error("Failed to perform the next chained update (to ver {new_version}): {err}")]
         NextUpdate {
             err: Box<Self>,
@@ -197,6 +211,12 @@ pub(crate) mod db_version_parse {
     }
 }
 
+async fn should_use_defaults(app: &App) -> Result<bool, config::get::Error> {
+    let config = Config::get(app).await?;
+
+    Ok(config.should_use_defaults)
+}
+
 /// Returns the current data as UNIX time stamp.
 pub(crate) fn get_current_date() -> i64 {
     let start = SystemTime::now();
@@ -238,7 +258,7 @@ pub(crate) async fn get_version_db(pool: &SqlitePool) -> Result<DbVersion, get_d
         )
         .fetch_optional(pool)
         .await
-        .map_err(|err| get_db_version::Error::VersionTableExistance(err))?;
+        .map_err(get_db_version::Error::VersionTableExistance)?;
 
         if let Some(output) = query {
             assert_eq!(output.result, 1);
@@ -261,7 +281,7 @@ pub(crate) async fn get_version_db(pool: &SqlitePool) -> Result<DbVersion, get_d
     )
     .fetch_one(pool)
     .await
-    .map_err(|err| get_db_version::Error::VersionNumberFetch(err))?;
+    .map_err(get_db_version::Error::VersionNumberFetch)?;
 
     Ok(DbVersion::from_db(
         current_version.number,
@@ -288,6 +308,26 @@ pub(crate) mod get_db_version {
 pub(crate) async fn migrate_db(app: &App) -> Result<(), migrate_db::Error> {
     let current_version = get_version(app).await?;
 
+    if app.db_version_at_start.get().is_none() {
+        app.db_version_at_start
+            .set(current_version)
+            .expect("the cell to be unititialized, we checked");
+    }
+
+    if app.db_version_at_start.get() == Some(&DbVersion::Empty) {
+        // We cannot run this code in the normal update function, because for the empty db, there
+        // is no way to know if we want defaults.
+        //
+        // So we need to add the defaults later, which is achieved by another call to `migrate_db`
+        // in provision.
+        //
+        // That is kinda hacky, but I don't see a way around it.
+        // For defaults added in version Two and onward, the default mechanism should just work.
+        if should_use_defaults(app).await? {
+            defaults::add_defaults_0_to_1(app).await?;
+        }
+    }
+
     if current_version == CURRENT_VERSION {
         return Ok(());
     }
@@ -300,7 +340,12 @@ pub(crate) async fn migrate_db(app: &App) -> Result<(), migrate_db::Error> {
 }
 
 pub(crate) mod migrate_db {
-    use crate::storage::migrate::{get_db_version, update};
+    use actix_web::ResponseError;
+
+    use crate::storage::{
+        migrate::{defaults, get_db_version, update},
+        sql::get::config,
+    };
 
     #[derive(thiserror::Error, Debug)]
     pub(crate) enum Error {
@@ -309,5 +354,12 @@ pub(crate) mod migrate_db {
 
         #[error("Failed to update the database: {0}")]
         Upadate(#[from] update::Error),
+
+        #[error("Failed to access the rocie config: {0}")]
+        ConfigGet(#[from] config::get::Error),
+        #[error("Failed to add defaults to the database: {0}")]
+        AddDefaults(#[from] defaults::apply_defaults::Error),
     }
+
+    impl ResponseError for Error {}
 }