Skip to content

Commit 3e6e3c2

Browse files
RUBY-3685 Fix insert_many in transaction with csot (#2996)
1 parent 2386682 commit 3e6e3c2

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

lib/mongo/bulk_write.rb

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def execute
6767
context = Operation::Context.new(
6868
client: client,
6969
session: session,
70-
operation_timeouts: { operation_timeout_ms: op_timeout_ms(deadline) }
70+
operation_timeouts: operation_timeouts(deadline)
7171
)
7272
if single_statement?(operation)
7373
write_concern = write_concern(session)
@@ -182,6 +182,22 @@ def calculate_deadline
182182
end
183183
end
184184

185+
# Returns the operation_timeouts hash for creating an Operation::Context.
186+
# Uses operation_timeout_ms when the timeout was explicitly set on the
187+
# bulk write, or inherited_timeout_ms when it comes from the collection
188+
# or client. This distinction is important inside transactions where
189+
# operation_timeout_ms is not allowed (RUBY-3685).
190+
def operation_timeouts(deadline)
191+
timeout = op_timeout_ms(deadline)
192+
return {} if timeout.nil?
193+
194+
if @options[:timeout_ms]
195+
{ operation_timeout_ms: timeout }
196+
else
197+
{ inherited_timeout_ms: timeout }
198+
end
199+
end
200+
185201
# @param [ Float | nil ] deadline Deadline for the batch of operations.
186202
#
187203
# @return [ Integer | nil ] Timeout in milliseconds for the next operation.

spec/mongo/session_transaction_spec.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,36 @@ class SessionTransactionSpecError < StandardError; end
263263
end
264264
end
265265
end
266+
267+
# RUBY-3685: insert_many (and bulk_write) raise ArgumentError inside
268+
# with_transaction when the client has timeout_ms set.
269+
# BulkWrite#execute passes operation_timeout_ms derived from
270+
# collection.timeout_ms, which conflicts with the transaction deadline
271+
# check in CsotTimeoutHolder.
272+
context 'when client has timeout_ms and insert_many is used inside with_transaction' do
273+
let(:client) do
274+
authorized_client.with(timeout_ms: 10_000)
275+
end
276+
277+
let(:collection) do
278+
client['session-transaction-test']
279+
end
280+
281+
it 'insert_many does not raise ArgumentError' do
282+
session.with_transaction do
283+
collection.insert_many([{ a: 1 }], session: session)
284+
end
285+
end
286+
287+
it 'bulk_write does not raise ArgumentError' do
288+
session.with_transaction do
289+
collection.bulk_write(
290+
[{ insert_one: { a: 1 } }],
291+
session: session
292+
)
293+
end
294+
end
295+
end
266296
end
267297
end
268298
end

0 commit comments

Comments
 (0)