diff --git a/libs/common/src/platform/state/derive-definition.ts b/libs/common/src/platform/state/derive-definition.ts index 702a4cce9bf..c164316be92 100644 --- a/libs/common/src/platform/state/derive-definition.ts +++ b/libs/common/src/platform/state/derive-definition.ts @@ -48,6 +48,10 @@ type DeriveDefinitionOptions { expect(parentState$.observed).toBe(false); }); + it("should clear state after cleanup", async () => { + const subscription = sut.state$.subscribe(); + parentState$.next(newDate); + await awaitAsync(); + + expect(memoryStorage.internalStore[deriveDefinition.buildCacheKey()]).toEqual( + new Date(newDate), + ); + + subscription.unsubscribe(); + // Wait for cleanup + await awaitAsync(cleanupDelayMs * 2); + + expect(memoryStorage.internalStore[deriveDefinition.buildCacheKey()]).toBeUndefined(); + }); + + it("should not clear state after cleanup if clearOnCleanup is false", async () => { + deriveDefinition.options.clearOnCleanup = false; + + const subscription = sut.state$.subscribe(); + parentState$.next(newDate); + await awaitAsync(); + + expect(memoryStorage.internalStore[deriveDefinition.buildCacheKey()]).toEqual( + new Date(newDate), + ); + + subscription.unsubscribe(); + // Wait for cleanup + await awaitAsync(cleanupDelayMs * 2); + + expect(memoryStorage.internalStore[deriveDefinition.buildCacheKey()]).toEqual( + new Date(newDate), + ); + }); + it("should not cleanup if there are still subscribers", async () => { const subscription1 = sut.state$.subscribe(); const sub2Emissions: Date[] = []; diff --git a/libs/common/src/platform/state/implementations/default-derived-state.ts b/libs/common/src/platform/state/implementations/default-derived-state.ts index 186faf99877..64a15e4acc5 100644 --- a/libs/common/src/platform/state/implementations/default-derived-state.ts +++ b/libs/common/src/platform/state/implementations/default-derived-state.ts @@ -44,7 +44,15 @@ export class DefaultDerivedState { return new ReplaySubject(1); }, - resetOnRefCountZero: () => timer(this.deriveDefinition.cleanupDelayMs), + resetOnRefCountZero: () => + timer(this.deriveDefinition.cleanupDelayMs).pipe( + concatMap(async () => { + if (this.deriveDefinition.clearOnCleanup) { + await this.memoryStorage.remove(this.storageKey); + } + return true; + }), + ), }), ); }