Skip to content

Commit 12ddf77

Browse files
authored
impl(spanner): promote from experimental and document multiplexed session support (#15366)
1 parent 19728fa commit 12ddf77

File tree

7 files changed

+43
-37
lines changed

7 files changed

+43
-37
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ breaking changes in the upcoming 3.x release. This release is scheduled for
66

77
## v2.41.0 - TBD
88

9+
### [Spanner](/google/cloud/spanner/README.md)
10+
11+
- [Multiplexed session](https://cloud.google.com/spanner/docs/sessions#multiplexed_sessions)
12+
support is now available. To enable Multiplexed sessions, add the
13+
`spanner::EnableMultiplexedSessionOption` to `Options` when calling
14+
`spanner::MakeConnection`. This enables Multiplexed sessions on all operations
15+
read-only, read-write, and partitioned.
16+
917
## v2.40.0 - 2025-08
1018

1119
### New Libraries

google/cloud/spanner/integration_tests/client_integration_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ class ClientIntegrationTest : public spanner_testing::DatabaseIntegrationTest {
5555
auto session_mode =
5656
internal::GetEnv("GOOGLE_CLOUD_CPP_SPANNER_TESTING_SESSION_MODE");
5757
if (session_mode.has_value() && *session_mode == "multiplexed") {
58-
options.set<spanner_experimental::EnableMultiplexedSessionOption>({});
58+
options.set<spanner::EnableMultiplexedSessionOption>({});
5959
}
6060
client_ = std::make_unique<Client>(
6161
MakeConnection(GetDatabase(), std::move(options)));

google/cloud/spanner/internal/connection_impl.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,7 @@ Status ConnectionImpl::PrepareSession(SessionHolder& session,
529529
Session::Mode mode) {
530530
if (!session) {
531531
StatusOr<SessionHolder> session_or;
532-
if (opts_.has<spanner_experimental::EnableMultiplexedSessionOption>()) {
532+
if (opts_.has<spanner::EnableMultiplexedSessionOption>()) {
533533
session_or = session_pool_->Multiplexed(mode);
534534
} else {
535535
session_or = session_pool_->Allocate(mode);

google/cloud/spanner/internal/connection_impl_test.cc

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2169,8 +2169,7 @@ TEST(ConnectionImplTest, MultiplexedExecuteBatchDmlSuccess) {
21692169
spanner::SqlStatement("UPDATE ..."),
21702170
};
21712171

2172-
auto options =
2173-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({});
2172+
auto options = Options{}.set<spanner::EnableMultiplexedSessionOption>({});
21742173
auto conn = MakeConnectionImpl(db, mock, options);
21752174
internal::OptionsSpan span(MakeLimitedTimeOptions());
21762175
auto txn = spanner::MakeReadWriteTransaction(
@@ -2945,8 +2944,7 @@ TEST(ConnectionImplTest, MutationCommitSuccess) {
29452944
commit_timestamp, spanner::CommitStats{request.mutations_size()});
29462945
});
29472946

2948-
auto options =
2949-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({});
2947+
auto options = Options{}.set<spanner::EnableMultiplexedSessionOption>({});
29502948
auto conn = MakeConnectionImpl(db, mock, options);
29512949
internal::OptionsSpan span(MakeLimitedTimeOptions());
29522950
auto commit = conn->Commit({spanner::MakeReadWriteTransaction(), mutations,
@@ -3017,8 +3015,7 @@ TEST(ConnectionImplTest, MutationCommitRetryOnceSuccess) {
30173015
commit_timestamp, spanner::CommitStats{original_mutations_size});
30183016
});
30193017

3020-
auto options =
3021-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({});
3018+
auto options = Options{}.set<spanner::EnableMultiplexedSessionOption>({});
30223019
auto conn = MakeConnectionImpl(db, mock, options);
30233020
internal::OptionsSpan span(MakeLimitedTimeOptions());
30243021
auto commit = conn->Commit({spanner::MakeReadWriteTransaction(), mutations,
@@ -3103,8 +3100,7 @@ TEST(ConnectionImplTest, MutationCommitRetryMoreThanOnceSuccess) {
31033100
commit_timestamp, spanner::CommitStats{original_mutations_size});
31043101
});
31053102

3106-
auto options =
3107-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({});
3103+
auto options = Options{}.set<spanner::EnableMultiplexedSessionOption>({});
31083104
auto conn = MakeConnectionImpl(db, mock, options);
31093105
internal::OptionsSpan span(MakeLimitedTimeOptions());
31103106
auto commit = conn->Commit({spanner::MakeReadWriteTransaction(), mutations,
@@ -3188,8 +3184,7 @@ TEST(ConnectionImplTest, MultiplexedPrecommitUpdated) {
31883184
});
31893185
}
31903186

3191-
auto options =
3192-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({});
3187+
auto options = Options{}.set<spanner::EnableMultiplexedSessionOption>({});
31933188
auto conn = MakeConnectionImpl(db, mock, options);
31943189
internal::OptionsSpan span(MakeLimitedTimeOptions());
31953190
spanner::Transaction txn =

google/cloud/spanner/internal/session_pool.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ SessionPool::SessionPool(spanner::Database db,
9494

9595
void SessionPool::Initialize() {
9696
internal::OptionsSpan span(opts_);
97-
if (opts_.has<spanner_experimental::EnableMultiplexedSessionOption>()) {
97+
if (opts_.has<spanner::EnableMultiplexedSessionOption>()) {
9898
std::unique_lock<std::mutex> lk(mu_);
9999
CreateMultiplexedSession(lk);
100100
ScheduleMultiplexedBackgroundWork(multiplexed_session_background_interval_);
@@ -120,7 +120,7 @@ SessionPool::~SessionPool() {
120120
// they must not have successfully finished a call to `lock()` on the
121121
// `weak_ptr` to `this` they hold. Any in-progress or subsequent `lock()`
122122
// will now return `nullptr`, in which case no work is done.
123-
if (opts_.has<spanner_experimental::EnableMultiplexedSessionOption>()) {
123+
if (opts_.has<spanner::EnableMultiplexedSessionOption>()) {
124124
current_multiplexed_timer_.cancel();
125125
} else {
126126
current_timer_.cancel();
@@ -442,7 +442,7 @@ StatusOr<SessionHolder> SessionPool::Allocate(Session::Mode mode) {
442442
}
443443

444444
StatusOr<SessionHolder> SessionPool::Multiplexed(Session::Mode mode) {
445-
if (opts_.has<spanner_experimental::EnableMultiplexedSessionOption>()) {
445+
if (opts_.has<spanner::EnableMultiplexedSessionOption>()) {
446446
std::unique_lock<std::mutex> lk(mu_);
447447
if (mode == Session::Mode::kDisassociated && multiplexed_session_.ok()) {
448448
// For disassociated sessions, only used in partitioned operations, we do

google/cloud/spanner/internal/session_pool_test.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ TEST_F(SessionPoolTest, Multiplexed) {
164164
google::cloud::internal::AutomaticallyCreatedBackgroundThreads threads;
165165
auto pool = MakeTestSessionPool(
166166
db, {mock}, threads.cq(),
167-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
167+
Options{}.set<spanner::EnableMultiplexedSessionOption>({}));
168168
auto session = pool->Multiplexed();
169169
ASSERT_STATUS_OK(session);
170170
EXPECT_EQ((*session)->session_name(), "multiplexed");
@@ -188,7 +188,7 @@ TEST_F(SessionPoolTest, MultiplexedAllocateRouteToLeader) {
188188
db, {mock}, threads.cq(),
189189
Options{}
190190
.set<spanner::RouteToLeaderOption>(true)
191-
.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
191+
.set<spanner::EnableMultiplexedSessionOption>({}));
192192
auto session = pool->Multiplexed();
193193
ASSERT_STATUS_OK(session);
194194
EXPECT_EQ((*session)->session_name(), "multiplexed");
@@ -241,7 +241,7 @@ TEST_F(SessionPoolTest, MultiplexedAllocateNoRouteToLeader) {
241241
db, {mock}, threads.cq(),
242242
Options{}
243243
.set<spanner::RouteToLeaderOption>(false)
244-
.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
244+
.set<spanner::EnableMultiplexedSessionOption>({}));
245245
auto session = pool->Multiplexed();
246246
ASSERT_STATUS_OK(session);
247247
EXPECT_EQ((*session)->session_name(), "multiplexed");
@@ -324,7 +324,7 @@ TEST_F(SessionPoolTest, MultiplexedCreateError) {
324324
google::cloud::internal::AutomaticallyCreatedBackgroundThreads threads;
325325
auto pool = MakeTestSessionPool(
326326
db, {mock}, threads.cq(),
327-
Options{}.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
327+
Options{}.set<spanner::EnableMultiplexedSessionOption>({}));
328328
auto session = pool->Multiplexed();
329329
EXPECT_THAT(session,
330330
StatusIs(StatusCode::kInternal, HasSubstr("init failure")));
@@ -554,7 +554,7 @@ TEST_F(SessionPoolTest, MultiplexedLabels) {
554554
db, {mock}, threads.cq(),
555555
Options{}
556556
.set<spanner::SessionPoolLabelsOption>(std::move(labels))
557-
.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
557+
.set<spanner::EnableMultiplexedSessionOption>({}));
558558
auto session = pool->Multiplexed();
559559
ASSERT_STATUS_OK(session);
560560
EXPECT_EQ((*session)->session_name(), "multiplexed");
@@ -598,7 +598,7 @@ TEST_F(SessionPoolTest, MultiplexedCreatorRole) {
598598
db, {mock}, threads.cq(),
599599
Options{}
600600
.set<spanner::SessionCreatorRoleOption>(role)
601-
.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
601+
.set<spanner::EnableMultiplexedSessionOption>({}));
602602
auto session = pool->Multiplexed();
603603
ASSERT_STATUS_OK(session);
604604
EXPECT_EQ((*session)->session_name(), "multiplexed");
@@ -773,7 +773,7 @@ TEST_F(SessionPoolTest, MultilpexedSessionReplacementSuccess) {
773773
background_interval)
774774
.set<MultiplexedSessionReplacementIntervalOption>(
775775
replacement_interval)
776-
.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
776+
.set<spanner::EnableMultiplexedSessionOption>({}));
777777

778778
auto s1 = pool->Multiplexed();
779779
ASSERT_STATUS_OK(s1);
@@ -815,7 +815,7 @@ TEST_F(SessionPoolTest, MultilpexedSessionReplacementRpcPermanentFailure) {
815815
background_interval)
816816
.set<MultiplexedSessionReplacementIntervalOption>(
817817
replacement_interval)
818-
.set<spanner_experimental::EnableMultiplexedSessionOption>({}));
818+
.set<spanner::EnableMultiplexedSessionOption>({}));
819819

820820
auto s1 = pool->Multiplexed();
821821
ASSERT_STATUS_OK(s1);

google/cloud/spanner/options.h

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,29 @@
5757

5858
namespace google {
5959
namespace cloud {
60-
namespace spanner_experimental {
60+
namespace spanner {
6161
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
6262

6363
/**
64-
* Option for `google::cloud::Options` to use MultiplexedSessions in lieu of
64+
* Option for `google::cloud::Options` to use Multiplexed sessions in lieu of
6565
* pooled sessions.
6666
*
67+
* When Multiplexed sessions are enabled, ALL operations: read-only,
68+
* partitioned, and read-write will use Multiplexed sessions. Selectively
69+
* enabling Multiplexed sessions for some subset of operations is not supported.
70+
*
71+
* @note None of the GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS* environment
72+
* variables are supported.
73+
*
74+
* @see https://cloud.google.com/spanner/docs/sessions#multiplexed_sessions for
75+
* more information.
76+
*
6777
* @ingroup google-cloud-spanner-options
6878
*/
6979
struct EnableMultiplexedSessionOption {
7080
using Type = absl::monostate;
7181
};
7282

73-
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
74-
} // namespace spanner_experimental
75-
76-
namespace spanner {
77-
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
78-
7983
/**
8084
* Option for `google::cloud::Options` to set a `spanner::RetryPolicy`.
8185
*
@@ -130,10 +134,10 @@ struct RouteToLeaderOption {
130134
* Option for `google::cloud::Options` to set the database role used for
131135
* session creation.
132136
*
133-
* When used in combination with Multiplexed Sessions, the database role applies
134-
* to all operations performed using that spanner::Connection. To perform
135-
* operations with a different database role, using Multiplexed Sessions, a
136-
* separate spanner::Connection is required.
137+
* @note When used in combination with Multiplexed sessions, the database role
138+
* applies to all operations performed using that spanner::Connection. To
139+
* perform operations with a different database role, using Multiplexed
140+
* sessions, a separate spanner::Connection is required.
137141
*
138142
* @ingroup google-cloud-spanner-options
139143
*/
@@ -252,8 +256,7 @@ using SessionPoolOptionList = OptionList<
252256
RouteToLeaderOption, SessionCreatorRoleOption, SessionPoolMinSessionsOption,
253257
SessionPoolMaxSessionsPerChannelOption, SessionPoolMaxIdleSessionsOption,
254258
SessionPoolActionOnExhaustionOption, SessionPoolKeepAliveIntervalOption,
255-
SessionPoolLabelsOption,
256-
spanner_experimental::EnableMultiplexedSessionOption>;
259+
SessionPoolLabelsOption, EnableMultiplexedSessionOption>;
257260

258261
/**
259262
* Option for `google::cloud::Options` to set the optimizer version used in an

0 commit comments

Comments
 (0)