Skip to content

Commit 6566fb5

Browse files
authoredDec 2, 2022
fix(NODE-4447): disable causal consistency in implicit sessions (#3479)
1 parent bb6683d commit 6566fb5

File tree

4 files changed

+499
-1
lines changed

4 files changed

+499
-1
lines changed
 

‎src/sessions.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,10 @@ export class ClientSession extends TypedEventEmitter<ClientSessionEvents> {
169169
this[kServerSession] = this.explicit ? this.sessionPool.acquire() : null;
170170
this[kTxnNumberIncrement] = 0;
171171

172+
const defaultCausalConsistencyValue = this.explicit && options.snapshot !== true;
172173
this.supports = {
173-
causalConsistency: options.snapshot !== true && options.causalConsistency !== false
174+
// if we can enable causal consistency, do so by default
175+
causalConsistency: options.causalConsistency ?? defaultCausalConsistencyValue
174176
};
175177

176178
this.clusterTime = options.initialClusterTime;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
{
2+
"description": "implicit sessions default causal consistency",
3+
"schemaVersion": "1.3",
4+
"runOnRequirements": [
5+
{
6+
"minServerVersion": "4.2",
7+
"topologies": [
8+
"replicaset",
9+
"sharded",
10+
"load-balanced"
11+
]
12+
}
13+
],
14+
"createEntities": [
15+
{
16+
"client": {
17+
"id": "client0",
18+
"useMultipleMongoses": false,
19+
"observeEvents": [
20+
"commandStartedEvent"
21+
]
22+
}
23+
},
24+
{
25+
"database": {
26+
"id": "database0",
27+
"client": "client0",
28+
"databaseName": "implicit-cc-tests"
29+
}
30+
},
31+
{
32+
"collection": {
33+
"id": "collectionDefault",
34+
"database": "database0",
35+
"collectionName": "coll-default"
36+
}
37+
},
38+
{
39+
"collection": {
40+
"id": "collectionSnapshot",
41+
"database": "database0",
42+
"collectionName": "coll-snapshot",
43+
"collectionOptions": {
44+
"readConcern": {
45+
"level": "snapshot"
46+
}
47+
}
48+
}
49+
},
50+
{
51+
"collection": {
52+
"id": "collectionlinearizable",
53+
"database": "database0",
54+
"collectionName": "coll-linearizable",
55+
"collectionOptions": {
56+
"readConcern": {
57+
"level": "linearizable"
58+
}
59+
}
60+
}
61+
}
62+
],
63+
"initialData": [
64+
{
65+
"collectionName": "coll-default",
66+
"databaseName": "implicit-cc-tests",
67+
"documents": [
68+
{
69+
"_id": 1,
70+
"x": "default"
71+
}
72+
]
73+
},
74+
{
75+
"collectionName": "coll-snapshot",
76+
"databaseName": "implicit-cc-tests",
77+
"documents": [
78+
{
79+
"_id": 1,
80+
"x": "snapshot"
81+
}
82+
]
83+
},
84+
{
85+
"collectionName": "coll-linearizable",
86+
"databaseName": "implicit-cc-tests",
87+
"documents": [
88+
{
89+
"_id": 1,
90+
"x": "linearizable"
91+
}
92+
]
93+
}
94+
],
95+
"tests": [
96+
{
97+
"description": "readConcern is not sent on retried read in implicit session when readConcern level is not specified",
98+
"operations": [
99+
{
100+
"name": "failPoint",
101+
"object": "testRunner",
102+
"arguments": {
103+
"client": "client0",
104+
"failPoint": {
105+
"configureFailPoint": "failCommand",
106+
"mode": {
107+
"times": 1
108+
},
109+
"data": {
110+
"failCommands": [
111+
"find"
112+
],
113+
"errorCode": 11600
114+
}
115+
}
116+
}
117+
},
118+
{
119+
"name": "find",
120+
"object": "collectionDefault",
121+
"arguments": {
122+
"filter": {}
123+
},
124+
"expectResult": [
125+
{
126+
"_id": 1,
127+
"x": "default"
128+
}
129+
]
130+
}
131+
],
132+
"expectEvents": [
133+
{
134+
"client": "client0",
135+
"events": [
136+
{
137+
"commandStartedEvent": {
138+
"command": {
139+
"find": "coll-default",
140+
"filter": {},
141+
"readConcern": {
142+
"$$exists": false
143+
}
144+
},
145+
"databaseName": "implicit-cc-tests"
146+
}
147+
},
148+
{
149+
"commandStartedEvent": {
150+
"command": {
151+
"find": "coll-default",
152+
"filter": {},
153+
"readConcern": {
154+
"$$exists": false
155+
}
156+
},
157+
"databaseName": "implicit-cc-tests"
158+
}
159+
}
160+
]
161+
}
162+
]
163+
},
164+
{
165+
"description": "afterClusterTime is not sent on retried read in implicit session when readConcern level is snapshot",
166+
"runOnRequirements": [
167+
{
168+
"minServerVersion": "5.0"
169+
}
170+
],
171+
"operations": [
172+
{
173+
"name": "failPoint",
174+
"object": "testRunner",
175+
"arguments": {
176+
"client": "client0",
177+
"failPoint": {
178+
"configureFailPoint": "failCommand",
179+
"mode": {
180+
"times": 1
181+
},
182+
"data": {
183+
"failCommands": [
184+
"find"
185+
],
186+
"errorCode": 11600
187+
}
188+
}
189+
}
190+
},
191+
{
192+
"name": "find",
193+
"object": "collectionSnapshot",
194+
"arguments": {
195+
"filter": {}
196+
},
197+
"expectResult": [
198+
{
199+
"_id": 1,
200+
"x": "snapshot"
201+
}
202+
]
203+
}
204+
],
205+
"expectEvents": [
206+
{
207+
"client": "client0",
208+
"events": [
209+
{
210+
"commandStartedEvent": {
211+
"command": {
212+
"find": "coll-snapshot",
213+
"filter": {},
214+
"readConcern": {
215+
"level": "snapshot",
216+
"afterClusterTime": {
217+
"$$exists": false
218+
}
219+
}
220+
},
221+
"databaseName": "implicit-cc-tests"
222+
}
223+
},
224+
{
225+
"commandStartedEvent": {
226+
"command": {
227+
"find": "coll-snapshot",
228+
"filter": {},
229+
"readConcern": {
230+
"level": "snapshot",
231+
"afterClusterTime": {
232+
"$$exists": false
233+
}
234+
}
235+
},
236+
"databaseName": "implicit-cc-tests"
237+
}
238+
}
239+
]
240+
}
241+
]
242+
},
243+
{
244+
"description": "afterClusterTime is not sent on retried read in implicit session when readConcern level is linearizable",
245+
"operations": [
246+
{
247+
"name": "failPoint",
248+
"object": "testRunner",
249+
"arguments": {
250+
"client": "client0",
251+
"failPoint": {
252+
"configureFailPoint": "failCommand",
253+
"mode": {
254+
"times": 1
255+
},
256+
"data": {
257+
"failCommands": [
258+
"find"
259+
],
260+
"errorCode": 11600
261+
}
262+
}
263+
}
264+
},
265+
{
266+
"name": "find",
267+
"object": "collectionlinearizable",
268+
"arguments": {
269+
"filter": {}
270+
},
271+
"expectResult": [
272+
{
273+
"_id": 1,
274+
"x": "linearizable"
275+
}
276+
]
277+
}
278+
],
279+
"expectEvents": [
280+
{
281+
"client": "client0",
282+
"events": [
283+
{
284+
"commandStartedEvent": {
285+
"command": {
286+
"find": "coll-linearizable",
287+
"filter": {},
288+
"readConcern": {
289+
"level": "linearizable",
290+
"afterClusterTime": {
291+
"$$exists": false
292+
}
293+
}
294+
},
295+
"databaseName": "implicit-cc-tests"
296+
}
297+
},
298+
{
299+
"commandStartedEvent": {
300+
"command": {
301+
"find": "coll-linearizable",
302+
"filter": {},
303+
"readConcern": {
304+
"level": "linearizable",
305+
"afterClusterTime": {
306+
"$$exists": false
307+
}
308+
}
309+
},
310+
"databaseName": "implicit-cc-tests"
311+
}
312+
}
313+
]
314+
}
315+
]
316+
}
317+
]
318+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
description: "implicit sessions default causal consistency"
2+
3+
schemaVersion: "1.3"
4+
5+
runOnRequirements:
6+
- minServerVersion: "4.2"
7+
topologies: [replicaset, sharded, load-balanced]
8+
9+
createEntities:
10+
- client:
11+
id: &client0 client0
12+
useMultipleMongoses: false
13+
observeEvents: [commandStartedEvent]
14+
- database:
15+
id: &database0 database0
16+
client: *client0
17+
databaseName: &databaseName implicit-cc-tests
18+
- collection:
19+
id: &collectionDefault collectionDefault
20+
database: *database0
21+
collectionName: &collectionNameDefault coll-default
22+
- collection:
23+
id: &collectionSnapshot collectionSnapshot
24+
database: *database0
25+
collectionName: &collectionNameSnapshot coll-snapshot
26+
collectionOptions:
27+
readConcern: { level: snapshot }
28+
- collection:
29+
id: &collectionlinearizable collectionlinearizable
30+
database: *database0
31+
collectionName: &collectionNamelinearizable coll-linearizable
32+
collectionOptions:
33+
readConcern: { level: linearizable }
34+
35+
initialData:
36+
- collectionName: *collectionNameDefault
37+
databaseName: *databaseName
38+
documents:
39+
- { _id: 1, x: default }
40+
- collectionName: *collectionNameSnapshot
41+
databaseName: *databaseName
42+
documents:
43+
- { _id: 1, x: snapshot }
44+
- collectionName: *collectionNamelinearizable
45+
databaseName: *databaseName
46+
documents:
47+
- { _id: 1, x: linearizable }
48+
49+
tests:
50+
- description: "readConcern is not sent on retried read in implicit session when readConcern level is not specified"
51+
operations:
52+
- &failPointCommand
53+
name: failPoint
54+
object: testRunner
55+
arguments:
56+
client: *client0
57+
failPoint:
58+
configureFailPoint: failCommand
59+
mode: { times: 1 }
60+
data:
61+
failCommands: [find]
62+
errorCode: 11600 #InterruptedAtShutdown
63+
- name: find
64+
object: *collectionDefault
65+
arguments:
66+
filter: {}
67+
expectResult: [{ _id: 1, x: default }]
68+
expectEvents:
69+
- client: *client0
70+
events:
71+
- commandStartedEvent: &commandStartedEventDefault
72+
command:
73+
find: *collectionNameDefault
74+
filter: {}
75+
readConcern: { $$exists: false }
76+
databaseName: *databaseName
77+
- commandStartedEvent: *commandStartedEventDefault
78+
79+
- description: "afterClusterTime is not sent on retried read in implicit session when readConcern level is snapshot"
80+
runOnRequirements:
81+
- minServerVersion: "5.0"
82+
operations:
83+
- *failPointCommand
84+
- name: find
85+
object: *collectionSnapshot
86+
arguments:
87+
filter: {}
88+
expectResult: [{ _id: 1, x: snapshot }]
89+
expectEvents:
90+
- client: *client0
91+
events:
92+
- commandStartedEvent: &commandStartedEventSnapshot
93+
command:
94+
find: *collectionNameSnapshot
95+
filter: {}
96+
readConcern:
97+
{ level: snapshot, afterClusterTime: { $$exists: false } }
98+
databaseName: *databaseName
99+
- commandStartedEvent: *commandStartedEventSnapshot
100+
101+
- description: "afterClusterTime is not sent on retried read in implicit session when readConcern level is linearizable"
102+
operations:
103+
- *failPointCommand
104+
- name: find
105+
object: *collectionlinearizable
106+
arguments:
107+
filter: {}
108+
expectResult: [{ _id: 1, x: linearizable }]
109+
expectEvents:
110+
- client: *client0
111+
events:
112+
- commandStartedEvent: &commandStartedEventLinearizable
113+
command:
114+
find: *collectionNamelinearizable
115+
filter: {}
116+
readConcern:
117+
{ level: linearizable, afterClusterTime: { $$exists: false } }
118+
databaseName: *databaseName
119+
- commandStartedEvent: *commandStartedEventLinearizable

‎test/unit/sessions.test.js

+59
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,65 @@ describe('Sessions - unit', function () {
167167
).to.throw('Properties "causalConsistency" and "snapshot" are mutually exclusive');
168168
});
169169

170+
it('should default `causalConsistency` to `true` for explicit non-snapshot sessions', function () {
171+
const session = new ClientSession(client, serverSessionPool, { explicit: true });
172+
expect(session.supports).property('causalConsistency', true);
173+
});
174+
175+
it('should default `causalConsistency` to `false` for explicit snapshot sessions', function () {
176+
const session = new ClientSession(client, serverSessionPool, {
177+
explicit: true,
178+
snapshot: true
179+
});
180+
expect(session.supports).property('causalConsistency', false);
181+
});
182+
183+
it('should allow `causalConsistency=false` option in explicit snapshot sessions', function () {
184+
const session = new ClientSession(client, serverSessionPool, {
185+
explicit: true,
186+
causalConsistency: false,
187+
snapshot: true
188+
});
189+
expect(session.supports).property('causalConsistency', false);
190+
});
191+
192+
it('should respect `causalConsistency=false` option in explicit sessions', function () {
193+
const session = new ClientSession(client, serverSessionPool, {
194+
explicit: true,
195+
causalConsistency: false
196+
});
197+
expect(session.supports).property('causalConsistency', false);
198+
});
199+
200+
it('should respect `causalConsistency=true` option in explicit non-snapshot sessions', function () {
201+
const session = new ClientSession(client, serverSessionPool, {
202+
explicit: true,
203+
causalConsistency: true
204+
});
205+
expect(session.supports).property('causalConsistency', true);
206+
});
207+
208+
it('should default `causalConsistency` to `false` for implicit sessions', function () {
209+
const session = new ClientSession(client, serverSessionPool, { explicit: false });
210+
expect(session.supports).property('causalConsistency', false);
211+
});
212+
213+
it('should respect `causalConsistency=false` option in implicit sessions', function () {
214+
const session = new ClientSession(client, serverSessionPool, {
215+
explicit: false,
216+
causalConsistency: false
217+
});
218+
expect(session.supports).property('causalConsistency', false);
219+
});
220+
221+
it('should respect `causalConsistency=true` option in implicit sessions', function () {
222+
const session = new ClientSession(client, serverSessionPool, {
223+
explicit: false,
224+
causalConsistency: true
225+
});
226+
expect(session.supports).property('causalConsistency', true);
227+
});
228+
170229
it('should default to `null` for `clusterTime`', function () {
171230
const session = new ClientSession(client, serverSessionPool);
172231
expect(session.clusterTime).to.not.exist;

0 commit comments

Comments
 (0)
Please sign in to comment.