Skip to content

Commit 49bd49e

Browse files
committed
fix(spanner): ExcludeTransactionFromChangeStreamsOption not always propagated
1 parent 9bea3fc commit 49bd49e

File tree

2 files changed

+49
-0
lines changed

2 files changed

+49
-0
lines changed

google/cloud/spanner/internal/connection_impl.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,12 @@ StatusOr<google::spanner::v1::Transaction> ConnectionImpl::BeginTransaction(
580580

581581
auto stub = GetStubBasedOnSessionMode(*session, ctx);
582582
auto const& current = internal::CurrentOptions();
583+
584+
if (current.has<spanner::ExcludeTransactionFromChangeStreamsOption>() &&
585+
current.get<spanner::ExcludeTransactionFromChangeStreamsOption>()) {
586+
begin.mutable_options()->set_exclude_txn_from_change_streams(true);
587+
}
588+
583589
auto response = RetryLoop(
584590
RetryPolicyPrototype(current)->clone(),
585591
BackoffPolicyPrototype(current)->clone(), Idempotency::kIdempotent,

google/cloud/spanner/internal/connection_impl_test.cc

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,49 @@ TEST(ConnectionImplTest, CommitSuccessExcludeFromChangeStreams) {
32333233
Eq(spanner::MakeTimestamp(absl::FromUnixSeconds(123)).value()))));
32343234
}
32353235

3236+
// Reproduces issue b/346858290 where `exclude_txn_from_change_streams` is not
3237+
// propagated from the OptionsSpan to the BeginTransaction request.
3238+
TEST(ConnectionImplTest, CommitSuccessExcludeFromChangeStreamsExplicitTxn) {
3239+
auto mock = std::make_shared<spanner_testing::MockSpannerStub>();
3240+
auto db = spanner::Database("placeholder_project", "placeholder_instance",
3241+
"placeholder_database_id");
3242+
EXPECT_CALL(*mock, BatchCreateSessions(_, _, HasDatabase(db)))
3243+
.WillOnce(Return(MakeSessionsResponse({"test-session-name"})));
3244+
EXPECT_CALL(*mock, BeginTransaction)
3245+
.WillOnce(
3246+
[](grpc::ClientContext&, Options const&,
3247+
google::spanner::v1::BeginTransactionRequest const& request) {
3248+
EXPECT_TRUE(request.options().has_read_write());
3249+
EXPECT_TRUE(request.options().exclude_txn_from_change_streams());
3250+
return MakeTestTransaction();
3251+
});
3252+
EXPECT_CALL(*mock, Commit(_, _, HasSession("test-session-name")))
3253+
.WillOnce(Return(MakeCommitResponse(
3254+
spanner::MakeTimestamp(std::chrono::system_clock::from_time_t(123))
3255+
.value())));
3256+
EXPECT_CALL(*mock,
3257+
AsyncDeleteSession(_, _, _, HasSessionName("test-session-name")))
3258+
.WillOnce(Return(make_ready_future(Status{})));
3259+
3260+
auto conn = MakeConnectionImpl(db, mock);
3261+
internal::OptionsSpan span(
3262+
MakeLimitedTimeOptions()
3263+
.set<spanner::ExcludeTransactionFromChangeStreamsOption>(true));
3264+
3265+
// Introduce additional scope here to ensure that when txn is destroyed
3266+
// the session_pool contained by the Connection is still present, such that,
3267+
// the session associated with the transaction can be returned to the pool.
3268+
{
3269+
auto txn = spanner::Transaction(spanner::Transaction::ReadWriteOptions{});
3270+
auto commit = conn->Commit({txn, {}});
3271+
EXPECT_THAT(
3272+
commit,
3273+
IsOkAndHolds(Field(
3274+
&spanner::CommitResult::commit_timestamp,
3275+
Eq(spanner::MakeTimestamp(absl::FromUnixSeconds(123)).value()))));
3276+
}
3277+
}
3278+
32363279
TEST(ConnectionImplTest, CommitSuccessWithMaxCommitDelay) {
32373280
auto mock = std::make_shared<spanner_testing::MockSpannerStub>();
32383281
auto db = spanner::Database("placeholder_project", "placeholder_instance",

0 commit comments

Comments
 (0)