fix(sqlite): concurrent migrate retries
This commit is contained in:
@@ -56,3 +56,47 @@ async fn a_database_migrated_by_the_old_layout_migrates_again_cleanly() {
|
||||
|
||||
assert_eq!(ledger(&pool).await, LEDGER);
|
||||
}
|
||||
|
||||
async fn wal_pool(path: &Path, create: bool) -> SqlitePool {
|
||||
let opts = SqliteConnectOptions::new()
|
||||
.filename(path)
|
||||
.create_if_missing(create)
|
||||
.journal_mode(sqlx::sqlite::SqliteJournalMode::Wal)
|
||||
.busy_timeout(std::time::Duration::from_secs(5));
|
||||
SqlitePoolOptions::new()
|
||||
.max_connections(2)
|
||||
.connect_with(opts)
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn race_two_migrators(start: Option<&Path>) {
|
||||
for _ in 0..10 {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
let path = dir.path().join("race.db");
|
||||
if let Some(src) = start {
|
||||
std::fs::copy(src, &path).unwrap();
|
||||
}
|
||||
let a = wal_pool(&path, start.is_none()).await;
|
||||
let b = wal_pool(&path, false).await;
|
||||
|
||||
let (ra, rb) = tokio::join!(sqlite::migrate(&a), sqlite::migrate(&b));
|
||||
|
||||
ra.unwrap();
|
||||
rb.unwrap();
|
||||
assert_eq!(ledger(&a).await, LEDGER);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn two_processes_migrating_the_same_fresh_database_both_succeed() {
|
||||
race_two_migrators(None).await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn two_processes_migrating_a_database_at_the_old_version_both_succeed() {
|
||||
race_two_migrators(Some(
|
||||
&Path::new(env!("CARGO_MANIFEST_DIR")).join(PRE_MERGE_DB),
|
||||
))
|
||||
.await;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user