@@ -69,6 +69,10 @@ public class SessionPoolOptions {
6969 /** Property for allowing mocking of session maintenance clock. */
7070 private final Clock poolMaintainerClock ;
7171
72+ private final Duration waitForMultiplexedSession ;
73+ private final boolean useMultiplexedSession ;
74+ private final Duration multiplexedSessionMaintenanceDuration ;
75+
7276 private SessionPoolOptions (Builder builder ) {
7377 // minSessions > maxSessions is only possible if the user has only set a value for maxSessions.
7478 // We allow that to prevent code that only sets a value for maxSessions to break if the
@@ -93,6 +97,9 @@ private SessionPoolOptions(Builder builder) {
9397 this .randomizePositionQPSThreshold = builder .randomizePositionQPSThreshold ;
9498 this .inactiveTransactionRemovalOptions = builder .inactiveTransactionRemovalOptions ;
9599 this .poolMaintainerClock = builder .poolMaintainerClock ;
100+ this .useMultiplexedSession = builder .useMultiplexedSession ;
101+ this .multiplexedSessionMaintenanceDuration = builder .multiplexedSessionMaintenanceDuration ;
102+ this .waitForMultiplexedSession = builder .waitForMultiplexedSession ;
96103 }
97104
98105 @ Override
@@ -123,7 +130,11 @@ public boolean equals(Object o) {
123130 && Objects .equals (this .randomizePositionQPSThreshold , other .randomizePositionQPSThreshold )
124131 && Objects .equals (
125132 this .inactiveTransactionRemovalOptions , other .inactiveTransactionRemovalOptions )
126- && Objects .equals (this .poolMaintainerClock , other .poolMaintainerClock );
133+ && Objects .equals (this .poolMaintainerClock , other .poolMaintainerClock )
134+ && Objects .equals (this .useMultiplexedSession , other .useMultiplexedSession )
135+ && Objects .equals (
136+ this .multiplexedSessionMaintenanceDuration , other .multiplexedSessionMaintenanceDuration )
137+ && Objects .equals (this .waitForMultiplexedSession , other .waitForMultiplexedSession );
127138 }
128139
129140 @ Override
@@ -148,7 +159,10 @@ public int hashCode() {
148159 this .releaseToPosition ,
149160 this .randomizePositionQPSThreshold ,
150161 this .inactiveTransactionRemovalOptions ,
151- this .poolMaintainerClock );
162+ this .poolMaintainerClock ,
163+ this .useMultiplexedSession ,
164+ this .multiplexedSessionMaintenanceDuration ,
165+ this .waitForMultiplexedSession );
152166 }
153167
154168 public Builder toBuilder () {
@@ -271,6 +285,18 @@ long getRandomizePositionQPSThreshold() {
271285 return randomizePositionQPSThreshold ;
272286 }
273287
288+ boolean getUseMultiplexedSession () {
289+ return useMultiplexedSession ;
290+ }
291+
292+ Duration getMultiplexedSessionMaintenanceDuration () {
293+ return multiplexedSessionMaintenanceDuration ;
294+ }
295+
296+ Duration getWaitForMultiplexedSession () {
297+ return waitForMultiplexedSession ;
298+ }
299+
274300 public static Builder newBuilder () {
275301 return new Builder ();
276302 }
@@ -467,6 +493,9 @@ public static class Builder {
467493 */
468494 private long randomizePositionQPSThreshold = 0L ;
469495
496+ private boolean useMultiplexedSession = false ;
497+ private Duration multiplexedSessionMaintenanceDuration = Duration .ofDays (7 );
498+ private Duration waitForMultiplexedSession = Duration .ofSeconds (10 );
470499 private Clock poolMaintainerClock ;
471500
472501 private static Position getReleaseToPositionFromSystemProperty () {
@@ -669,6 +698,47 @@ Builder setPoolMaintainerClock(Clock poolMaintainerClock) {
669698 return this ;
670699 }
671700
701+ /**
702+ * Sets whether the client should use multiplexed session or not. If set to true, the client
703+ * optimises and runs multiple applicable requests concurrently on a single session. A single
704+ * multiplexed session is sufficient to handle all concurrent traffic.
705+ *
706+ * <p>When set to false, the client uses the regular session cached in the session pool for
707+ * running 1 concurrent transaction per session. We require to provision sufficient sessions by
708+ * making use of {@link SessionPoolOptions#minSessions} and {@link
709+ * SessionPoolOptions#maxSessions} based on the traffic load. Failing to do so will result in
710+ * higher latencies.
711+ */
712+ Builder setUseMultiplexedSession (boolean useMultiplexedSession ) {
713+ this .useMultiplexedSession = useMultiplexedSession ;
714+ return this ;
715+ }
716+
717+ @ VisibleForTesting
718+ Builder setMultiplexedSessionMaintenanceDuration (
719+ Duration multiplexedSessionMaintenanceDuration ) {
720+ this .multiplexedSessionMaintenanceDuration = multiplexedSessionMaintenanceDuration ;
721+ return this ;
722+ }
723+
724+ /**
725+ * This option is only used when {@link SessionPoolOptions#useMultiplexedSession} is set to
726+ * true. If greater than zero, calls to {@link Spanner#getDatabaseClient(DatabaseId)} will block
727+ * for up to the given duration while waiting for the multiplexed session to be created. The
728+ * default value for this is 10 seconds.
729+ *
730+ * <p>If this is set to null or zero, the client does not wait for the session to be created,
731+ * which means that the first read requests could see more latency, as they will need to wait
732+ * until the multiplexed session has been created.
733+ *
734+ * <p>Note that we would need to use the option {@link SessionPoolOptions#waitForMinSessions} if
735+ * we want a similar blocking behavior for the other sessions within the session pool.
736+ */
737+ Builder setWaitForMultiplexedSession (Duration waitForMultiplexedSession ) {
738+ this .waitForMultiplexedSession = waitForMultiplexedSession ;
739+ return this ;
740+ }
741+
672742 /**
673743 * Sets whether the client should automatically execute a background query to detect the dialect
674744 * that is used by the database or not. Set this option to true if you do not know what the
0 commit comments