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