| | import type { CanvasManager } from 'features/controlLayers/konva/CanvasManager'; |
| | import { CanvasModuleBase } from 'features/controlLayers/konva/CanvasModuleBase'; |
| | import type { Transparency } from 'features/controlLayers/konva/util'; |
| | import { getPrefixedId } from 'features/controlLayers/konva/util'; |
| | import type { GenerationMode } from 'features/controlLayers/store/types'; |
| | import { LRUCache } from 'lru-cache'; |
| | import type { Logger } from 'roarr'; |
| |
|
| | type GetCacheEntryWithFallbackArg<T extends NonNullable<unknown>> = { |
| | cache: LRUCache<string, T>; |
| | key: string; |
| | getValue: () => Promise<T>; |
| | onHit?: (value: T) => void; |
| | onMiss?: () => void; |
| | }; |
| |
|
| | type CanvasCacheModuleConfig = { |
| | |
| | |
| | |
| | imageNameCacheSize: number; |
| | |
| | |
| | |
| | imageDataCacheSize: number; |
| | |
| | |
| | |
| | transparencyCalculationCacheSize: number; |
| | |
| | |
| | |
| | canvasElementCacheSize: number; |
| | |
| | |
| | |
| | generationModeCacheSize: number; |
| | }; |
| |
|
| | const DEFAULT_CONFIG: CanvasCacheModuleConfig = { |
| | imageNameCacheSize: 1000, |
| | imageDataCacheSize: 32, |
| | transparencyCalculationCacheSize: 1000, |
| | canvasElementCacheSize: 32, |
| | generationModeCacheSize: 100, |
| | }; |
| |
|
| | |
| | |
| | |
| | |
| | export class CanvasCacheModule extends CanvasModuleBase { |
| | readonly type = 'cache'; |
| | readonly id: string; |
| | readonly path: string[]; |
| | readonly log: Logger; |
| | readonly parent: CanvasManager; |
| | readonly manager: CanvasManager; |
| |
|
| | config: CanvasCacheModuleConfig = DEFAULT_CONFIG; |
| |
|
| | |
| | |
| | |
| | |
| | |
| | imageNameCache = new LRUCache<string, string>({ max: this.config.imageNameCacheSize }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | canvasElementCache = new LRUCache<string, HTMLCanvasElement>({ max: this.config.canvasElementCacheSize }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | imageDataCache = new LRUCache<string, ImageData>({ max: this.config.imageDataCacheSize }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | transparencyCalculationCache = new LRUCache<string, Transparency>({ max: this.config.imageDataCacheSize }); |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | generationModeCache = new LRUCache<string, GenerationMode>({ max: this.config.generationModeCacheSize }); |
| |
|
| | constructor(manager: CanvasManager) { |
| | super(); |
| | this.id = getPrefixedId('cache'); |
| | this.manager = manager; |
| | this.parent = manager; |
| | this.path = this.manager.buildPath(this); |
| | this.log = this.manager.buildLogger(this); |
| |
|
| | this.log.debug('Creating cache module'); |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | static getWithFallback = async <T extends NonNullable<unknown>>({ |
| | cache, |
| | getValue, |
| | key, |
| | onHit, |
| | onMiss, |
| | }: GetCacheEntryWithFallbackArg<T>): Promise<T> => { |
| | let value = cache.get(key); |
| | if (value === undefined) { |
| | onMiss?.(); |
| | value = await getValue(); |
| | cache.set(key, value); |
| | } else { |
| | onHit?.(value); |
| | } |
| | return value; |
| | }; |
| |
|
| | |
| | |
| | |
| | clearAll = () => { |
| | this.canvasElementCache.clear(); |
| | this.imageNameCache.clear(); |
| | this.generationModeCache.clear(); |
| | }; |
| |
|
| | destroy = () => { |
| | this.log.debug('Destroying cache module'); |
| | this.clearAll(); |
| | }; |
| | } |
| |
|