test(crawler): deflake sync serialization concurrency test #7
@@ -583,10 +583,18 @@ async fn sync_chapters_serializes_concurrent_calls_for_same_manga(pool: PgPool)
|
|||||||
.fetch_all(&pool)
|
.fetch_all(&pool)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(
|
// The per-manga advisory lock serializes the two calls, but it cannot
|
||||||
alive,
|
// dictate WHICH commits last (spawn order is not guaranteed — under load
|
||||||
vec!["A".to_string(), "B".to_string(), "C".to_string()],
|
// it inverts), so two correct last-writer-wins outcomes are possible:
|
||||||
"all chapters survive concurrent syncs that both contain them"
|
// - Y (list [A,B,C]) commits last → nothing dropped → [A,B,C].
|
||||||
|
// - X (list [A,B]) commits last → it soft-drops C, a key it never saw
|
||||||
|
// and which the next full sync re-adds → [A,B].
|
||||||
|
// The lock's job is to prevent a TORN result (a lost B, a half-applied
|
||||||
|
// drop), not to fix an order it cannot. Accept either serialization;
|
||||||
|
// anything else means the lock failed to serialize.
|
||||||
|
assert!(
|
||||||
|
alive == ["A", "B", "C"] || alive == ["A", "B"],
|
||||||
|
"concurrent syncs must leave a valid serialization, got {alive:?}"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user