evento_sql_migrator/lib.rs
1//! SQL database migrations for the Evento event sourcing library.
2//!
3//! This crate provides database schema migrations required for storing events, snapshots,
4//! and subscriber state in SQL databases. It supports SQLite, MySQL, and PostgreSQL through
5//! feature flags.
6//!
7//! # Features
8//!
9//! - **`sqlite`** - Enables SQLite database support
10//! - **`mysql`** - Enables MySQL database support
11//! - **`postgres`** - Enables PostgreSQL database support
12//!
13//! All features are enabled by default. You can selectively enable only the databases you need:
14//!
15//! ```toml
16//! [dependencies]
17//! evento-sql-migrator = { version = "1.8", default-features = false, features = ["postgres"] }
18//! ```
19//!
20//! # Usage
21//!
22//! The main entry point is the [`new`] function, which creates a [`Migrator`]
23//! instance configured with all Evento migrations.
24//!
25//! ```rust,ignore
26//! use sqlx_migrator::{Migrate, Plan};
27//!
28//! // Acquire a database connection
29//! let mut conn = pool.acquire().await?;
30//!
31//! // Create the migrator for your database type
32//! let migrator = evento_sql_migrator::new::<sqlx::Sqlite>()?;
33//!
34//! // Run all pending migrations
35//! migrator.run(&mut *conn, &Plan::apply_all()).await?;
36//! ```
37//!
38//! When using the main `evento` crate, the migrator is re-exported:
39//!
40//! ```rust,ignore
41//! let migrator = evento::sql_migrator::new::<sqlx::Sqlite>()?;
42//! ```
43//!
44//! # Migrations
45//!
46//! The crate includes the following migrations:
47//!
48//! - [`InitMigration`] - Creates the initial database schema (event, snapshot, subscriber tables)
49//! - [`M0002`] - Adds `timestamp_subsec` column for sub-second precision timestamps
50//! - [`M0003`] - Drops the snapshot table and extends the event name column length
51//!
52//! # Database Schema
53//!
54//! After running all migrations, the database will contain:
55//!
56//! ## Event Table
57//!
58//! Stores all domain events:
59//!
60//! | Column | Type | Description |
61//! |--------|------|-------------|
62//! | `id` | VARCHAR(26) | Event ID (ULID format) |
63//! | `name` | VARCHAR(50) | Event type name |
64//! | `aggregator_type` | VARCHAR(50) | Aggregate root type |
65//! | `aggregator_id` | VARCHAR(26) | Aggregate root instance ID |
66//! | `version` | INTEGER | Event sequence number |
67//! | `data` | BLOB | Serialized event data |
68//! | `metadata` | BLOB | Serialized event metadata |
69//! | `routing_key` | VARCHAR(50) | Optional routing key |
70//! | `timestamp` | BIGINT | Event timestamp (seconds) |
71//! | `timestamp_subsec` | BIGINT | Sub-second precision |
72//!
73//! ## Subscriber Table
74//!
75//! Tracks event subscription progress:
76//!
77//! | Column | Type | Description |
78//! |--------|------|-------------|
79//! | `key` | VARCHAR(50) | Subscriber identifier (primary key) |
80//! | `worker_id` | VARCHAR(26) | Associated worker ID |
81//! | `cursor` | TEXT | Current event stream position |
82//! | `lag` | INTEGER | Subscription lag counter |
83//! | `enabled` | BOOLEAN | Whether subscription is active |
84//! | `created_at` | TIMESTAMP | Creation timestamp |
85//! | `updated_at` | TIMESTAMP | Last update timestamp |
86
87use sqlx_migrator::{Info, Migrator};
88
89mod m0001;
90mod m0002;
91mod m0003;
92
93pub use m0001::InitMigration;
94pub use m0002::M0002;
95pub use m0003::M0003;
96
97/// Creates a new [`Migrator`] instance with all Evento migrations registered.
98///
99/// The migrator is generic over the database type and works with SQLite, MySQL, and PostgreSQL
100/// when the corresponding feature is enabled.
101///
102/// # Example
103///
104/// ```rust,ignore
105/// use sqlx_migrator::{Migrate, Plan};
106///
107/// // For SQLite
108/// let migrator = evento_sql_migrator::new::<sqlx::Sqlite>()?;
109///
110/// // For PostgreSQL
111/// let migrator = evento_sql_migrator::new::<sqlx::Postgres>()?;
112///
113/// // For MySQL
114/// let migrator = evento_sql_migrator::new::<sqlx::MySql>()?;
115///
116/// // Run migrations
117/// migrator.run(&mut *conn, &Plan::apply_all()).await?;
118/// ```
119///
120/// # Errors
121///
122/// Returns an error if migration registration fails.
123pub fn new<DB: sqlx::Database>() -> Result<Migrator<DB>, sqlx_migrator::Error>
124where
125 InitMigration: sqlx_migrator::Migration<DB>,
126 M0002: sqlx_migrator::Migration<DB>,
127 M0003: sqlx_migrator::Migration<DB>,
128{
129 let mut migrator = Migrator::default();
130 migrator.add_migration(Box::new(InitMigration))?;
131 migrator.add_migration(Box::new(M0002))?;
132 migrator.add_migration(Box::new(M0003))?;
133
134 Ok(migrator)
135}