Skip to content

Commit 106ab09

Browse files
feat(NODE-5717): make ExceededTimeLimit retryable reads error (#3947)
1 parent 9126b3e commit 106ab09

File tree

3 files changed

+218
-5
lines changed

3 files changed

+218
-5
lines changed

src/error.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -1145,14 +1145,12 @@ const RETRYABLE_READ_ERROR_CODES = new Set<number>([
11451145
MONGODB_ERROR_CODES.InterruptedAtShutdown,
11461146
MONGODB_ERROR_CODES.InterruptedDueToReplStateChange,
11471147
MONGODB_ERROR_CODES.NotPrimaryNoSecondaryOk,
1148-
MONGODB_ERROR_CODES.NotPrimaryOrSecondary
1148+
MONGODB_ERROR_CODES.NotPrimaryOrSecondary,
1149+
MONGODB_ERROR_CODES.ExceededTimeLimit
11491150
]);
11501151

11511152
// see: https://github.com/mongodb/specifications/blob/master/source/retryable-writes/retryable-writes.rst#terms
1152-
const RETRYABLE_WRITE_ERROR_CODES = new Set<number>([
1153-
...RETRYABLE_READ_ERROR_CODES,
1154-
MONGODB_ERROR_CODES.ExceededTimeLimit
1155-
]);
1153+
const RETRYABLE_WRITE_ERROR_CODES = RETRYABLE_READ_ERROR_CODES;
11561154

11571155
export function needsRetryableWriteLabel(error: Error, maxWireVersion: number): boolean {
11581156
// pre-4.4 server, then the driver adds an error label for every valid case
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
{
2+
"description": "ExceededTimeLimit is a retryable read",
3+
"schemaVersion": "1.3",
4+
"runOnRequirements": [
5+
{
6+
"minServerVersion": "4.0",
7+
"topologies": [
8+
"single",
9+
"replicaset"
10+
]
11+
},
12+
{
13+
"minServerVersion": "4.1.7",
14+
"topologies": [
15+
"sharded",
16+
"load-balanced"
17+
]
18+
}
19+
],
20+
"createEntities": [
21+
{
22+
"client": {
23+
"id": "client0",
24+
"useMultipleMongoses": false,
25+
"observeEvents": [
26+
"commandStartedEvent"
27+
]
28+
}
29+
},
30+
{
31+
"database": {
32+
"id": "database0",
33+
"client": "client0",
34+
"databaseName": "retryable-reads-tests"
35+
}
36+
},
37+
{
38+
"collection": {
39+
"id": "collection0",
40+
"database": "database0",
41+
"collectionName": "exceededtimelimit-test"
42+
}
43+
}
44+
],
45+
"initialData": [
46+
{
47+
"collectionName": "exceededtimelimit-test",
48+
"databaseName": "retryable-reads-tests",
49+
"documents": [
50+
{
51+
"_id": 1,
52+
"x": 11
53+
},
54+
{
55+
"_id": 2,
56+
"x": 22
57+
},
58+
{
59+
"_id": 3,
60+
"x": 33
61+
}
62+
]
63+
}
64+
],
65+
"tests": [
66+
{
67+
"description": "Find succeeds on second attempt after ExceededTimeLimit",
68+
"operations": [
69+
{
70+
"name": "failPoint",
71+
"object": "testRunner",
72+
"arguments": {
73+
"client": "client0",
74+
"failPoint": {
75+
"configureFailPoint": "failCommand",
76+
"mode": {
77+
"times": 1
78+
},
79+
"data": {
80+
"failCommands": [
81+
"find"
82+
],
83+
"errorCode": 262
84+
}
85+
}
86+
}
87+
},
88+
{
89+
"name": "find",
90+
"arguments": {
91+
"filter": {
92+
"_id": {
93+
"$gt": 1
94+
}
95+
}
96+
},
97+
"object": "collection0",
98+
"expectResult": [
99+
{
100+
"_id": 2,
101+
"x": 22
102+
},
103+
{
104+
"_id": 3,
105+
"x": 33
106+
}
107+
]
108+
}
109+
],
110+
"expectEvents": [
111+
{
112+
"client": "client0",
113+
"events": [
114+
{
115+
"commandStartedEvent": {
116+
"command": {
117+
"find": "exceededtimelimit-test",
118+
"filter": {
119+
"_id": {
120+
"$gt": 1
121+
}
122+
}
123+
},
124+
"commandName": "find",
125+
"databaseName": "retryable-reads-tests"
126+
}
127+
},
128+
{
129+
"commandStartedEvent": {
130+
"command": {
131+
"find": "exceededtimelimit-test",
132+
"filter": {
133+
"_id": {
134+
"$gt": 1
135+
}
136+
}
137+
},
138+
"commandName": "find",
139+
"databaseName": "retryable-reads-tests"
140+
}
141+
}
142+
]
143+
}
144+
]
145+
}
146+
]
147+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
description: "ExceededTimeLimit is a retryable read"
2+
3+
schemaVersion: "1.3"
4+
5+
runOnRequirements:
6+
- minServerVersion: "4.0"
7+
topologies: [single, replicaset]
8+
- minServerVersion: "4.1.7"
9+
topologies: [sharded, load-balanced]
10+
11+
createEntities:
12+
- client:
13+
id: &client0 client0
14+
# Ensure the `configureFailpoint` and `find` commands are run on the same mongos
15+
useMultipleMongoses: false
16+
observeEvents: [ commandStartedEvent ]
17+
- database:
18+
id: &database0 database0
19+
client: *client0
20+
databaseName: &database0Name "retryable-reads-tests"
21+
- collection:
22+
id: &collection0 collection0
23+
database: *database0
24+
collectionName: &collection0Name "exceededtimelimit-test"
25+
26+
initialData:
27+
- collectionName: *collection0Name
28+
databaseName: *database0Name
29+
documents:
30+
- { _id: 1, x: 11 }
31+
- { _id: 2, x: 22 }
32+
- { _id: 3, x: 33 }
33+
34+
tests:
35+
- description: "Find succeeds on second attempt after ExceededTimeLimit"
36+
operations:
37+
- name: failPoint
38+
object: testRunner
39+
arguments:
40+
client: *client0
41+
failPoint:
42+
configureFailPoint: failCommand
43+
mode: { times: 1 }
44+
data:
45+
failCommands: [ "find" ]
46+
errorCode: 262 # ExceededTimeLimit
47+
- name: find
48+
arguments:
49+
filter: { _id: { $gt: 1 } }
50+
object: *collection0
51+
expectResult:
52+
- { _id: 2, x: 22 }
53+
- { _id: 3, x: 33 }
54+
expectEvents:
55+
- client: *client0
56+
events:
57+
- commandStartedEvent:
58+
command:
59+
find: *collection0Name
60+
filter: { _id: { $gt: 1 } }
61+
commandName: find
62+
databaseName: *database0Name
63+
- commandStartedEvent:
64+
command:
65+
find: *collection0Name
66+
filter: { _id: { $gt: 1 } }
67+
commandName: find
68+
databaseName: *database0Name

0 commit comments

Comments
 (0)