@@ -1516,6 +1516,65 @@ public void testReadWriteUnimplemented_firstReceivesError_secondFallsBackToRegul
15161516 assertEquals (1L , client .multiplexedSessionDatabaseClient .getNumSessionsReleased ().get ());
15171517 }
15181518
1519+ @ Test
1520+ public void testOtherUnimplementedError_ReadWriteTransactionStillUsesMultiplexedSession () {
1521+ mockSpanner .setExecuteStreamingSqlExecutionTime (
1522+ SimulatedExecutionTime .ofException (
1523+ Status .UNIMPLEMENTED
1524+ .withDescription ("Multiplexed sessions are not supported." )
1525+ .asRuntimeException ()));
1526+
1527+ DatabaseClientImpl client =
1528+ (DatabaseClientImpl ) spanner .getDatabaseClient (DatabaseId .of ("p" , "i" , "d" ));
1529+
1530+ // Wait until the initial BeginTransaction RPC with read-write is complete.
1531+ assertNotNull (client .multiplexedSessionDatabaseClient );
1532+ Transaction txn =
1533+ client .multiplexedSessionDatabaseClient .getReadWriteBeginTransactionReference ();
1534+ assertNotNull (txn );
1535+ assertNotNull (txn .getId ());
1536+ assertFalse (client .multiplexedSessionDatabaseClient .unimplementedForRW .get ());
1537+
1538+ // Try to execute a query using single use transaction.
1539+ try (ResultSet resultSet = client .singleUse ().executeQuery (STATEMENT )) {
1540+ SpannerException spannerException = assertThrows (SpannerException .class , resultSet ::next );
1541+ assertEquals (ErrorCode .UNIMPLEMENTED , spannerException .getErrorCode ());
1542+ }
1543+ // Verify other UNIMPLEMENTED errors does not turn off read-write transactions to use
1544+ // multiplexed sessions.
1545+ assertFalse (client .multiplexedSessionDatabaseClient .unimplementedForRW .get ());
1546+
1547+ // The read-write transaction should use multiplexed sessions and succeed.
1548+ client
1549+ .readWriteTransaction ()
1550+ .run (
1551+ transaction -> {
1552+ // Returns a ResultSet containing the precommit token (ResultSetPrecommitToken)
1553+ transaction .executeUpdate (UPDATE_STATEMENT );
1554+
1555+ // Verify that a precommit token is received. This guarantees that the read-write
1556+ // transaction was executed on a multiplexed session.
1557+ TransactionContextImpl impl = (TransactionContextImpl ) transaction ;
1558+ assertNotNull (impl .getLatestPrecommitToken ());
1559+ assertEquals (
1560+ ByteString .copyFromUtf8 ("ResultSetPrecommitToken" ),
1561+ impl .getLatestPrecommitToken ().getPrecommitToken ());
1562+ return null ;
1563+ });
1564+
1565+ // Verify that two ExecuteSqlRequests were received and second one uses a multiplexed session.
1566+ assertEquals (2 , mockSpanner .countRequestsOfType (ExecuteSqlRequest .class ));
1567+ List <ExecuteSqlRequest > requests = mockSpanner .getRequestsOfType (ExecuteSqlRequest .class );
1568+
1569+ Session session2 = mockSpanner .getSession (requests .get (1 ).getSession ());
1570+ assertNotNull (session2 );
1571+ assertTrue (session2 .getMultiplexed ());
1572+
1573+ assertNotNull (client .multiplexedSessionDatabaseClient );
1574+ assertEquals (2L , client .multiplexedSessionDatabaseClient .getNumSessionsAcquired ().get ());
1575+ assertEquals (2L , client .multiplexedSessionDatabaseClient .getNumSessionsReleased ().get ());
1576+ }
1577+
15191578 private void waitForSessionToBeReplaced (DatabaseClientImpl client ) {
15201579 assertNotNull (client .multiplexedSessionDatabaseClient );
15211580 SessionReference sessionReference =
0 commit comments