Skip to content

fix(spanner): include mutation_key in BeginTransaction RPC#5768

Open
olavloite wants to merge 2 commits into
googleapis:mainfrom
olavloite:spanner-mutation-key-in-explicit-begin
Open

fix(spanner): include mutation_key in BeginTransaction RPC#5768
olavloite wants to merge 2 commits into
googleapis:mainfrom
olavloite:spanner-mutation-key-in-explicit-begin

Conversation

@olavloite
Copy link
Copy Markdown
Contributor

The BeginTransaction RPC should include a mutation_key when a transaction is only writing mutations.

The BeginTransaction RPC should include a mutation_key when a transaction
is only writing mutations.
@olavloite olavloite requested review from a team as code owners May 27, 2026 13:24
@olavloite olavloite requested a review from sakthivelmanii May 27, 2026 13:24
@product-auto-label product-auto-label Bot added the api: spanner Issues related to the Spanner API. label May 27, 2026
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/spanner/src/mutation.rs
Comment thread src/spanner/src/mutation.rs
Comment thread src/spanner/Cargo.toml Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented May 27, 2026

Codecov Report

❌ Patch coverage is 98.71795% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.89%. Comparing base (265f1b4) to head (88dee17).

Files with missing lines Patch % Lines
src/spanner/src/mutation.rs 98.24% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@alvarowolfx alvarowolfx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some ideas to avoid mut variables and also use existing methods to pick a random item on a iterator.

Comment on lines +192 to +203
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;
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this can be more like this and avoid mut variables:

Suggested change
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);

Comment on lines +187 to +188
let idx = select_random_index(non_inserts.len());
return Some((*non_inserts[idx]).clone());
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can use the .choose method on iterators.

Suggested change
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());

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: spanner Issues related to the Spanner API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants