Skip to content

Commit

Permalink
fix(NODE-6412): read stale response from previously timed out connect…
Browse files Browse the repository at this point in the history
…ion (#4273)
  • Loading branch information
nbbeeken authored and baileympearson committed Oct 21, 2024
1 parent af6e0c8 commit 2c1d2c2
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 1 deletion.
5 changes: 4 additions & 1 deletion src/cmap/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -752,9 +752,12 @@ export class Connection extends TypedEventEmitter<ConnectionEvents> {
}
} catch (readError) {
if (TimeoutError.is(readError)) {
throw new MongoOperationTimeoutError(
const error = new MongoOperationTimeoutError(
`Timed out during socket read (${readError.duration}ms)`
);
this.dataEvents = null;
this.onError(error);
throw error;
}
throw readError;
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ describe('CSOT spec tests', function () {

runUnifiedSuite(specs, (test, configuration) => {
const sessionCSOTTests = ['timeoutMS applied to withTransaction'];
if (
configuration.topologyType === 'LoadBalanced' &&
test.description === 'timeoutMS is refreshed for close'
) {
return 'LoadBalanced cannot refresh timeoutMS and run expected killCursors because pinned connection has been closed by the timeout';
}
if (
sessionCSOTTests.includes(test.description) &&
configuration.topologyType === 'ReplicaSetWithPrimary' &&
Expand Down
46 changes: 46 additions & 0 deletions test/integration/client-side-operations-timeout/node_csot.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1116,4 +1116,50 @@ describe('CSOT driver tests', metadata, () => {
);
});
});

describe('Connection after timeout', { requires: { mongodb: '>=4.4' } }, function () {
let client: MongoClient;

beforeEach(async function () {
client = this.configuration.newClient({ timeoutMS: 500 });

const failpoint: FailPoint = {
configureFailPoint: 'failCommand',
mode: {
times: 1
},
data: {
failCommands: ['insert'],
blockConnection: true,
blockTimeMS: 700
}
};

await client.db('admin').command(failpoint);
});

afterEach(async function () {
await client.close();
});

it('closes so pending messages are not read by another operation', async function () {
const cmap = [];
client.on('connectionCheckedOut', ev => cmap.push(ev));
client.on('connectionClosed', ev => cmap.push(ev));

const error = await client
.db('socket')
.collection('closes')
.insertOne({})
.catch(error => error);

expect(error).to.be.instanceOf(MongoOperationTimeoutError);
expect(cmap).to.have.lengthOf(2);

const [checkedOut, closed] = cmap;
expect(checkedOut).to.have.property('name', 'connectionCheckedOut');
expect(closed).to.have.property('name', 'connectionClosed');
expect(checkedOut).to.have.property('connectionId', closed.connectionId);
});
});
});

0 comments on commit 2c1d2c2

Please sign in to comment.