fix(spanner): include mutation_key in BeginTransaction RPC#5768
fix(spanner): include mutation_key in BeginTransaction RPC#5768olavloite wants to merge 2 commits into
Conversation
The BeginTransaction RPC should include a mutation_key when a transaction is only writing mutations.
There was a problem hiding this comment.
Code Review
This pull request implements mutation key selection to preserve blind write intent on multiplexed sessions by passing a selected mutation_key during explicit transaction initialization. It updates transaction-beginning methods across read_only_transaction.rs, read_write_transaction.rs, and result_set.rs to accept this optional key. Feedback on the changes suggests removing the newly introduced rand dependency in favor of a simpler, deterministic selection strategy (e.g., picking the first non-insert mutation). Additionally, the reviewer points out that matching on non-existent Operation::Send and Operation::Ack variants will cause compilation errors, and recommends removing the unused rand imports and dependencies.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5768 +/- ##
=======================================
Coverage 97.88% 97.89%
=======================================
Files 226 226
Lines 56447 56512 +65
=======================================
+ Hits 55255 55322 +67
+ Misses 1192 1190 -2 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
alvarowolfx
left a comment
There was a problem hiding this comment.
some ideas to avoid mut variables and also use existing methods to pick a random item on a iterator.
| let mut max_insert: Option<&crate::model::Mutation> = None; | ||
| let mut max_rows = 0; | ||
|
|
||
| for m in mutations { | ||
| if let Some(Operation::Insert(write)) = &m.operation { | ||
| let rows = write.values.len(); | ||
| if max_insert.is_none() || rows > max_rows { | ||
| max_insert = Some(m); | ||
| max_rows = rows; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Maybe this can be more like this and avoid mut variables:
| let mut max_insert: Option<&crate::model::Mutation> = None; | |
| let mut max_rows = 0; | |
| for m in mutations { | |
| if let Some(Operation::Insert(write)) = &m.operation { | |
| let rows = write.values.len(); | |
| if max_insert.is_none() || rows > max_rows { | |
| max_insert = Some(m); | |
| max_rows = rows; | |
| } | |
| } | |
| } | |
| let max_insert = mutations // Type: &[Mutation] (Slice) | |
| .iter() // 1. Converts to Iterator<Item = &Mutation> | |
| .filter_map(|m| match &m.operation { // 2. Filters and transforms | |
| Some(Operation::Insert(write)) => Some((m, write.values.len())), | |
| _ => None, | |
| }) // Now an Iterator<Item = (&Mutation, usize)> | |
| .max_by_key(|&(_, rows)| rows) // 3. Consumes iterator, returns Option<(&Mutation, usize)> | |
| .map(|(m, _)| m); |
| let idx = select_random_index(non_inserts.len()); | ||
| return Some((*non_inserts[idx]).clone()); |
There was a problem hiding this comment.
I think we can use the .choose method on iterators.
| let idx = select_random_index(non_inserts.len()); | |
| return Some((*non_inserts[idx]).clone()); | |
| use rand::seq::IteratorRandom; | |
| return non_inserts | |
| .iter() | |
| .choose(&mut rand::rng()) | |
| .map(|&&m| m.clone()); |
The BeginTransaction RPC should include a mutation_key when a transaction is only writing mutations.