2026-07-19 01:20:18 +09:00
|
|
|
use std::time::Duration;
|
|
|
|
|
|
|
|
|
|
use remora_schema::{SCHEMA_GENERATION, generation, is_ready, migrate};
|
|
|
|
|
use sqlx::{PgPool, postgres::PgPoolOptions};
|
|
|
|
|
|
|
|
|
|
async fn test_pool() -> Option<PgPool> {
|
|
|
|
|
let Some(url) = std::env::var("DATABASE_URL")
|
|
|
|
|
.ok()
|
|
|
|
|
.filter(|value| !value.is_empty())
|
|
|
|
|
else {
|
|
|
|
|
if std::env::var("REMORA_SCHEMA_REQUIRE").is_ok() {
|
|
|
|
|
panic!("DATABASE_URL is required when REMORA_SCHEMA_REQUIRE is set");
|
|
|
|
|
}
|
|
|
|
|
return None;
|
|
|
|
|
};
|
|
|
|
|
Some(
|
|
|
|
|
PgPoolOptions::new()
|
|
|
|
|
.max_connections(12)
|
|
|
|
|
.acquire_timeout(Duration::from_secs(10))
|
|
|
|
|
.connect(&url)
|
|
|
|
|
.await
|
|
|
|
|
.expect("connect postgres"),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn migration_is_idempotent_and_marks_the_complete_generation() {
|
|
|
|
|
let Some(pool) = test_pool().await else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
migrate(&pool).await.expect("first migration");
|
|
|
|
|
migrate(&pool).await.expect("second migration");
|
|
|
|
|
assert_eq!(
|
|
|
|
|
generation(&pool).await.expect("schema generation"),
|
|
|
|
|
Some(SCHEMA_GENERATION)
|
|
|
|
|
);
|
|
|
|
|
assert!(is_ready(&pool).await.expect("schema readiness"));
|
|
|
|
|
|
2026-07-19 02:29:36 +09:00
|
|
|
let missing_tables: Vec<String> = sqlx::query_scalar(
|
|
|
|
|
"SELECT table_name
|
|
|
|
|
FROM unnest(ARRAY[
|
|
|
|
|
'mutation_records', 'principal_identities', 'source_credentials', 'jobs',
|
|
|
|
|
'attempts', 'result_inventories', 'deletion_operations',
|
|
|
|
|
'live_event_history_state', 'worker_descriptors', 'remora_schema_state'
|
|
|
|
|
]) AS expected(table_name)
|
|
|
|
|
WHERE to_regclass('public.' || table_name) IS NULL
|
|
|
|
|
ORDER BY table_name",
|
2026-07-19 01:20:18 +09:00
|
|
|
)
|
2026-07-19 02:29:36 +09:00
|
|
|
.fetch_all(&pool)
|
2026-07-19 01:20:18 +09:00
|
|
|
.await
|
|
|
|
|
.expect("schema tables");
|
2026-07-19 02:29:36 +09:00
|
|
|
assert!(
|
|
|
|
|
missing_tables.is_empty(),
|
|
|
|
|
"missing tables: {missing_tables:?}"
|
|
|
|
|
);
|
2026-07-19 01:20:18 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[tokio::test]
|
|
|
|
|
async fn concurrent_owners_converge_before_readiness() {
|
|
|
|
|
let Some(pool) = test_pool().await else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
let (first, second) = tokio::join!(migrate(&pool), migrate(&pool));
|
|
|
|
|
first.expect("first owner");
|
|
|
|
|
second.expect("second owner");
|
|
|
|
|
assert!(is_ready(&pool).await.expect("schema readiness"));
|
|
|
|
|
}
|