feat: event ids, outbox identity migration

This commit is contained in:
2026-10-25 23:57:24 +01:00
parent c31aa033cc
commit 32dfc84697
14 changed files with 287 additions and 39 deletions

View File

@@ -109,3 +109,84 @@ async fn claimed_rows_are_marked_processing_and_not_claimed_twice() {
let payloads: Vec<&str> = first.iter().map(|r| r.payload.as_str()).collect();
assert_eq!(payloads, ["p0", "p1", "p2"], "oldest first");
}
mod identity {
use domain::{
events::DomainEvent,
ports::{EventConsumer, EventPublisher},
value_objects::UserId,
};
use futures::StreamExt;
use sqlx::SqlitePool;
use super::{DbEventQueueConfig, config};
use crate::event_queue::SqliteEventQueue;
async fn queue() -> (SqliteEventQueue, SqlitePool) {
let pool = sqlx::sqlite::SqlitePoolOptions::new()
.max_connections(1)
.connect("sqlite::memory:")
.await
.unwrap();
crate::migrate(&pool).await.unwrap();
let cfg: DbEventQueueConfig = config(10);
(SqliteEventQueue::create(pool.clone(), cfg), pool)
}
fn event() -> DomainEvent {
DomainEvent::UserUpdated {
user_id: UserId::generate(),
}
}
#[tokio::test]
async fn published_events_get_a_unique_event_id() {
let (q, pool) = queue().await;
q.publish(&event()).await.unwrap();
q.publish(&event()).await.unwrap();
let ids: Vec<Option<String>> =
sqlx::query_scalar("SELECT event_id FROM event_queue ORDER BY id")
.fetch_all(&pool)
.await
.unwrap();
assert_eq!(ids.len(), 2);
let a = ids[0].as_deref().expect("first event has an id");
let b = ids[1].as_deref().expect("second event has an id");
assert_ne!(a, b);
uuid::Uuid::parse_str(a).expect("event id is a uuid");
}
#[tokio::test]
async fn the_consumer_surfaces_the_published_event_id() {
let (q, pool) = queue().await;
q.publish(&event()).await.unwrap();
let stored: String = sqlx::query_scalar("SELECT event_id FROM event_queue")
.fetch_one(&pool)
.await
.unwrap();
let envelope = q.consume().next().await.unwrap().unwrap();
assert_eq!(envelope.id().unwrap().value().to_string(), stored);
}
#[tokio::test]
async fn legacy_queue_rows_without_event_id_still_decode() {
let (q, pool) = queue().await;
let payload =
serde_json::to_string(&crate::event_queue::DbEventPayload::from(&event())).unwrap();
sqlx::query(
"INSERT INTO event_queue (event_type, payload, event_id) VALUES ('UserUpdated', ?, NULL)",
)
.bind(payload)
.execute(&pool)
.await
.unwrap();
let envelope = q.consume().next().await.unwrap().unwrap();
assert!(envelope.id().is_none());
}
}