Skip to content

Commit 90d9547

Browse files
authored
Second attempt to clean up after reconnects (#205)
We had a previous attempt to clean up after reconnects. But there's still one more failure mode where _something_ happens during the reconnect handshake that makes the server believe it has never seen the client before in its life and assign a new session id. When that happens, the previous connection is never reset, and the timer eventually fires and kills the new connection accidentally. This change now makes the establishment of a new connection always clean up the previous data in the session, no matter what.
1 parent 7c8d01b commit 90d9547

File tree

3 files changed

+19
-14
lines changed

3 files changed

+19
-14
lines changed

.github/workflows/ci.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
fail-fast: false
1515
matrix:
16-
os: [windows-latest, macos-latest, ubuntu-latest]
16+
os: [macos-latest, ubuntu-latest]
1717
runs-on: ${{ matrix.os }}
1818
permissions:
1919
contents: write

transport/session.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -340,10 +340,16 @@ export class Session<ConnType extends Connection> {
340340
this.connection = undefined;
341341
}
342342

343-
replaceWithNewConnection(newConn: ConnType) {
343+
replaceWithNewConnection(newConn: ConnType, isTransparentReconnect: boolean) {
344344
this.closeStaleConnection(newConn);
345345
this.cancelGrace();
346-
this.sendBufferedMessages(newConn);
346+
if (isTransparentReconnect) {
347+
// only send the buffered messages if this is considered a transparent reconnect. there are
348+
// cases where the cient reconnects but with a different session id. for those cases we should
349+
// not send messages from a previous session.
350+
351+
this.sendBufferedMessages(newConn);
352+
}
347353
this.connection = newConn;
348354

349355
// we only call replaceWithNewConnection after

transport/transport.ts

+10-11
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ export abstract class Transport<ConnType extends Connection> {
211211
protected onConnect(
212212
conn: ConnType,
213213
session: Session<ConnType>,
214-
isReconnect: boolean,
214+
isTransparentReconnect: boolean,
215215
) {
216216
this.eventDispatcher.dispatchEvent('connectionStatus', {
217217
status: 'connect',
@@ -220,9 +220,7 @@ export abstract class Transport<ConnType extends Connection> {
220220

221221
conn.telemetry = createConnectionTelemetryInfo(conn, session.telemetry);
222222

223-
if (isReconnect) {
224-
session.replaceWithNewConnection(conn);
225-
}
223+
session.replaceWithNewConnection(conn, isTransparentReconnect);
226224

227225
this.log?.info(`connected to ${session.to}`, {
228226
...conn.loggingMetadata,
@@ -269,7 +267,8 @@ export abstract class Transport<ConnType extends Connection> {
269267
propagationCtx?: PropagationContext;
270268
}) {
271269
let session = this.sessions.get(to);
272-
let isReconnect = session !== undefined;
270+
const isReconnect = session !== undefined;
271+
let isTransparentReconnect = isReconnect;
273272

274273
if (
275274
session?.advertisedSessionId !== undefined &&
@@ -289,7 +288,7 @@ export abstract class Transport<ConnType extends Connection> {
289288
closeHandshakingConnection: handshakingConn !== undefined,
290289
handshakingConn,
291290
});
292-
isReconnect = false;
291+
isTransparentReconnect = false;
293292
session = undefined;
294293
}
295294

@@ -308,7 +307,7 @@ export abstract class Transport<ConnType extends Connection> {
308307
if (handshakingConn !== undefined) {
309308
session.replaceWithNewHandshakingConnection(handshakingConn);
310309
}
311-
return { session, isReconnect };
310+
return { session, isReconnect, isTransparentReconnect };
312311
}
313312

314313
protected deleteSession({
@@ -746,13 +745,13 @@ export abstract class ClientTransport<
746745
transportMessage: parsed,
747746
});
748747

749-
const { session, isReconnect } = this.getOrCreateSession({
748+
const { session, isTransparentReconnect } = this.getOrCreateSession({
750749
to: parsed.from,
751750
conn,
752751
sessionId: parsed.payload.status.sessionId,
753752
});
754753

755-
this.onConnect(conn, session, isReconnect);
754+
this.onConnect(conn, session, isTransparentReconnect);
756755

757756
// After a successful connection, we start restoring the budget
758757
// so that the next time we try to connect, we don't hit the client
@@ -1248,7 +1247,7 @@ export abstract class ServerTransport<
12481247
return false;
12491248
}
12501249

1251-
const { session, isReconnect } = this.getOrCreateSession({
1250+
const { session, isTransparentReconnect } = this.getOrCreateSession({
12521251
to: parsed.from,
12531252
conn,
12541253
sessionId: parsed.payload.sessionId,
@@ -1266,7 +1265,7 @@ export abstract class ServerTransport<
12661265
sessionId: session.id,
12671266
});
12681267
conn.send(this.codec.toBuffer(responseMsg));
1269-
this.onConnect(conn, session, isReconnect);
1268+
this.onConnect(conn, session, isTransparentReconnect);
12701269

12711270
return session;
12721271
}

0 commit comments

Comments
 (0)