Nice db split

This commit is contained in:
Adrian Woźniak 2023-06-06 17:02:42 +02:00
parent ca88ce1268
commit 37241b2357
16 changed files with 426 additions and 3395 deletions

1
Cargo.lock generated
View File

@ -3279,6 +3279,7 @@ name = "migration"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-std", "async-std",
"async-trait",
"clap 3.2.25", "clap 3.2.25",
"dotenv", "dotenv",
"sea-orm-migration", "sea-orm-migration",

View File

@ -14,6 +14,7 @@ clap = { version = "3.2.25", features = ['derive'] }
tracing = { version = "0.1.37" } tracing = { version = "0.1.37" }
tracing-subscriber = { version = "0.3.17", features = ['env-filter'] } tracing-subscriber = { version = "0.3.17", features = ['env-filter'] }
dotenv = { version = "0.15.0" } dotenv = { version = "0.15.0" }
async-trait = { version = "0.1.68" }
[dependencies.sea-orm-migration] [dependencies.sea-orm-migration]
version = "0.11.0" version = "0.11.0"

View File

@ -0,0 +1,22 @@
use sea_orm::Iterable;
use sea_orm_migration::prelude::*;
use crate::extension::postgres::Type;
use crate::types::*;
use crate::{create_type, drop_type};
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
create_type!(manager, CartType);
Ok(())
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
drop_type!(manager, CartType);
Ok(())
}
}

View File

@ -0,0 +1,104 @@
use sea_orm_migration::prelude::*;
use sea_query::expr::SimpleExpr;
/// ```sql
/// id character varying NOT NULL,
/// email character varying,
/// billing_address_id character varying,
/// shipping_address_id character varying,
/// region_id character varying NOT NULL,
/// customer_id character varying,
/// payment_id character varying,
/// type public.cart_types DEFAULT 'default'::public.cart_types NOT NULL,
/// completed_at timestamp with time zone,
/// created_at timestamp with time zone DEFAULT now() NOT NULL,
/// updated_at timestamp with time zone DEFAULT now() NOT NULL,
/// deleted_at timestamp with time zone,
/// metadata jsonb,
/// idempotency_key character varying,
/// context jsonb,
/// payment_authorized_at timestamp with time zone,
/// sales_channel_id character varying
/// ```
#[derive(DeriveMigrationName)]
pub struct Migration;
#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.create_table(
Table::create()
.table(Cart::Carts)
.col(
ColumnDef::new(Cart::Id)
.uuid()
.not_null()
.default(SimpleExpr::Custom("public.uuid_generate_v4()".into()))
.primary_key(),
)
.col(ColumnDef::new(Cart::Email).string())
.col(ColumnDef::new(Cart::BillingAddressId).uuid())
.col(ColumnDef::new(Cart::ShippingAddressId).uuid())
.col(ColumnDef::new(Cart::RegionId).uuid().not_null())
.col(ColumnDef::new(Cart::CustomerId).uuid())
.col(ColumnDef::new(Cart::PaymentId).uuid())
.col(
ColumnDef::new(Cart::CartType)
.string()
.default(SimpleExpr::Custom("'default'::public.cart_types".into()))
.not_null(),
)
.col(ColumnDef::new(Cart::CompletedAt).timestamp())
.col(
ColumnDef::new(Cart::CreatedAt)
.timestamp()
.default(SimpleExpr::Custom("now()".into()))
.not_null(),
)
.col(
ColumnDef::new(Cart::UpdatedAt)
.timestamp()
.default(SimpleExpr::Custom("now()".into()))
.not_null(),
)
.col(ColumnDef::new(Cart::DeletedAt).timestamp())
.col(ColumnDef::new(Cart::Metadata).json_binary())
.col(ColumnDef::new(Cart::IdempotencyKey).uuid())
.col(ColumnDef::new(Cart::Context).json_binary())
.col(ColumnDef::new(Cart::PaymentAuthorizedAt).timestamp())
.col(ColumnDef::new(Cart::SalesChannelId).uuid())
.to_owned(),
)
.await
}
async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.drop_table(Table::drop().table(Cart::Carts).to_owned())
.await?;
Ok(())
}
}
#[derive(Iden)]
enum Cart {
Carts,
Id,
Email,
BillingAddressId,
ShippingAddressId,
RegionId,
CustomerId,
PaymentId,
CartType,
CompletedAt,
CreatedAt,
UpdatedAt,
DeletedAt,
Metadata,
IdempotencyKey,
Context,
PaymentAuthorizedAt,
SalesChannelId,
}

View File

@ -0,0 +1,16 @@
use sea_orm_migration::{MigrationTrait, MigratorTrait};
mod m20230603_102634_types;
mod m20230603_120814_carts;
pub struct CartsMigrator;
#[async_trait::async_trait]
impl MigratorTrait for CartsMigrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20230603_102634_types::Migration),
Box::new(m20230603_120814_carts::Migration),
]
}
}

View File

