@@ -446,20 +446,14 @@ def end_session
446446    # 
447447    # @since 2.7.0 
448448    def  with_transaction ( options  =  nil ) 
449-       if  timeout_ms  =  ( options  || { } ) [ :timeout_ms ] 
450-         timeout_sec  =  timeout_ms  / 1_000.0 
451-         deadline  =  Utils . monotonic_time  + timeout_sec 
452-         @with_transaction_deadline  =  deadline 
453-       elsif  default_timeout_ms  =  @options [ :default_timeout_ms ] 
454-         timeout_sec  =  default_timeout_ms  / 1_000.0 
455-         deadline  =  Utils . monotonic_time  + timeout_sec 
456-         @with_transaction_deadline  =  deadline 
457-       elsif  @client . timeout_sec 
458-         deadline  =  Utils . monotonic_time  + @client . timeout_sec 
459-         @with_transaction_deadline  =  deadline 
460-       else 
461-         deadline  =  Utils . monotonic_time  + 120 
462-       end 
449+       @with_transaction_deadline  =  calculate_with_transaction_deadline ( options ) 
450+       deadline  =  if  @with_transaction_deadline 
451+                    # CSOT enabled, so we have a customer defined deadline. 
452+                    @with_transaction_deadline 
453+                  else 
454+                     # CSOT not enabled, so we use the default deadline, 120 seconds. 
455+                    Utils . monotonic_time  + 120 
456+                  end 
463457      transaction_in_progress  =  false 
464458      loop  do 
465459        commit_options  =  { } 
@@ -478,7 +472,7 @@ def with_transaction(options = nil)
478472            transaction_in_progress  =  false 
479473          end 
480474
481-           if  Utils . monotonic_time  >=  deadline 
475+           if  deadline_expired? ( deadline ) 
482476            transaction_in_progress  =  false 
483477            raise 
484478          end 
@@ -500,7 +494,7 @@ def with_transaction(options = nil)
500494            return  rv 
501495          rescue  Mongo ::Error  =>  e 
502496            if  e . label? ( 'UnknownTransactionCommitResult' ) 
503-               if  Utils . monotonic_time  >=  deadline  ||
497+               if    deadline_expired? ( deadline )  ||
504498                e . is_a? ( Error ::OperationFailure ::Family )  && e . max_time_ms_expired? 
505499              then 
506500                transaction_in_progress  =  false 
@@ -1191,6 +1185,8 @@ def txn_num
11911185    # @api private 
11921186    attr_accessor  :snapshot_timestamp 
11931187
1188+     # @return [ Integer | nil ] The deadline for the current transaction, if any. 
1189+     # @api private 
11941190    attr_reader  :with_transaction_deadline 
11951191
11961192    private 
@@ -1286,5 +1282,30 @@ def operation_timeouts(opts)
12861282        end 
12871283      end 
12881284    end 
1285+ 
1286+     def  calculate_with_transaction_deadline ( opts ) 
1287+       calc  =  ->  ( timeout )  { 
1288+         if  timeout  == 0 
1289+           0 
1290+         else 
1291+           Utils . monotonic_time  + ( timeout  / 1000.0 ) 
1292+         end 
1293+       } 
1294+       if  timeout_ms  =  opts &.dig ( :timeout_ms ) 
1295+         calc . call ( timeout_ms ) 
1296+       elsif  default_timeout_ms  =  @options [ :default_timeout_ms ] 
1297+         calc . call ( default_timeout_ms ) 
1298+       elsif  @client . timeout_ms 
1299+         calc . call ( @client . timeout_ms ) 
1300+       end 
1301+     end 
1302+ 
1303+     def  deadline_expired? ( deadline ) 
1304+       if  deadline . zero? 
1305+         false 
1306+       else 
1307+         Utils . monotonic_time  >= deadline 
1308+       end 
1309+     end 
12891310  end 
12901311end 
0 commit comments