@@ -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