Files
AppFlowy/frontend/rust-lib/flowy-server/src/supabase/migration.rs
Nathan.fooo edc7933c66 feat: support pg storage (#2935)
* refactor: using tokio-postgres

* chore: update

* chore: update env

* chore: update

* chore: upgrade supabase and add logout button

* refactor: update

* chore: update

* refactor: using message queue to handle the pg connection

* refactor: move test

* refactor: update sql

* chore: create pg database when user login

* chore: update scheme

* chore: generic user service

* chore: update

* chore: create statistics

* chore: create snapshot

* chore: add test

* chore: add database cloud service

* chore: add document cloud service

* chore: update interface

* test: add document test

* refactor: document interface

* chore: fix test

* chore: update

* chore: update test

* test: add test

* test: add test

* test: add test

* chore: update collab rev

* fix: flutter analyzer

* chore: update

* chore: update

* chore: update

* fix: tests

* chore: update

* chore: update collab rev

* ci: rust fmt

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
2023-07-05 20:57:09 +08:00

101 lines
3.2 KiB
Rust

use refinery::embed_migrations;
use tokio_postgres::Client;
embed_migrations!("./src/supabase/migrations");
const AF_MIGRATION_HISTORY: &str = "af_migration_history";
pub(crate) async fn run_migrations(client: &mut Client) -> Result<(), anyhow::Error> {
match migrations::runner()
.set_migration_table_name(AF_MIGRATION_HISTORY)
.run_async(client)
.await
{
Ok(report) => {
if !report.applied_migrations().is_empty() {
tracing::info!("Run postgres db migration: {:?}", report);
}
Ok(())
},
Err(e) => {
tracing::error!("postgres db migration error: {}", e);
Err(anyhow::anyhow!("postgres db migration error: {}", e))
},
}
}
/// Drop all tables and dependencies defined in the v1_initial_up.sql.
/// Be careful when using this function. It will drop all tables and dependencies.
/// Mostly used for testing.
#[allow(dead_code)]
#[cfg(debug_assertions)]
pub(crate) async fn run_initial_drop(client: &Client) {
// let sql = include_str!("migrations/initial/initial_down.sql");
let sql = r#"DROP TABLE IF EXISTS af_user;
DROP TABLE IF EXISTS af_workspace;
DROP TABLE IF EXISTS af_user_profile;
DROP TABLE IF EXISTS af_collab;
DROP VIEW IF EXISTS af_collab_state;
DROP TABLE IF EXISTS af_collab_snapshot;
DROP TABLE IF EXISTS af_collab_statistics;
DROP TRIGGER IF EXISTS create_af_user_profile_trigger ON af_user_profile CASCADE;
DROP FUNCTION IF EXISTS create_af_user_profile_trigger_func;
DROP TRIGGER IF EXISTS create_af_workspace_trigger ON af_workspace CASCADE;
DROP FUNCTION IF EXISTS create_af_workspace_trigger_func;
DROP TRIGGER IF EXISTS af_collab_insert_trigger ON af_collab CASCADE;
DROP FUNCTION IF EXISTS increment_af_collab_update_count;
DROP TRIGGER IF EXISTS af_collab_snapshot_update_edit_count_trigger ON af_collab_snapshot;
DROP FUNCTION IF EXISTS af_collab_snapshot_update_edit_count;
DROP TRIGGER IF EXISTS check_and_delete_snapshots_trigger ON af_collab_snapshot CASCADE;
DROP FUNCTION IF EXISTS check_and_delete_snapshots;
"#;
client.batch_execute(sql).await.unwrap();
client
.batch_execute("DROP TABLE IF EXISTS af_migration_history")
.await
.unwrap();
}
#[cfg(test)]
mod tests {
use tokio_postgres::NoTls;
use crate::supabase::migration::run_initial_drop;
use crate::supabase::*;
// ‼️‼️‼️ Warning: this test will create a table in the database
#[tokio::test]
async fn test_postgres_db() -> Result<(), anyhow::Error> {
if dotenv::from_filename(".env.test.danger").is_err() {
return Ok(());
}
let configuration = PostgresConfiguration::from_env().unwrap();
let mut config = tokio_postgres::Config::new();
config
.host(&configuration.url)
.user(&configuration.user_name)
.password(&configuration.password)
.port(configuration.port);
// Using the https://docs.rs/postgres-openssl/latest/postgres_openssl/ to enable tls connection.
let (client, connection) = config.connect(NoTls).await?;
tokio::spawn(async move {
if let Err(e) = connection.await {
tracing::error!("postgres db connection error: {}", e);
}
});
#[cfg(debug_assertions)]
{
run_initial_drop(&client).await;
}
Ok(())
}
}