model-cache.ts 2.1 KB

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