Skip to content

Commit fd8f3bd

Browse files
nbbeekendariakp
authored andcommitted
fix(NODE-6412): read stale response from previously timed out connection (#4273)
1 parent c55f965 commit fd8f3bd

File tree

3 files changed

+56
-1
lines changed

3 files changed

+56
-1
lines changed

src/cmap/connection.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -752,9 +752,12 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
752752
}
753753
} catch (readError) {
754754
if (TimeoutError.is(readError)) {
755-
throw new MongoOperationTimeoutError(
755+
const error = new MongoOperationTimeoutError(
756756
`Timed out during socket read (${readError.duration}ms)`
757757
);
758+
this.dataEvents = null;
759+
this.onError(error);
760+
throw error;
758761
}
759762
throw readError;
760763
} finally {

test/integration/client-side-operations-timeout/client_side_operations_timeout.spec.test.ts

+6
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ describe('CSOT spec tests', function () {
4848

4949
runUnifiedSuite(specs, (test, configuration) => {
5050
const sessionCSOTTests = ['timeoutMS applied to withTransaction'];
51+
if (
52+
configuration.topologyType === 'LoadBalanced' &&
53+
test.description === 'timeoutMS is refreshed for close'
54+
) {
55+
return 'LoadBalanced cannot refresh timeoutMS and run expected killCursors because pinned connection has been closed by the timeout';
56+
}
5157
if (
5258
sessionCSOTTests.includes(test.description) &&
5359
configuration.topologyType === 'ReplicaSetWithPrimary' &&

test/integration/client-side-operations-timeout/node_csot.test.ts

+46
Original file line numberDiff line numberDiff line change
@@ -1116,4 +1116,50 @@ describe('CSOT driver tests', metadata, () => {
11161116
);
11171117
});
11181118
});
1119+
1120+
describe('Connection after timeout', { requires: { mongodb: '>=4.4' } }, function () {
1121+
let client: MongoClient;
1122+
1123+
beforeEach(async function () {
1124+
client = this.configuration.newClient({ timeoutMS: 500 });
1125+
1126+
const failpoint: FailPoint = {
1127+
configureFailPoint: 'failCommand',
1128+
mode: {
1129+
times: 1
1130+
},
1131+
data: {
1132+
failCommands: ['insert'],
1133+
blockConnection: true,
1134+
blockTimeMS: 700
1135+
}
1136+
};
1137+
1138+
await client.db('admin').command(failpoint);
1139+
});
1140+
1141+
afterEach(async function () {
1142+
await client.close();
1143+
});
1144+
1145+
it('closes so pending messages are not read by another operation', async function () {
1146+
const cmap = [];
1147+
client.on('connectionCheckedOut', ev => cmap.push(ev));
1148+
client.on('connectionClosed', ev => cmap.push(ev));
1149+
1150+
const error = await client
1151+
.db('socket')
1152+
.collection('closes')
1153+
.insertOne({})
1154+
.catch(error => error);
1155+
1156+
expect(error).to.be.instanceOf(MongoOperationTimeoutError);
1157+
expect(cmap).to.have.lengthOf(2);
1158+
1159+
const [checkedOut, closed] = cmap;
1160+
expect(checkedOut).to.have.property('name', 'connectionCheckedOut');
1161+
expect(closed).to.have.property('name', 'connectionClosed');
1162+
expect(checkedOut).to.have.property('connectionId', closed.connectionId);
1163+
});
1164+
});
11191165
});

0 commit comments

Comments
 (0)