Skip to content

Commit f61df16

Browse files
mbroadstdaprahamian
authored andcommitted
feat(sessions): track dirty state of sessions, drop after use
If a network error occurs during an operation using a session, that session must now be marked dirty and discarded after the operation completes (allowing for retryability). NODE-1977
1 parent 06689df commit f61df16

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

lib/core/sdam/server.js

+24
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,12 @@ class Server extends EventEmitter {
240240
}
241241

242242
wireProtocol.command(this, ns, cmd, options, (err, result) => {
243+
if (err && err instanceof MongoNetworkError) {
244+
if (options.session) {
245+
options.session.serverSession.isDirty = true;
246+
}
247+
}
248+
243249
if (err && isSDAMUnrecoverableError(err)) {
244250
this.emit('error', err);
245251
}
@@ -258,6 +264,12 @@ class Server extends EventEmitter {
258264
*/
259265
query(ns, cmd, cursorState, options, callback) {
260266
wireProtocol.query(this, ns, cmd, cursorState, options, (err, result) => {
267+
if (err && err instanceof MongoNetworkError) {
268+
if (options.session) {
269+
options.session.serverSession.isDirty = true;
270+
}
271+
}
272+
261273
if (err && isSDAMUnrecoverableError(err)) {
262274
this.emit('error', err);
263275
}
@@ -276,6 +288,12 @@ class Server extends EventEmitter {
276288
*/
277289
getMore(ns, cursorState, batchSize, options, callback) {
278290
wireProtocol.getMore(this, ns, cursorState, batchSize, options, (err, result) => {
291+
if (err && err instanceof MongoNetworkError) {
292+
if (options.session) {
293+
options.session.serverSession.isDirty = true;
294+
}
295+
}
296+
279297
if (err && isSDAMUnrecoverableError(err)) {
280298
this.emit('error', err);
281299
}
@@ -406,6 +424,12 @@ function executeWriteOperation(args, options, callback) {
406424
}
407425

408426
return wireProtocol[op](server, ns, ops, options, (err, result) => {
427+
if (err && err instanceof MongoNetworkError) {
428+
if (options.session) {
429+
options.session.serverSession.isDirty = true;
430+
}
431+
}
432+
409433
if (err && isSDAMUnrecoverableError(err)) {
410434
server.emit('error', err);
411435
}

lib/core/sessions.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ class ServerSession {
527527
this.id = { id: new Binary(uuidV4(), Binary.SUBTYPE_UUID) };
528528
this.lastUse = Date.now();
529529
this.txnNumber = 0;
530+
this.isDirty = false;
530531
}
531532

532533
/**
@@ -603,15 +604,20 @@ class ServerSessionPool {
603604
release(session) {
604605
const sessionTimeoutMinutes = this.topology.logicalSessionTimeoutMinutes;
605606
while (this.sessions.length) {
606-
const session = this.sessions[this.sessions.length - 1];
607-
if (session.hasTimedOut(sessionTimeoutMinutes)) {
607+
const pooledSession = this.sessions[this.sessions.length - 1];
608+
if (pooledSession.hasTimedOut(sessionTimeoutMinutes)) {
608609
this.sessions.pop();
609610
} else {
610611
break;
611612
}
612613
}
613614

614615
if (!session.hasTimedOut(sessionTimeoutMinutes)) {
616+
if (session.isDirty) {
617+
return;
618+
}
619+
620+
// otherwise, readd this session to the session pool
615621
this.sessions.unshift(session);
616622
}
617623
}

0 commit comments

Comments
 (0)