]>
Commit | Line | Data |
---|---|---|
0ffd6d32 | 1 | import { Model } from 'sequelize-typescript' |
0ffd6d32 C |
2 | import { logger } from '@server/helpers/logger' |
3 | ||
4 | type ModelCacheType = | |
5 | 'local-account-name' | |
6 | | 'local-actor-name' | |
7 | | 'local-actor-url' | |
943e5193 C |
8 | | 'load-video-immutable-id' |
9 | | 'load-video-immutable-url' | |
7eba5e1f C |
10 | |
11 | type DeleteKey = | |
12 | 'video' | |
0ffd6d32 C |
13 | |
14 | class ModelCache { | |
15 | ||
16 | private static instance: ModelCache | |
17 | ||
18 | private readonly localCache: { [id in ModelCacheType]: Map<string, any> } = { | |
19 | 'local-account-name': new Map(), | |
20 | 'local-actor-name': new Map(), | |
7eba5e1f | 21 | 'local-actor-url': new Map(), |
943e5193 C |
22 | 'load-video-immutable-id': new Map(), |
23 | 'load-video-immutable-url': new Map() | |
7eba5e1f C |
24 | } |
25 | ||
26 | private readonly deleteIds: { | |
27 | [deleteKey in DeleteKey]: Map<number, { cacheType: ModelCacheType, key: string }[]> | |
28 | } = { | |
29 | video: new Map() | |
0ffd6d32 C |
30 | } |
31 | ||
32 | private constructor () { | |
33 | } | |
34 | ||
35 | static get Instance () { | |
36 | return this.instance || (this.instance = new this()) | |
37 | } | |
38 | ||
39 | doCache<T extends Model> (options: { | |
40 | cacheType: ModelCacheType | |
41 | key: string | |
b49f22d8 | 42 | fun: () => Promise<T> |
0ffd6d32 | 43 | whitelist?: () => boolean |
7eba5e1f | 44 | deleteKey?: DeleteKey |
0ffd6d32 | 45 | }) { |
7eba5e1f | 46 | const { cacheType, key, fun, whitelist, deleteKey } = options |
0ffd6d32 C |
47 | |
48 | if (whitelist && whitelist() !== true) return fun() | |
49 | ||
50 | const cache = this.localCache[cacheType] | |
51 | ||
52 | if (cache.has(key)) { | |
53 | logger.debug('Model cache hit for %s -> %s.', cacheType, key) | |
41fb13c3 | 54 | return Promise.resolve<T>(cache.get(key)) |
0ffd6d32 C |
55 | } |
56 | ||
57 | return fun().then(m => { | |
7eba5e1f C |
58 | if (!m) return m |
59 | ||
0ffd6d32 C |
60 | if (!whitelist || whitelist()) cache.set(key, m) |
61 | ||
7eba5e1f C |
62 | if (deleteKey) { |
63 | const map = this.deleteIds[deleteKey] | |
64 | if (!map.has(m.id)) map.set(m.id, []) | |
65 | ||
66 | const a = map.get(m.id) | |
67 | a.push({ cacheType, key }) | |
68 | } | |
69 | ||
0ffd6d32 C |
70 | return m |
71 | }) | |
72 | } | |
7eba5e1f C |
73 | |
74 | invalidateCache (deleteKey: DeleteKey, modelId: number) { | |
75 | const map = this.deleteIds[deleteKey] | |
76 | ||
77 | if (!map.has(modelId)) return | |
78 | ||
79 | for (const toDelete of map.get(modelId)) { | |
80 | logger.debug('Removing %s -> %d of model cache %s -> %s.', deleteKey, modelId, toDelete.cacheType, toDelete.key) | |
81 | this.localCache[toDelete.cacheType].delete(toDelete.key) | |
82 | } | |
83 | ||
84 | map.delete(modelId) | |
85 | } | |
0ffd6d32 C |
86 | } |
87 | ||
88 | export { | |
89 | ModelCache | |
90 | } |