@@ -257,6 +257,7 @@ def legacy_write_with_retry(server = nil, context:)
257257 def modern_write_with_retry ( session , server , context , &block )
258258 txn_num = nil
259259 connection_succeeded = false
260+ was_starting = false
260261
261262 result = server . with_connection (
262263 connection_global_id : context . connection_global_id ,
@@ -266,6 +267,7 @@ def modern_write_with_retry(session, server, context, &block)
266267
267268 session . materialize_if_needed
268269 txn_num = session . in_transaction? ? session . txn_num : session . next_txn_num
270+ was_starting = session . starting_transaction?
269271
270272 # The context needs to be duplicated here because we will be using
271273 # it later for the retry as well.
@@ -288,7 +290,11 @@ def modern_write_with_retry(session, server, context, &block)
288290 retry_context = context . with ( is_retry : true )
289291
290292 if is_overload
291- overload_write_retry ( e , session , txn_num , context : retry_context , failed_server : server , error_count : 1 , &block )
293+ overload_write_retry ( e , session , txn_num ,
294+ context : retry_context . with ( overload_only_retry : true ) ,
295+ failed_server : server , error_count : 1 ,
296+ was_starting_transaction : was_starting ,
297+ &block )
292298 else
293299 # Context#with creates a new context, which is not necessary here
294300 # but the API is less prone to misuse this way.
@@ -351,7 +357,7 @@ def retry_write(original_error, txn_num, context:, failed_server: nil, &block)
351357 rescue *retryable_exceptions , Error ::PoolError => e
352358 if retryable_overload_error? ( e )
353359 e . add_notes ( 'modern retry' , "attempt #{ attempt } " )
354- return overload_write_retry ( e , context . session , txn_num , context : context , failed_server : server , error_count : attempt , &block )
360+ return overload_write_retry ( e , context . session , txn_num , context : context , failed_server : server , error_count : attempt , was_starting_transaction : false , &block )
355361 end
356362 maybe_fail_on_retryable ( e , original_error , context , attempt )
357363 failed_server = server
@@ -360,7 +366,7 @@ def retry_write(original_error, txn_num, context:, failed_server: nil, &block)
360366 rescue Error ::OperationFailure ::Family => e
361367 if retryable_overload_error? ( e )
362368 e . add_notes ( 'modern retry' , "attempt #{ attempt } " )
363- return overload_write_retry ( e , context . session , txn_num , context : context , failed_server : server , error_count : attempt , &block )
369+ return overload_write_retry ( e , context . session , txn_num , context : context , failed_server : server , error_count : attempt , was_starting_transaction : false , &block )
364370 end
365371 maybe_fail_on_operation_failure ( e , original_error , context , attempt )
366372 failed_server = server
@@ -375,7 +381,8 @@ def retry_write(original_error, txn_num, context:, failed_server: nil, &block)
375381 end
376382
377383 # Retry loop for overload write errors with exponential backoff.
378- def overload_write_retry ( last_error , session , txn_num , context :, failed_server :, error_count :, &block )
384+ def overload_write_retry ( last_error , session , txn_num , context :, failed_server :, error_count :,
385+ was_starting_transaction : false , &block )
379386 loop do
380387 delay = retry_policy . backoff_delay ( error_count )
381388 unless retry_policy . should_retry_overload? ( error_count , delay , context : context )
@@ -401,6 +408,7 @@ def overload_write_retry(last_error, session, txn_num, context:, failed_server:,
401408 end
402409
403410 begin
411+ session . revert_to_starting_transaction! if was_starting_transaction
404412 context . check_timeout!
405413 result = server . with_connection ( connection_global_id : context . connection_global_id ) do |connection |
406414 yield connection , txn_num , context
@@ -423,6 +431,7 @@ def overload_write_retry(last_error, session, txn_num, context:, failed_server:,
423431 end
424432 end
425433 retry_policy . record_non_overload_retry_failure unless is_overload
434+ context = context . with ( overload_only_retry : false ) unless is_overload
426435 failed_server = server
427436 last_error = e
428437 rescue Error , Error ::AuthError => e
0 commit comments