@ -1,23 +1,12 @@
use sea_orm_migration::prelude::*; use sea_orm_migration::prelude::*;
use sea_orm_migration::sea_orm::Statement;
use sea_query::expr::SimpleExpr; use sea_query::expr::SimpleExpr;
use crate::sea_orm::DatabaseBackend;
#[derive(DeriveMigrationName)] #[derive(DeriveMigrationName)]
pub struct Migration; pub struct Migration;
#[async_trait::async_trait] #[async_trait::async_trait]
impl MigrationTrait for Migration { impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.get_connection()
.execute(Statement::from_string(
DatabaseBackend::Postgres,
"CREATE EXTENSION \"uuid-ossp\"".to_string(),
))
.await?;
manager manager
.create_table( .create_table(
Table::create() Table::create()
@ -41,7 +30,7 @@ impl MigrationTrait for Migration {
ColumnDef::new(BatchJob::Id) ColumnDef::new(BatchJob::Id)
.uuid() .uuid()
.not_null() .not_null()
.default(SimpleExpr::Custom("uuid_generate_v4()".into())) .default(SimpleExpr::Custom("public.uuid_generate_v4()".into()))
.primary_key(), .primary_key(),
) )
.col(ColumnDef::new(BatchJob::BatchType).string().not_null()) .col(ColumnDef::new(BatchJob::BatchType).string().not_null())

13
migration/src/jobs/mod.rs Normal file
View File

@ -0,0 +1,13 @@
use sea_orm_migration::{MigrationTrait, MigratorTrait};
pub mod m20230603_120814_batch_jobs;
pub struct JobsMigrator;
#[async_trait::async_trait]
impl MigratorTrait for JobsMigrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
eprintln!("JobsMigrator");
vec![Box::new(m20230603_120814_batch_jobs::Migration)]
}
}

View File

@ -1,30 +1,7 @@
pub use sea_orm_migration::prelude::*; pub use sea_orm_migration::prelude::*;
mod m20230603_102630_schema; pub mod carts;
mod m20230603_102634_types; pub mod jobs;
mod m20230603_120814_addresses; pub mod public;
mod m20230603_120814_jobs;
pub mod schema_list; pub mod schema_list;
pub mod types; pub mod types;
pub struct PublicMigrator;
#[async_trait::async_trait]
impl MigratorTrait for PublicMigrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![
Box::new(m20230603_102630_schema::Migration),
Box::new(m20230603_102634_types::Migration),
Box::new(m20230603_120814_addresses::Migration),
]
}
}
pub struct JobsMigrator;
#[async_trait::async_trait]
impl MigratorTrait for JobsMigrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
vec![Box::new(m20230603_120814_jobs::Migration)]
}
}

View File

@ -20,14 +20,27 @@ async fn main() {
init_logger(cli.verbose); init_logger(cli.verbose);
cli.database_schema = Some(PostgreSQLSchema::Public.as_str().into()); run_cli(
run_cli(&cli, migration::PublicMigrator).await; &mut cli,
PostgreSQLSchema::Public,
cli.database_schema = Some(PostgreSQLSchema::Jobs.as_str().into()); migration::public::PublicMigrator,
run_cli(&cli, migration::JobsMigrator).await; )
.await;
run_cli(
&mut cli,
PostgreSQLSchema::Jobs,
migration::jobs::JobsMigrator,
)
.await;
run_cli(
&mut cli,
PostgreSQLSchema::Carts,
migration::carts::CartsMigrator,
)
.await;
} }
pub async fn run_cli<M>(cli: &Cli, migrator: M) pub async fn run_cli<M>(cli: &mut Cli, schema: PostgreSQLSchema, migrator: M)
where where
M: MigratorTrait, M: MigratorTrait,
{ {
@ -35,22 +48,25 @@ where
.database_url .database_url
.as_ref() .as_ref()
.expect("Environment variable 'DATABASE_URL' not set"); .expect("Environment variable 'DATABASE_URL' not set");
let schema = cli
.database_schema
.as_ref()
.cloned()
.unwrap_or_else(|| "public".to_owned());
let schema = schema.as_str().to_string();
let connect_options = ConnectOptions::new(url.clone()) let connect_options = ConnectOptions::new(url.clone())
.set_schema_search_path(schema) .set_schema_search_path(schema.clone())
.to_owned(); .to_owned();
let db = &Database::connect(connect_options) let db = Database::connect(connect_options)
.await .await
.expect("Fail to acquire database connection"); .expect("Fail to acquire database connection");
run_migrate(migrator, db, cli.command.clone()) db.execute_unprepared(&format!("SET search_path = '{}'", schema))
.await .await
.unwrap_or_else(handle_error); .unwrap();
let res = run_migrate(migrator, &db, cli.command.clone()).await;
if cfg!(debug_assertions) {
res.unwrap();
} else {
res.unwrap_or_else(handle_error);
}
} }
pub async fn run_migrate<M>( pub async fn run_migrate<M>(
@ -83,7 +99,7 @@ where
fn init_logger(verbose: bool) { fn init_logger(verbose: bool) {
let filter = match verbose { let filter = match verbose {
true => "debug", true => "debug",
false => "sea_orm_migration=info", false => "sea_orm_migration=trace",
}; };
let filter_layer = EnvFilter::try_new(filter).unwrap(); let filter_layer = EnvFilter::try_new(filter).unwrap();
@ -96,8 +112,8 @@ fn init_logger(verbose: bool) {
.init() .init()
} else { } else {
let fmt_layer = tracing_subscriber::fmt::layer() let fmt_layer = tracing_subscriber::fmt::layer()
.with_target(false) .with_target(true)
.with_level(false) .with_level(true)
.without_time(); .without_time();
tracing_subscriber::registry() tracing_subscriber::registry()
.with(filter_layer) .with(filter_layer)
@ -120,18 +136,6 @@ pub struct Cli {
#[clap(action, short = 'v', long, global = true, help = "Show debug messages")] #[clap(action, short = 'v', long, global = true, help = "Show debug messages")]
verbose: bool, verbose: bool,
#[clap(
value_parser,
global = true,
short = 's',
long,
env = "DATABASE_SCHEMA",
long_help = "Database schema\n \
- For MySQL and SQLite, this argument is ignored.\n \
- For PostgreSQL, this argument is optional with default value 'public'.\n"
)]
database_schema: Option<String>,
#[clap( #[clap(
value_parser, value_parser,
global = true, global = true,
@ -173,18 +177,6 @@ you should provide the directory of that submodule.",
)] )]
migration_dir: String, migration_dir: String,
#[clap(
value_parser,
global = true,
short = 's',
long,
env = "DATABASE_SCHEMA",
long_help = "Database schema\n \
- For MySQL and SQLite, this argument is ignored.\n \
- For PostgreSQL, this argument is optional with default value 'public'.\n"
)]
database_schema: Option<String>,
#[clap( #[clap(
value_parser, value_parser,
global = true, global = true,

