model-cache.ts 2.1 KB

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