@@ -446,20 +446,14 @@ def end_session
446
446
#
447
447
# @since 2.7.0
448
448
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
463
457
transaction_in_progress = false
464
458
loop do
465
459
commit_options = { }
@@ -478,7 +472,7 @@ def with_transaction(options = nil)
478
472
transaction_in_progress = false
479
473
end
480
474
481
- if Utils . monotonic_time >= deadline
475
+ if deadline_expired? ( deadline )
482
476
transaction_in_progress = false
483
477
raise
484
478
end
@@ -500,7 +494,7 @@ def with_transaction(options = nil)
500
494
return rv
501
495
rescue Mongo ::Error => e
502
496
if e . label? ( 'UnknownTransactionCommitResult' )
503
- if Utils . monotonic_time >= deadline ||
497
+ if deadline_expired? ( deadline ) ||
504
498
e . is_a? ( Error ::OperationFailure ::Family ) && e . max_time_ms_expired?
505
499
then
506
500
transaction_in_progress = false
@@ -1191,6 +1185,8 @@ def txn_num
1191
1185
# @api private
1192
1186
attr_accessor :snapshot_timestamp
1193
1187
1188
+ # @return [ Integer | nil ] The deadline for the current transaction, if any.
1189
+ # @api private
1194
1190
attr_reader :with_transaction_deadline
1195
1191
1196
1192
private
@@ -1286,5 +1282,30 @@ def operation_timeouts(opts)
1286
1282
end
1287
1283
end
1288
1284
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
1289
1310
end
1290
1311
end
0 commit comments