View File

@ -3,32 +3,7 @@ use sea_orm_migration::prelude::*;
use crate::extension::postgres::Type; use crate::extension::postgres::Type;
use crate::types::*; use crate::types::*;
use crate::{create_type, drop_type};
macro_rules! create_type {
($manager: ident, $ty: ident) => {
$manager
.create_type(
Type::create()
.as_enum($ty::iter().next().unwrap())
.values($ty::iter().skip(1))
.to_owned(),
)
.await?;
};
}
macro_rules! drop_type {
($manager: ident, $ty: ident) => {
$manager
.drop_type(
Type::drop()
.if_exists()
.cascade()
.name($ty::iter().next().unwrap())
.to_owned(),
)
.await?;
};
}
#[derive(DeriveMigrationName)] #[derive(DeriveMigrationName)]
pub struct Migration; pub struct Migration;

View File

@ -0,0 +1,19 @@
use sea_orm_migration::{MigrationTrait, MigratorTrait};
mod m20230603_102630_schema;
mod m20230603_102634_types;
mod m20230603_120814_addresses;
pub struct PublicMigrator;
#[async_trait::async_trait]
impl MigratorTrait for PublicMigrator {
fn migrations() -> Vec<Box<dyn MigrationTrait>> {
eprintln!("PublicMigrator");
vec![
Box::new(m20230603_102630_schema::Migration),
Box::new(m20230603_102634_types::Migration),
Box::new(m20230603_120814_addresses::Migration),
]
}
}

View File

@ -6,6 +6,7 @@ use sea_orm_migration::prelude::*;
pub enum PostgreSQLSchema { pub enum PostgreSQLSchema {
Public, Public,
Jobs, Jobs,
Carts,
} }
impl PostgreSQLSchema { impl PostgreSQLSchema {
@ -13,6 +14,7 @@ impl PostgreSQLSchema {
match self { match self {
PostgreSQLSchema::Public => "public", PostgreSQLSchema::Public => "public",
PostgreSQLSchema::Jobs => "jobs", PostgreSQLSchema::Jobs => "jobs",
PostgreSQLSchema::Carts => "carts",
} }
} }
} }

View File

@ -1,6 +1,34 @@
use sea_orm::EnumIter; use sea_orm::EnumIter;
use sea_orm_migration::prelude::*; use sea_orm_migration::prelude::*;
#[macro_export]
macro_rules! create_type {
($manager: ident, $ty: ident) => {
$manager
.create_type(
Type::create()
.as_enum($ty::iter().next().unwrap())
.values($ty::iter().skip(1))
.to_owned(),
)
.await?;
};
}
#[macro_export]
macro_rules! drop_type {
($manager: ident, $ty: ident) => {
$manager
.drop_type(
Type::drop()
.if_exists()
.cascade()
.name($ty::iter().next().unwrap())
.to_owned(),
)
.await?;
};
}
#[derive(Iden, EnumIter)] #[derive(Iden, EnumIter)]
pub enum PaymentCollectionStatus { pub enum PaymentCollectionStatus {
PaymentCollectionStatuses, PaymentCollectionStatuses,

File diff suppressed because it is too large Load Diff