Skip to content

Commit e855c5c

Browse files
authored
client: make append visibility check deterministic (#48)
Merges the deterministic append-visibility check and full diagnostic sample reporting.
2 parents c8c32b1 + b2c5c8b commit e855c5c

1 file changed

Lines changed: 28 additions & 6 deletions

File tree

crates/ytsaurus-client/examples/append.rs

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,14 +242,20 @@ fn run() -> Result<(), ClientError> {
242242
raced(&client, &exclusive, false)? == 100,
243243
)?;
244244

245-
step("What a reader sees while an append is in flight");
245+
step("What a reader sees before an append commits");
246246
// Nothing, which is the answer that lets a reader poll `@row_count` without
247247
// a lock: the rows arrive with the upload transaction's commit, all at once.
248248
let inflight = format!("{BASE}/inflight");
249249
client.create("table", &inflight)?;
250250
client.write_table_rows(&inflight, entries(0..10))?;
251251
let body = encoded(entries(10..40));
252-
let (path, writing) = (inflight.clone(), client.clone());
252+
// This outer transaction is the cluster-held boundary for the samples.
253+
// The writer may finish while its thread is winding down, but the rows
254+
// cannot become visible until `commit` below. `is_finished` therefore only
255+
// decides when there are no more useful samples to take; it cannot let the
256+
// final one race the commit.
257+
let tx = client.start_transaction()?;
258+
let (path, writing) = (inflight.clone(), tx.client().clone());
253259
let upload = std::thread::spawn(move || {
254260
writing.write_table_streaming(TablePath::new(&path).append(), Trickle::new(body))
255261
});
@@ -260,12 +266,10 @@ fn run() -> Result<(), ClientError> {
260266
}
261267
upload.join().expect("the upload thread finished")?;
262268
check(
263-
&format!(
264-
"{} readings during the upload, every one of them 10",
265-
seen.len()
266-
),
269+
&readings_report(&seen),
267270
!seen.is_empty() && seen.iter().all(|&n| n == 10),
268271
)?;
272+
tx.commit()?;
269273
check("and 40 once it commits", client.row_count(&inflight)? == 40)?;
270274

271275
benchmark(&client)?;
@@ -447,6 +451,11 @@ fn first_line(message: &str) -> &str {
447451
message.lines().next().unwrap_or(message)
448452
}
449453

454+
/// What the in-flight check actually observed, including the values on failure.
455+
fn readings_report(readings: &[i64]) -> String {
456+
format!("readings before the transaction commits: {readings:?}")
457+
}
458+
450459
fn step(what: &str) {
451460
println!("\n== {what}");
452461
}
@@ -463,3 +472,16 @@ fn check(what: &str, passed: bool) -> Result<(), ClientError> {
463472
eprintln!(" FAIL {what}");
464473
Err(ClientError::Config(format!("check failed: {what}")))
465474
}
475+
476+
#[cfg(test)]
477+
mod tests {
478+
use super::readings_report;
479+
480+
#[test]
481+
fn readings_report_keeps_every_observation() {
482+
assert_eq!(
483+
readings_report(&[10, 10, 40]),
484+
"readings before the transaction commits: [10, 10, 40]"
485+
);
486+
}
487+
}

0 commit comments

Comments
 (0)