Wave-3 review gate: contract conformance clean; two findings fixed inline — substrate boundary move (open_writer_connection → seam.rs), writer-slot release on with_writer/begin/commit error arms + regression tests (task review-wave-3)
This commit is contained in:
1 parent
a82c543b40
commit
ecb8211694
8 files changed
+290
-34
No files matched your search
@@ -118,6 +118,47 @@ async fn notify_never_produces_payload_too_large() {
|
||||
cleanup(&dir);
|
||||
}
|
||||
|
||||
/// Acceptance: an auto-commit op's *error* arm releases the writer
|
||||
/// slot — the lease-out-both-arms property (ADR-007's seam posture):
|
||||
/// after a notify whose statement fails at the storage layer, the slot
|
||||
/// is free again and a subsequent writer op succeeds without parking.
|
||||
#[tokio::test(flavor = "multi_thread")]
|
||||
async fn failed_notify_releases_the_writer_slot() {
|
||||
let dir = temp_dir("err-arm-release");
|
||||
let path = temp_path("err-arm-release");
|
||||
let store = open_store(path.to_str().unwrap(), Default::default()).unwrap();
|
||||
|
||||
let side = rusqlite::Connection::open(&path).unwrap();
|
||||
side.execute_batch(
|
||||
"CREATE TRIGGER block_notify BEFORE INSERT ON __alkstore_notifications
|
||||
BEGIN SELECT RAISE(ABORT, 'notify insert blocked'); END",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let err = store.notify("orders", json!({"x": 1})).await.unwrap_err();
|
||||
let source = match &err {
|
||||
Error::Database(source) => source.to_string(),
|
||||
other => panic!("the induced failure surfaces as Database, got {other:?}"),
|
||||
};
|
||||
assert!(
|
||||
source.contains("notify insert blocked"),
|
||||
"the source chain carries the trigger's message, got: {source}"
|
||||
);
|
||||
side.execute_batch("DROP TRIGGER block_notify;").unwrap();
|
||||
drop(side);
|
||||
|
||||
let deadline = tokio::time::Instant::now() + Duration::from_secs(5);
|
||||
let landed = tokio::time::timeout_at(deadline, store.notify("orders", json!({"x": 2})))
|
||||
.await
|
||||
.expect(
|
||||
"the failed op must release the writer slot — the slot is free again, \
|
||||
never parked",
|
||||
);
|
||||
landed.expect("the notify lands after a failed op released the slot");
|
||||
store.close();
|
||||
cleanup(&dir);
|
||||
}
|
||||
|
||||
/// Acceptance: `listen` returns a working receiver — wakes arrive
|
||||
/// after commits by other connections, and `Wake { channel }` carries
|
||||
/// the channel name only. The honest posture: the watcher fans out on
|
||||
|
||||
Reference in new issue
Block a user