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//! - [`M0004`] - Replaces `idx_event_type` with a composite cursor-scan index
52//!
53//! # Database Schema
54//!
55//! After running all migrations, the database will contain:
56//!
57//! ## Event Table
58//!
59//! Stores all domain events:
60//!
61//! | Column | Type | Description |
62//! |--------|------|-------------|
63//! | `id` | VARCHAR(26) | Event ID (ULID format) |
64//! | `name` | VARCHAR(50) | Event type name |
65//! | `aggregator_type` | VARCHAR(50) | Aggregate root type |
66//! | `aggregator_id` | VARCHAR(26) | Aggregate root instance ID |
67//! | `version` | INTEGER | Event sequence number |
68//! | `data` | BLOB | Serialized event data |
69//! | `metadata` | BLOB | Serialized event metadata |
70//! | `routing_key` | VARCHAR(50) | Optional routing key |
71//! | `timestamp` | BIGINT | Event timestamp (seconds) |
72//! | `timestamp_subsec` | BIGINT | Sub-second precision |
73//!
74//! ## Subscriber Table
75//!
76//! Tracks event subscription progress:
77//!
78//! | Column | Type | Description |
79//! |--------|------|-------------|
80//! | `key` | VARCHAR(50) | Subscriber identifier (primary key) |
81//! | `worker_id` | VARCHAR(26) | Associated worker ID |
82//! | `cursor` | TEXT | Current event stream position |
83//! | `lag` | INTEGER | Subscription lag counter |
84//! | `enabled` | BOOLEAN | Whether subscription is active |
85//! | `created_at` | TIMESTAMP | Creation timestamp |
86//! | `updated_at` | TIMESTAMP | Last update timestamp |
87
88use sqlx_migrator::{Info, Migrator};
89
90mod m0001;
91mod m0002;
92mod m0003;
93mod m0004;
94
95pub use m0001::InitMigration;
96pub use m0002::M0002;
97pub use m0003::M0003;
98pub use m0004::M0004;
99
100/// Creates a new [`Migrator`] instance with all Evento migrations registered.
101///
102/// The migrator is generic over the database type and works with SQLite, MySQL, and PostgreSQL
103/// when the corresponding feature is enabled.
104///
105/// # Example
106///
107/// ```rust,ignore
108/// use sqlx_migrator::{Migrate, Plan};
109///
110/// // For SQLite
111/// let migrator = evento_sql_migrator::new::<sqlx::Sqlite>()?;
112///
113/// // For PostgreSQL
114/// let migrator = evento_sql_migrator::new::<sqlx::Postgres>()?;
115///
116/// // For MySQL
117/// let migrator = evento_sql_migrator::new::<sqlx::MySql>()?;
118///
119/// // Run migrations
120/// migrator.run(&mut *conn, &Plan::apply_all()).await?;
121/// ```
122///
123/// # Errors
124///
125/// Returns an error if migration registration fails.
126pub fn new<DB: sqlx::Database>() -> Result<Migrator<DB>, sqlx_migrator::Error>
127where
128 InitMigration: sqlx_migrator::Migration<DB>,
129 M0002: sqlx_migrator::Migration<DB>,
130 M0003: sqlx_migrator::Migration<DB>,
131 M0004: sqlx_migrator::Migration<DB>,
132{
133 let mut migrator = Migrator::default();
134 migrator.add_migration(Box::new(InitMigration))?;
135 migrator.add_migration(Box::new(M0002))?;
136 migrator.add_migration(Box::new(M0003))?;
137 migrator.add_migration(Box::new(M0004))?;
138
139 Ok(migrator)
140}