use std::sync::{Arc, Barrier};
use chio_settle::{DeadLetterRecord, SettlementFailureCode, SettlementFailureReason};
use chio_store_sqlite::dead_letters::SqliteDeadLetterStore;
use chio_store_sqlite::SqliteReceiptStore;
use chio_test_support::prelude::*;
const ROUNDS: u64 = 25;
fn permanent(receipt_id: &str, attempts: u32) -> DeadLetterRecord {
DeadLetterRecord::new(
receipt_id,
100,
attempts,
SettlementFailureReason::from_detail(SettlementFailureCode::Rpc, "permanent"),
)
}
#[test]
fn concurrent_identical_dead_letters_land_one_row() {
let dir = tempfile::tempdir().test_unwrap();
let db_path = dir.path().join("receipts.sqlite");
let receipts_a = SqliteReceiptStore::open(&db_path).test_unwrap();
let receipts_b = SqliteReceiptStore::open(&db_path).test_unwrap();
let store_a = Arc::new(SqliteDeadLetterStore::open_alongside(&receipts_a).test_unwrap());
let store_b = Arc::new(SqliteDeadLetterStore::open_alongside(&receipts_b).test_unwrap());
for round in 0..ROUNDS {
let receipt_id = format!("dl-race-{round}");
let barrier = Arc::new(Barrier::new(2));
let mut actors = Vec::new();
for store in [Arc::clone(&store_a), Arc::clone(&store_b)] {
let barrier = Arc::clone(&barrier);
let receipt_id = receipt_id.clone();
actors.push(std::thread::spawn(move || {
barrier.wait();
store
.insert(&permanent(&receipt_id, 3))
.test_expect("concurrent identical dead-letter must not error")
}));
}
let inserted: Vec<bool> = actors
.into_iter()
.map(|actor| actor.join().test_expect("dead-letter actor joins"))
.collect();
assert_eq!(
inserted.iter().filter(|new_row| **new_row).count(),
1,
"round {round}: exactly one of two identical concurrent dead-letters may report a new row, got {inserted:?}"
);
assert!(
!store_a
.insert(&permanent(&receipt_id, 3))
.test_expect("idempotent replay must not error"),
"round {round}: byte-identical dead-letter replay must report an existing row"
);
}
}