Skip to content

Commit a839581

Browse files
authored
DRIVERS-2533: add RunCursorCommand API (#1412)
1 parent eb9d42c commit a839581

File tree

11 files changed

+2928
-30
lines changed

11 files changed

+2928
-30
lines changed

source/client-side-operations-timeout/tests/runCursorCommand.json

Lines changed: 583 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
description: runCursorCommand
2+
3+
schemaVersion: '1.9'
4+
5+
runOnRequirements:
6+
- minServerVersion: "4.4"
7+
8+
createEntities:
9+
- client:
10+
id: &failPointClient failPointClient
11+
useMultipleMongoses: false
12+
- client:
13+
id: &commandClient commandClient
14+
useMultipleMongoses: false
15+
observeEvents: [commandStartedEvent, commandSucceededEvent]
16+
- client:
17+
id: &client client
18+
useMultipleMongoses: false
19+
observeEvents: [commandStartedEvent]
20+
ignoreCommandMonitoringEvents: [killCursors]
21+
- database: # For tests that need success event assertions
22+
id: &commandDb commandDb
23+
client: *commandClient
24+
databaseName: *commandDb
25+
- database:
26+
id: &db db
27+
client: *client
28+
databaseName: *db
29+
- collection:
30+
id: &collection collection
31+
database: *db
32+
collectionName: *collection
33+
34+
initialData:
35+
- collectionName: *collection
36+
databaseName: *db
37+
documents: &documents
38+
- { _id: 1, x: 11 }
39+
- { _id: 2, x: 22 }
40+
- { _id: 3, x: 33 }
41+
- { _id: 4, x: 44 }
42+
- { _id: 5, x: 55 }
43+
44+
tests:
45+
- description: errors if timeoutMode is set without timeoutMS
46+
operations:
47+
- name: runCursorCommand
48+
object: *db
49+
arguments:
50+
commandName: find
51+
command: { find: *collection }
52+
timeoutMode: cursorLifetime
53+
expectError:
54+
isClientError: true
55+
56+
- description: error if timeoutMode is cursorLifetime and cursorType is tailableAwait
57+
operations:
58+
- name: runCursorCommand
59+
object: *db
60+
arguments:
61+
commandName: find
62+
command: { find: *collection }
63+
timeoutMode: cursorLifetime
64+
cursorType: tailableAwait
65+
expectError:
66+
isClientError: true
67+
68+
# If timeoutMode is unset, it should default to CURSOR_LIFETIME and the time remaining after the find succeeds should be applied to the getMore
69+
- description: Non-tailable cursor lifetime remaining timeoutMS applied to getMore if timeoutMode is unset
70+
runOnRequirements:
71+
- serverless: forbid
72+
operations:
73+
# Block find/getMore for 15ms.
74+
- name: failPoint
75+
object: testRunner
76+
arguments:
77+
client: *failPointClient
78+
failPoint:
79+
configureFailPoint: failCommand
80+
mode: { times: 2 }
81+
data:
82+
failCommands: [find, getMore]
83+
blockConnection: true
84+
blockTimeMS: 60
85+
# Run a find with timeoutMS less than double our failPoint blockTimeMS and
86+
# batchSize less than the total document count will cause a find and a getMore to be sent.
87+
# Both will block for 60ms so together they will go over the timeout.
88+
- name: runCursorCommand
89+
object: *db
90+
arguments:
91+
commandName: find
92+
timeoutMS: 100
93+
command: { find: *collection, batchSize: 2 }
94+
expectError:
95+
isTimeoutError: true
96+
expectEvents:
97+
- client: *client
98+
events:
99+
- commandStartedEvent:
100+
commandName: find
101+
command:
102+
find: *collection
103+
maxTimeMS: { $$type: [int, long] }
104+
- commandStartedEvent:
105+
commandName: getMore
106+
command:
107+
getMore: { $$type: [int, long] }
108+
collection: *collection
109+
maxTimeMS: { $$exists: true }
110+
111+
# If timeoutMode=ITERATION, timeoutMS applies separately to the initial find and the getMore on the cursor. Neither
112+
# command should have a maxTimeMS field. This is a failure test. The "find" inherits timeoutMS=100 and "getMore"
113+
# commands are blocked for 60ms, causing iteration to fail with a timeout error.
114+
- description: Non=tailable cursor iteration timeoutMS is refreshed for getMore if timeoutMode is iteration - failure
115+
runOnRequirements:
116+
- serverless: forbid
117+
operations:
118+
- name: failPoint
119+
object: testRunner
120+
arguments:
121+
client: *failPointClient
122+
failPoint:
123+
configureFailPoint: failCommand
124+
mode: { times: 1 }
125+
data:
126+
failCommands: ["getMore"]
127+
blockConnection: true
128+
blockTimeMS: 60
129+
- name: runCursorCommand
130+
object: *db
131+
arguments:
132+
commandName: find
133+
command: { find: *collection, batchSize: 2 }
134+
timeoutMode: iteration
135+
timeoutMS: 100
136+
batchSize: 2
137+
expectError:
138+
isTimeoutError: true
139+
expectEvents:
140+
- client: *client
141+
events:
142+
- commandStartedEvent:
143+
commandName: find
144+
databaseName: *db
145+
command:
146+
find: *collection
147+
maxTimeMS: { $$exists: false }
148+
- commandStartedEvent:
149+
commandName: getMore
150+
databaseName: *db
151+
command:
152+
getMore: { $$type: ["int", "long"] }
153+
collection: *collection
154+
maxTimeMS: { $$exists: false }
155+
156+
# The timeoutMS option should apply separately to the initial "find" and each getMore. This is a failure test. The
157+
# find inherits timeoutMS=100 from the collection and the getMore command blocks for 60ms, causing iteration to fail
158+
# with a timeout error.
159+
- description: Tailable cursor iteration timeoutMS is refreshed for getMore - failure
160+
runOnRequirements:
161+
- serverless: forbid
162+
operations:
163+
- name: failPoint
164+
object: testRunner
165+
arguments:
166+
client: *failPointClient
167+
failPoint:
168+
configureFailPoint: failCommand
169+
mode: { times: 1 }
170+
data:
171+
failCommands: ["getMore"]
172+
blockConnection: true
173+
blockTimeMS: 60
174+
- name: dropCollection
175+
object: *db
176+
arguments:
177+
collection: &cappedCollection cappedCollection
178+
- name: createCollection
179+
object: *db
180+
arguments:
181+
collection: *cappedCollection
182+
capped: true
183+
size: 4096
184+
max: 3
185+
saveResultAsEntity: *cappedCollection
186+
- name: insertMany
187+
object: *cappedCollection
188+
arguments:
189+
documents:
190+
- { _id: 1, x: 11 }
191+
- { _id: 2, x: 22 }
192+
- name: createCommandCursor
193+
object: *db
194+
arguments:
195+
commandName: find
196+
command: { find: *cappedCollection, batchSize: 1, tailable: true }
197+
timeoutMode: iteration
198+
timeoutMS: 100
199+
batchSize: 1
200+
cursorType: tailable
201+
saveResultAsEntity: &tailableCursor tailableCursor
202+
# Iterate the cursor twice: the first iteration will return the document from the batch in the find and the
203+
# second will do a getMore.
204+
- name: iterateUntilDocumentOrError
205+
object: *tailableCursor
206+
- name: iterateUntilDocumentOrError
207+
object: *tailableCursor
208+
expectError:
209+
isTimeoutError: true
210+
expectEvents:
211+
- client: *client
212+
events:
213+
- commandStartedEvent:
214+
commandName: drop
215+
- commandStartedEvent:
216+
commandName: create
217+
- commandStartedEvent:
218+
commandName: insert
219+
- commandStartedEvent:
220+
commandName: find
221+
databaseName: *db
222+
command:
223+
find: *cappedCollection
224+
tailable: true
225+
awaitData: { $$exists: false }
226+
maxTimeMS: { $$exists: false }
227+
- commandStartedEvent:
228+
commandName: getMore
229+
databaseName: *db
230+
command:
231+
getMore: { $$type: ["int", "long"] }
232+
collection: *cappedCollection
233+
maxTimeMS: { $$exists: false }
234+
235+
# The timeoutMS value should be refreshed for getMore's. This is a failure test. The find inherits timeoutMS=10 from
236+
# the collection and the getMore blocks for 15ms, causing iteration to fail with a timeout error.
237+
- description: Tailable cursor awaitData iteration timeoutMS is refreshed for getMore - failure
238+
runOnRequirements:
239+
- serverless: forbid
240+
operations:
241+
- name: failPoint
242+
object: testRunner
243+
arguments:
244+
client: *failPointClient
245+
failPoint:
246+
configureFailPoint: failCommand
247+
mode: { times: 1 }
248+
data:
249+
failCommands: ["getMore"]
250+
blockConnection: true
251+
blockTimeMS: 60
252+
- name: dropCollection
253+
object: *db
254+
arguments:
255+
collection: &cappedCollection cappedCollection
256+
- name: createCollection
257+
object: *db
258+
arguments:
259+
collection: *cappedCollection
260+
capped: true
261+
size: 4096
262+
max: 3
263+
saveResultAsEntity: *cappedCollection
264+
- name: insertMany
265+
object: *cappedCollection
266+
arguments:
267+
documents: [ { foo: bar }, { fizz: buzz } ]
268+
- name: createCommandCursor
269+
object: *db
270+
arguments:
271+
command: { find: *cappedCollection, tailable: true, awaitData: true }
272+
cursorType: tailableAwait
273+
batchSize: 1
274+
saveResultAsEntity: &tailableCursor tailableCursor
275+
# Iterate twice to force a getMore.
276+
- name: iterateUntilDocumentOrError
277+
object: *tailableCursor
278+
- name: iterateUntilDocumentOrError
279+
object: *tailableCursor
280+
expectError:
281+
isTimeoutError: true
282+
expectEvents:
283+
- client: *client
284+
events:
285+
- commandStartedEvent:
286+
commandName: drop
287+
- commandStartedEvent:
288+
commandName: create
289+
- commandStartedEvent:
290+
commandName: insert
291+
- commandStartedEvent:
292+
commandName: find
293+
databaseName: *db
294+
command:
295+
find: *cappedCollection
296+
tailable: true
297+
awaitData: true
298+
maxTimeMS: { $$exists: true }
299+
- commandStartedEvent:
300+
commandName: getMore
301+
databaseName: *db
302+
command:
303+
getMore: { $$type: ["int", "long"] }
304+
collection: *cappedCollection

0 commit comments

Comments
 (0)