esrs/sql/
migrations.rs

1use async_trait::async_trait;
2use sqlx::postgres::PgQueryResult;
3use sqlx::{Database, Error, Pool, Postgres, Transaction};
4
5use crate::{statement, Aggregate};
6
7/// Trait used to handle current code migrations.
8#[async_trait]
9pub trait MigrationsHandler<D>
10where
11    D: Database,
12{
13    async fn run<A>(pool: &Pool<D>) -> Result<(), Error>
14    where
15        A: Aggregate;
16}
17
18pub struct Migrations;
19
20#[async_trait]
21impl MigrationsHandler<Postgres> for Migrations {
22    async fn run<A>(pool: &Pool<Postgres>) -> Result<(), Error>
23    where
24        A: Aggregate,
25    {
26        let mut transaction: Transaction<Postgres> = pool.begin().await?;
27
28        let migrations: Vec<String> = vec![
29            statement!("postgres/migrations/01_create_table.sql", A),
30            statement!("postgres/migrations/02_create_index.sql", A),
31            statement!("postgres/migrations/03_create_unique_constraint.sql", A),
32            statement!("postgres/migrations/04_add_version.sql", A),
33        ];
34
35        for migration in migrations {
36            let _: PgQueryResult = sqlx::query(migration.as_str()).execute(&mut *transaction).await?;
37        }
38
39        transaction.commit().await
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use sqlx::{Pool, Postgres};
46
47    use crate::sql::migrations::{Migrations, MigrationsHandler};
48    use crate::Aggregate;
49
50    #[sqlx::test]
51    async fn can_read_postgres_migrations(pool: Pool<Postgres>) {
52        let result = Migrations::run::<TestAggregate>(&pool).await;
53        dbg!(&result);
54        assert!(result.is_ok());
55    }
56
57    #[derive(Debug, thiserror::Error)]
58    pub enum Error {}
59
60    pub struct TestAggregate;
61
62    #[derive(serde::Serialize, serde::Deserialize)]
63    pub struct TestEvent;
64
65    #[cfg(feature = "upcasting")]
66    impl crate::event::Upcaster for TestEvent {}
67
68    impl Aggregate for TestAggregate {
69        const NAME: &'static str = "test";
70        type State = ();
71        type Command = ();
72        type Event = TestEvent;
73        type Error = Error;
74
75        fn handle_command(_state: &Self::State, _command: Self::Command) -> Result<Vec<Self::Event>, Self::Error> {
76            Ok(vec![])
77        }
78
79        fn apply_event(_state: Self::State, _payload: Self::Event) -> Self::State {}
80    }
81}