mirror of
https://github.com/immich-app/immich.git
synced 2026-02-28 01:29:04 +03:00
fix(web): clear cache when asset changes (#26257)
* fix(web): clear cache when asset changes * formatting
This commit is contained in:
@@ -1,25 +1,23 @@
|
|||||||
|
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||||
import { eventManager } from '$lib/managers/event-manager.svelte';
|
import { eventManager } from '$lib/managers/event-manager.svelte';
|
||||||
import { getAssetInfo, getAssetOcr, type AssetOcrResponseDto, type AssetResponseDto } from '@immich/sdk';
|
import { getAssetInfo, getAssetOcr } from '@immich/sdk';
|
||||||
|
|
||||||
const defaultSerializer = <K>(params: K) => JSON.stringify(params);
|
const defaultSerializer = <K>(params: K) => JSON.stringify(params);
|
||||||
|
|
||||||
class AsyncCache<V> {
|
class AsyncCache<K, V> {
|
||||||
#cache = new Map<string, V>();
|
#cache = new Map<string, V>();
|
||||||
|
|
||||||
async getOrFetch<K>(
|
constructor(private fetcher: (params: K) => Promise<V>) {}
|
||||||
params: K,
|
|
||||||
fetcher: (params: K) => Promise<V>,
|
async getOrFetch(params: K, updateCache: boolean): Promise<V> {
|
||||||
keySerializer: (params: K) => string = defaultSerializer,
|
const cacheKey = defaultSerializer(params);
|
||||||
updateCache: boolean,
|
|
||||||
): Promise<V> {
|
|
||||||
const cacheKey = keySerializer(params);
|
|
||||||
|
|
||||||
const cached = this.#cache.get(cacheKey);
|
const cached = this.#cache.get(cacheKey);
|
||||||
if (cached) {
|
if (cached) {
|
||||||
return cached;
|
return cached;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = await fetcher(params);
|
const value = await this.fetcher(params);
|
||||||
if (value && updateCache) {
|
if (value && updateCache) {
|
||||||
this.#cache.set(cacheKey, value);
|
this.#cache.set(cacheKey, value);
|
||||||
}
|
}
|
||||||
@@ -27,30 +25,43 @@ class AsyncCache<V> {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearKey(params: K) {
|
||||||
|
const cacheKey = defaultSerializer(params);
|
||||||
|
this.#cache.delete(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
clear() {
|
clear() {
|
||||||
this.#cache.clear();
|
this.#cache.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AssetCacheManager {
|
class AssetCacheManager {
|
||||||
#assetCache = new AsyncCache<AssetResponseDto>();
|
#assetCache = new AsyncCache(getAssetInfo);
|
||||||
#ocrCache = new AsyncCache<AssetOcrResponseDto[]>();
|
#ocrCache = new AsyncCache(getAssetOcr);
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
eventManager.on({
|
eventManager.on({
|
||||||
AssetEditsApplied: () => {
|
AssetEditsApplied: (assetId) => {
|
||||||
this.#assetCache.clear();
|
this.invalidateAsset(assetId);
|
||||||
this.#ocrCache.clear();
|
},
|
||||||
|
AssetUpdate: (asset) => {
|
||||||
|
this.invalidateAsset(asset.id);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAsset(assetIdentifier: { key?: string; slug?: string; id: string }, updateCache = true) {
|
async getAsset({ id, key, slug }: { id: string; key?: string; slug?: string }, updateCache = true) {
|
||||||
return this.#assetCache.getOrFetch(assetIdentifier, getAssetInfo, defaultSerializer, updateCache);
|
return this.#assetCache.getOrFetch({ id, key, slug }, updateCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAssetOcr(id: string) {
|
async getAssetOcr(id: string) {
|
||||||
return this.#ocrCache.getOrFetch({ id }, getAssetOcr, (params) => params.id, true);
|
return this.#ocrCache.getOrFetch({ id }, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidateAsset(id: string) {
|
||||||
|
const { key, slug } = authManager.params;
|
||||||
|
this.#assetCache.clearKey({ id, key, slug });
|
||||||
|
this.#ocrCache.clearKey({ id });
|
||||||
}
|
}
|
||||||
|
|
||||||
clearAssetCache() {
|
clearAssetCache() {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|||||||
|
|
||||||
// Mock the SDK
|
// Mock the SDK
|
||||||
vi.mock('@immich/sdk', () => ({
|
vi.mock('@immich/sdk', () => ({
|
||||||
|
getAssetInfo: vi.fn(),
|
||||||
getAssetOcr: vi.fn(),
|
getAssetOcr: vi.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ websocket
|
|||||||
.on('on_new_release', (event) => eventManager.emit('ReleaseEvent', event))
|
.on('on_new_release', (event) => eventManager.emit('ReleaseEvent', event))
|
||||||
.on('on_session_delete', () => authManager.logout())
|
.on('on_session_delete', () => authManager.logout())
|
||||||
.on('on_user_delete', (id) => eventManager.emit('UserAdminDeleted', { id }))
|
.on('on_user_delete', (id) => eventManager.emit('UserAdminDeleted', { id }))
|
||||||
|
.on('on_asset_update', (asset) => eventManager.emit('AssetUpdate', asset))
|
||||||
.on('on_person_thumbnail', (id) => eventManager.emit('PersonThumbnailReady', { id }))
|
.on('on_person_thumbnail', (id) => eventManager.emit('PersonThumbnailReady', { id }))
|
||||||
.on('on_notification', () => notificationManager.refresh())
|
.on('on_notification', () => notificationManager.refresh())
|
||||||
.on('connect_error', (e) => console.log('Websocket Connect Error', e));
|
.on('connect_error', (e) => console.log('Websocket Connect Error', e));
|
||||||
|
|||||||
Reference in New Issue
Block a user