@@ -448,20 +448,14 @@ def end_session
448448 #
449449 # @since 2.7.0
450450 def with_transaction ( options = nil )
451- if timeout_ms = ( options || { } ) [ :timeout_ms ]
452- timeout_sec = timeout_ms / 1_000.0
453- deadline = Utils . monotonic_time + timeout_sec
454- @with_transaction_deadline = deadline
455- elsif default_timeout_ms = @options [ :default_timeout_ms ]
456- timeout_sec = default_timeout_ms / 1_000.0
457- deadline = Utils . monotonic_time + timeout_sec
458- @with_transaction_deadline = deadline
459- elsif @client . timeout_sec
460- deadline = Utils . monotonic_time + @client . timeout_sec
461- @with_transaction_deadline = deadline
462- else
463- deadline = Utils . monotonic_time + 120
464- end
451+ @with_transaction_deadline = calculate_with_transaction_deadline ( options )
452+ deadline = if @with_transaction_deadline
453+ # CSOT enabled, so we have a customer defined deadline.
454+ @with_transaction_deadline
455+ else
456+ # CSOT not enabled, so we use the default deadline, 120 seconds.
457+ Utils . monotonic_time + 120
458+ end
465459 transaction_in_progress = false
466460 loop do
467461 commit_options = { }
@@ -480,7 +474,7 @@ def with_transaction(options = nil)
480474 transaction_in_progress = false
481475 end
482476
483- if Utils . monotonic_time >= deadline
477+ if deadline_expired? ( deadline )
484478 transaction_in_progress = false
485479 raise
486480 end
@@ -502,7 +496,7 @@ def with_transaction(options = nil)
502496 return rv
503497 rescue Mongo ::Error => e
504498 if e . label? ( 'UnknownTransactionCommitResult' )
505- if Utils . monotonic_time >= deadline ||
499+ if deadline_expired? ( deadline ) ||
506500 e . is_a? ( Error ::OperationFailure ::Family ) && e . max_time_ms_expired?
507501 then
508502 transaction_in_progress = false
@@ -1206,6 +1200,8 @@ def txn_num
12061200 # @api private
12071201 attr_accessor :snapshot_timestamp
12081202
1203+ # @return [ Integer | nil ] The deadline for the current transaction, if any.
1204+ # @api private
12091205 attr_reader :with_transaction_deadline
12101206
12111207 private
@@ -1301,5 +1297,30 @@ def operation_timeouts(opts)
13011297 end
13021298 end
13031299 end
1300+
1301+ def calculate_with_transaction_deadline ( opts )
1302+ calc = -> ( timeout ) {
1303+ if timeout == 0
1304+ 0
1305+ else
1306+ Utils . monotonic_time + ( timeout / 1000.0 )
1307+ end
1308+ }
1309+ if timeout_ms = opts &.dig ( :timeout_ms )
1310+ calc . call ( timeout_ms )
1311+ elsif default_timeout_ms = @options [ :default_timeout_ms ]
1312+ calc . call ( default_timeout_ms )
1313+ elsif @client . timeout_ms
1314+ calc . call ( @client . timeout_ms )
1315+ end
1316+ end
1317+
1318+ def deadline_expired? ( deadline )
1319+ if deadline . zero?
1320+ false
1321+ else
1322+ Utils . monotonic_time >= deadline
1323+ end
1324+ end
13041325 end
13051326end
0 commit comments