diff --git a/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts b/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts index 1095af6884..e77a1871d2 100644 --- a/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts +++ b/client/src/app/site/services/autoupdate/autoupdate-communication.service.ts @@ -7,9 +7,11 @@ import { ModelRequest } from 'src/app/domain/interfaces/model-request'; import { HttpStreamEndpointService } from 'src/app/gateways/http-stream'; import { formatQueryParams } from 'src/app/infrastructure/definitions/http'; import { djb2hash } from 'src/app/infrastructure/utils'; +import { fqidFromCollectionAndId } from 'src/app/infrastructure/utils/transform-functions'; import { SharedWorkerService } from 'src/app/openslides-main-module/services/shared-worker.service'; import { AutoupdateAuthChange, + AutoupdateCleanupCache, AutoupdateCloseStream, AutoupdateNewUser, AutoupdateOpenStream, @@ -172,6 +174,31 @@ export class AutoupdateCommunicationService { } as AutoupdateCloseStream); } + /** + * Notifies the worker about deleted fqids + * + * @param streamId Id of the stream + * @param deletedData map op collections and ids to be deleted + */ + public cleanupCollections(streamId: Id, deletedData: { [collection: string]: Id[] }): void { + const deletedFqids: string[] = []; + for (const coll of Object.keys(deletedData)) { + for (const id of deletedData[coll]) { + deletedFqids.push(fqidFromCollectionAndId(coll, id)); + } + } + + if (deletedFqids.length) { + this.sharedWorker.sendMessage(`autoupdate`, { + action: `cleanup-cache`, + params: { + streamId, + deletedFqids + } + } as AutoupdateCleanupCache); + } + } + /** * @returns Observable containing messages from autoupdate */ diff --git a/client/src/app/site/services/autoupdate/autoupdate.service.ts b/client/src/app/site/services/autoupdate/autoupdate.service.ts index f81842b1f0..2d050b4ef3 100644 --- a/client/src/app/site/services/autoupdate/autoupdate.service.ts +++ b/client/src/app/site/services/autoupdate/autoupdate.service.ts @@ -236,7 +236,9 @@ export class AutoupdateService { changedFullListModels: fullListUpdateCollections, deletedModels: {} }) - .then(() => { + .then(deletedModels => { + this.communication.cleanupCollections(requestId, deletedModels); + if (this._resolveDataReceived[requestId]) { this._resolveDataReceived[requestId](modelData); delete this._resolveDataReceived[requestId]; diff --git a/client/src/app/site/services/view-model-store-update.service.ts b/client/src/app/site/services/view-model-store-update.service.ts index cfaf044a0c..371a58e76e 100644 --- a/client/src/app/site/services/view-model-store-update.service.ts +++ b/client/src/app/site/services/view-model-store-update.service.ts @@ -56,7 +56,7 @@ export class ViewModelStoreUpdateService { changedFullListModels, deletedModels, patch - }: UpdatePatch): Promise { + }: UpdatePatch): Promise { const _deletedModels: DeletedModels = {}; const _changedModels: ChangedModels = {}; @@ -86,6 +86,7 @@ export class ViewModelStoreUpdateService { } await this.doCollectionUpdates(_changedModels, _deletedModels); + return _deletedModels; } private createCollectionUpdate( diff --git a/client/src/app/worker/autoupdate-stream.ts b/client/src/app/worker/autoupdate-stream.ts index 31de3a4e92..1153c3494d 100644 --- a/client/src/app/worker/autoupdate-stream.ts +++ b/client/src/app/worker/autoupdate-stream.ts @@ -167,6 +167,30 @@ export class AutoupdateStream { this.clearSubscriptions(); } + /** + * Removes fqids from the cache. + * + * @param fqids list of fqids to delete + */ + public removeFqids(fqids: string[]): void { + let lastHit: string | null = null; + for (const key of Object.keys(this._currentData)) { + if (lastHit === null || !key.startsWith(fqids[lastHit] + `/`)) { + lastHit = null; + for (let i = 0; i < fqids.length; i++) { + if (key.startsWith(fqids[i] + `/`)) { + lastHit = key; + break; + } + } + } + + if (lastHit !== null) { + delete this._currentData[key]; + } + } + } + public clearSubscriptions(): void { this._currentData = null; } diff --git a/client/src/app/worker/interfaces-autoupdate.ts b/client/src/app/worker/interfaces-autoupdate.ts index d9f1823128..30445b475d 100644 --- a/client/src/app/worker/interfaces-autoupdate.ts +++ b/client/src/app/worker/interfaces-autoupdate.ts @@ -34,6 +34,16 @@ export interface AutoupdateCloseStream extends WorkerMessageContent { params: AutoupdateCloseStreamParams; } +export interface AutoupdateCleanupCacheParams { + streamId: number; + deletedFqids: string[]; +} + +export interface AutoupdateCleanupCache extends WorkerMessageContent { + action: 'cleanup-cache'; + params: AutoupdateCleanupCacheParams; +} + export interface AutoupdateSetConnectionStatusParams { status: 'online' | 'offline'; } diff --git a/client/src/app/worker/sw-autoupdate.ts b/client/src/app/worker/sw-autoupdate.ts index 5d988cf63d..7b35f81595 100644 --- a/client/src/app/worker/sw-autoupdate.ts +++ b/client/src/app/worker/sw-autoupdate.ts @@ -3,6 +3,7 @@ import { environment } from 'src/environments/environment'; import { AutoupdateStreamPool } from './autoupdate-stream-pool'; import { AutoupdateSubscription } from './autoupdate-subscription'; import { + AutoupdateCleanupCacheParams, AutoupdateCloseStreamParams, AutoupdateOpenStreamParams, AutoupdateSetEndpointParams @@ -134,6 +135,15 @@ function closeConnection(ctx: MessagePort, params: AutoupdateCloseStreamParams): subscription.closePort(ctx); } +function cleanupStream(params: AutoupdateCleanupCacheParams): void { + const subscription = autoupdatePool.getSubscriptionById(params.streamId); + if (!subscription) { + return; + } + + subscription.stream.removeFqids(params.deletedFqids); +} + let currentlyOnline = navigator.onLine; function updateOnlineStatus(): void { if (currentlyOnline === navigator.onLine) { @@ -180,6 +190,9 @@ export function addAutoupdateListener(context: any): void { case `reconnect-force`: autoupdatePool.reconnectAll(false); break; + case `cleanup-cache`: + cleanupStream(params); + break; case `enable-debug`: registerDebugCommands(); break;