Skip to content

Commit bbad57f

Browse files
committed
feat: rewrite of redis unloading logic to utilize before/after-unloadDocument
1 parent 31896d8 commit bbad57f

1 file changed

Lines changed: 17 additions & 38 deletions

File tree

packages/extension-redis/src/Redis.ts

Lines changed: 17 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import type {
55
Hocuspocus,
66
afterLoadDocumentPayload,
77
afterStoreDocumentPayload,
8+
afterUnloadDocumentPayload,
89
beforeBroadcastStatelessPayload,
10+
beforeUnloadDocumentPayload,
911
onAwarenessUpdatePayload,
1012
onChangePayload,
1113
onConfigurePayload,
@@ -108,12 +110,6 @@ export class Redis implements Extension {
108110

109111
messagePrefix: Buffer;
110112

111-
/**
112-
* When we have a high frequency of updates to a document we don't need tons of setTimeouts
113-
* piling up, so we'll track them to keep it to the most recent per document.
114-
*/
115-
private pendingDisconnects = new Map<string, NodeJS.Timeout>();
116-
117113
private pendingAfterStoreDocumentResolves = new Map<
118114
string,
119115
{ timeout: NodeJS.Timeout; resolve: () => void }
@@ -389,42 +385,25 @@ export class Redis implements Extension {
389385
}
390386

391387
/**
392-
* Make sure to *not* listen for further changes, when there’s
393-
* no one connected anymore.
388+
* Delay unloading to allow syncs to finish
394389
*/
395-
public onDisconnect = async ({ documentName }: onDisconnectPayload) => {
396-
const pending = this.pendingDisconnects.get(documentName);
397-
398-
if (pending) {
399-
clearTimeout(pending);
400-
this.pendingDisconnects.delete(documentName);
401-
}
402-
403-
const disconnect = () => {
404-
const document = this.instance.documents.get(documentName);
405-
406-
this.pendingDisconnects.delete(documentName);
407-
408-
// Do nothing, when other users are still connected to the document.
409-
if (document && document.getConnectionsCount() > 0) {
410-
return;
411-
}
390+
async beforeUnloadDocument(data: beforeUnloadDocumentPayload) {
391+
return new Promise<void>((resolve) => {
392+
setTimeout(() => {
393+
resolve();
394+
}, this.configuration.disconnectDelay);
395+
});
396+
}
412397

413-
// Time to end the subscription on the document channel.
414-
this.sub.unsubscribe(this.subKey(documentName), (error: any) => {
415-
if (error) {
416-
console.error(error);
417-
}
418-
});
398+
async afterUnloadDocument(data: afterUnloadDocumentPayload) {
399+
if (data.instance.documents.has(data.documentName)) return; // skip unsubscribe if the document is already loaded again (maybe fast reconnect)
419400

420-
if (document) {
421-
this.instance.unloadDocument(document);
401+
this.sub.unsubscribe(this.subKey(data.documentName), (error: any) => {
402+
if (error) {
403+
console.error(error);
422404
}
423-
};
424-
// Delay the disconnect procedure to allow last minute syncs to happen
425-
const timeout = setTimeout(disconnect, this.configuration.disconnectDelay);
426-
this.pendingDisconnects.set(documentName, timeout);
427-
};
405+
});
406+
}
428407

429408
async beforeBroadcastStateless(data: beforeBroadcastStatelessPayload) {
430409
const message = new OutgoingMessage(

0 commit comments

Comments
 (0)