ニジカ投稿局 https://tv.nizika.tv
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

95 lines
2.2 KiB

  1. import { Model } from 'sequelize-typescript'
  2. import { logger } from '@server/helpers/logger.js'
  3. type ModelCacheType =
  4. 'server-account'
  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. 'server-account': 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. clearCache (cacheType: ModelCacheType) {
  66. this.localCache[cacheType] = new Map()
  67. }
  68. }
  69. export {
  70. ModelCache
  71. }