@@ -2170,6 +2170,148 @@ public void testBatchWriteAtLeastOnce() {
21702170 assertFalse (mockSpanner .getSession (executeSqlRequests .get (2 ).getSession ()).getMultiplexed ());
21712171 }
21722172
2173+ @ Test
2174+ public void testReadWriteTransactionUsingTransactionManager_SetsTransactionID_DuringAborted () {
2175+ // Whenever an ABORTED exception occurs, the transaction ID that caused the ABORT should be set in the AbortedException class.
2176+ DatabaseClientImpl client =
2177+ (DatabaseClientImpl ) spanner .getDatabaseClient (DatabaseId .of ("p" , "i" , "d" ));
2178+ // Force the Commit RPC to return Aborted the first time it is called. The exception is cleared
2179+ // after the first call, so the retry should succeed.
2180+ mockSpanner .setCommitExecutionTime (
2181+ SimulatedExecutionTime .ofException (
2182+ mockSpanner .createAbortedException (ByteString .copyFromUtf8 ("test" ))));
2183+
2184+ ByteString abortedTransactionID = null ;
2185+ AbortedException exception = null ;
2186+ try (TransactionManager manager = client .transactionManager ()) {
2187+ TransactionContext transaction = manager .begin ();
2188+ try {
2189+ try (ResultSet resultSet = transaction .executeQuery (STATEMENT )) {
2190+ //noinspection StatementWithEmptyBody
2191+ while (resultSet .next ()) {
2192+ // ignore
2193+ }
2194+ }
2195+ manager .commit ();
2196+ assertNotNull (manager .getCommitTimestamp ());
2197+ } catch (AbortedException e ) {
2198+ // The transactionID of the Aborted transaction should be set in AbortedException class.
2199+ assertNotNull (e .getTransactionID ());
2200+ abortedTransactionID = e .getTransactionID ();
2201+ exception = e ;
2202+ }
2203+ }
2204+ assertNotNull (abortedTransactionID );
2205+ assertNotNull (exception );
2206+ mockSpanner .clearRequests ();
2207+
2208+ // Use AbortedException while creating a new instance of TransactionManager
2209+ try (TransactionManager manager = client .transactionManager ()) {
2210+ TransactionContext transaction = manager .begin (exception );
2211+ while (true ) {
2212+ try {
2213+ try (ResultSet resultSet = transaction .executeQuery (STATEMENT )) {
2214+ //noinspection StatementWithEmptyBody
2215+ while (resultSet .next ()) {
2216+ // ignore
2217+ }
2218+ }
2219+ manager .commit ();
2220+ assertNotNull (manager .getCommitTimestamp ());
2221+ break ;
2222+ } catch (AbortedException e ) {
2223+ transaction = manager .resetForRetry ();
2224+ }
2225+ }
2226+ }
2227+
2228+ List <ExecuteSqlRequest > executeSqlRequests =
2229+ mockSpanner .getRequestsOfType (ExecuteSqlRequest .class );
2230+ assertEquals (1 , executeSqlRequests .size ());
2231+ assertTrue (mockSpanner .getSession (executeSqlRequests .get (0 ).getSession ()).getMultiplexed ());
2232+ assertNotNull (executeSqlRequests .get (0 ).getTransaction ().getBegin ().getReadWrite ().getMultiplexedSessionPreviousTransactionId ());
2233+ assertEquals (executeSqlRequests .get (0 ).getTransaction ().getBegin ().getReadWrite ().getMultiplexedSessionPreviousTransactionId (), abortedTransactionID );
2234+
2235+ assertNotNull (client .multiplexedSessionDatabaseClient );
2236+ assertEquals (1L , client .multiplexedSessionDatabaseClient .getNumSessionsAcquired ().get ());
2237+ assertEquals (1L , client .multiplexedSessionDatabaseClient .getNumSessionsReleased ().get ());
2238+ }
2239+
2240+ @ Test
2241+ public void testReadWriteTransactionUsingTransactionManager_SetsTransactionID_DuringAbortedInExecuteSql () {
2242+ // Whenever an ABORTED exception occurs, the transaction ID that caused the ABORT should be set in the AbortedException class.
2243+ DatabaseClientImpl client =
2244+ (DatabaseClientImpl ) spanner .getDatabaseClient (DatabaseId .of ("p" , "i" , "d" ));
2245+
2246+ ByteString abortedTransactionID = null ;
2247+ AbortedException exception = null ;
2248+ try (TransactionManager manager = client .transactionManager ()) {
2249+ TransactionContext transaction = manager .begin ();
2250+ try {
2251+ try (ResultSet resultSet = transaction .executeQuery (STATEMENT )) {
2252+ //noinspection StatementWithEmptyBody
2253+ while (resultSet .next ()) {
2254+ // ignore
2255+ }
2256+ }
2257+
2258+ mockSpanner .setExecuteStreamingSqlExecutionTime (
2259+ SimulatedExecutionTime .ofException (
2260+ mockSpanner .createAbortedException (ByteString .copyFromUtf8 ("test" ))));
2261+
2262+ try (ResultSet resultSet = transaction .executeQuery (STATEMENT )) {
2263+ //noinspection StatementWithEmptyBody
2264+ while (resultSet .next ()) {
2265+ // ignore
2266+ }
2267+ }
2268+ manager .commit ();
2269+ assertNotNull (manager .getCommitTimestamp ());
2270+ } catch (AbortedException e ) {
2271+ // The transactionID of the Aborted transaction should be set in AbortedException class.
2272+ assertNotNull (e .getTransactionID ());
2273+ abortedTransactionID = e .getTransactionID ();
2274+ exception = e ;
2275+ }
2276+ }
2277+ assertNotNull (abortedTransactionID );
2278+ assertNotNull (exception );
2279+ mockSpanner .clearRequests ();
2280+
2281+ // Use AbortedException while creating a new instance of TransactionManager
2282+
2283+ try (TransactionManager manager = client .transactionManager ()) {
2284+ TransactionContext transaction = manager .begin (exception );
2285+ while (true ) {
2286+ try {
2287+ try (ResultSet resultSet = transaction .executeQuery (STATEMENT )) {
2288+ //noinspection StatementWithEmptyBody
2289+ while (resultSet .next ()) {
2290+ // ignore
2291+ }
2292+ }
2293+ manager .commit ();
2294+ assertNotNull (manager .getCommitTimestamp ());
2295+ break ;
2296+ } catch (AbortedException e ) {
2297+ transaction = manager .resetForRetry ();
2298+ }
2299+ }
2300+ }
2301+
2302+ List <ExecuteSqlRequest > executeSqlRequests =
2303+ mockSpanner .getRequestsOfType (ExecuteSqlRequest .class );
2304+ assertEquals (1 , executeSqlRequests .size ());
2305+ assertTrue (mockSpanner .getSession (executeSqlRequests .get (0 ).getSession ()).getMultiplexed ());
2306+ assertNotNull (executeSqlRequests .get (0 ).getTransaction ().getBegin ().getReadWrite ().getMultiplexedSessionPreviousTransactionId ());
2307+ assertEquals (executeSqlRequests .get (0 ).getTransaction ().getBegin ().getReadWrite ().getMultiplexedSessionPreviousTransactionId (), abortedTransactionID );
2308+
2309+
2310+ assertNotNull (client .multiplexedSessionDatabaseClient );
2311+ assertEquals (2L , client .multiplexedSessionDatabaseClient .getNumSessionsAcquired ().get ());
2312+ assertEquals (2L , client .multiplexedSessionDatabaseClient .getNumSessionsReleased ().get ());
2313+ }
2314+
21732315 private void waitForSessionToBeReplaced (DatabaseClientImpl client ) {
21742316 assertNotNull (client .multiplexedSessionDatabaseClient );
21752317 SessionReference sessionReference =
0 commit comments