Skip to content

Commit 9964849

Browse files
Close webchannel instances on terminate (#9041)
Explicitly close any unclosed WebChannel instances on Firestore#terminate()
1 parent 770e455 commit 9964849

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

.changeset/spotty-ghosts-kneel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@firebase/firestore": patch
3+
---
4+
5+
Clean up leaked WebChannel instances when the Firestore instance is terminated.

packages/firestore/src/platform/browser/webchannel_connection.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export class WebChannelConnection extends RestConnection {
5959
private readonly useFetchStreams: boolean;
6060
private readonly longPollingOptions: ExperimentalLongPollingOptions;
6161

62+
/** A collection of open WebChannel instances */
63+
private openWebChannels: WebChannel[] = [];
64+
6265
constructor(info: DatabaseInfo) {
6366
super(info);
6467
this.forceLongPolling = info.forceLongPolling;
@@ -239,6 +242,7 @@ export class WebChannelConnection extends RestConnection {
239242
request
240243
);
241244
const channel = webchannelTransport.createWebChannel(url, request);
245+
this.addOpenWebChannel(channel);
242246

243247
// WebChannel supports sending the first message with the handshake - saving
244248
// a network round trip. However, it will have to call send in the same
@@ -321,6 +325,7 @@ export class WebChannelConnection extends RestConnection {
321325
`RPC '${rpcName}' stream ${streamId} transport closed`
322326
);
323327
streamBridge.callOnClose();
328+
this.removeOpenWebChannel(channel);
324329
}
325330
});
326331

@@ -427,4 +432,32 @@ export class WebChannelConnection extends RestConnection {
427432
}, 0);
428433
return streamBridge;
429434
}
435+
436+
/**
437+
* Closes and cleans up any resources associated with the connection.
438+
*/
439+
terminate(): void {
440+
// If the Firestore instance is terminated, we will explicitly
441+
// close any remaining open WebChannel instances.
442+
this.openWebChannels.forEach(webChannel => webChannel.close());
443+
this.openWebChannels = [];
444+
}
445+
446+
/**
447+
* Add a WebChannel instance to the collection of open instances.
448+
* @param webChannel
449+
*/
450+
addOpenWebChannel(webChannel: WebChannel): void {
451+
this.openWebChannels.push(webChannel);
452+
}
453+
454+
/**
455+
* Remove a WebChannel instance from the collection of open instances.
456+
* @param webChannel
457+
*/
458+
removeOpenWebChannel(webChannel: WebChannel): void {
459+
this.openWebChannels = this.openWebChannels.filter(
460+
instance => instance === webChannel
461+
);
462+
}
430463
}

0 commit comments

Comments
 (0)