cache.service.ts 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import { Injectable } from '@nestjs/common';
  2. import { JsonCompatible } from '@vendure/common/lib/shared-types';
  3. import { Instrument } from '../common';
  4. import { ConfigService } from '../config/config.service';
  5. import { Logger } from '../config/index';
  6. import { CacheStrategy, SetCacheKeyOptions } from '../config/system/cache-strategy';
  7. import { Cache, CacheConfig } from './cache';
  8. /**
  9. * @description
  10. * The CacheService is used to cache data in order to optimize performance.
  11. *
  12. * Internally it makes use of the configured {@link CacheStrategy} to persist
  13. * the cache into a key-value store.
  14. *
  15. * @since 3.1.0
  16. * @docsCategory cache
  17. */
  18. @Injectable()
  19. @Instrument()
  20. export class CacheService {
  21. protected cacheStrategy: CacheStrategy;
  22. constructor(private configService: ConfigService) {
  23. this.cacheStrategy = this.configService.systemOptions.cacheStrategy;
  24. }
  25. /**
  26. * @description
  27. * Creates a new {@link Cache} instance with the given configuration.
  28. *
  29. * The `Cache` instance provides a convenience wrapper around the `CacheService`
  30. * methods.
  31. */
  32. createCache(config: CacheConfig): Cache {
  33. return new Cache(config, this);
  34. }
  35. /**
  36. * @description
  37. * Gets an item from the cache, or returns undefined if the key is not found, or the
  38. * item has expired.
  39. */
  40. async get<T extends JsonCompatible<T>>(key: string): Promise<T | undefined> {
  41. try {
  42. const result = await this.cacheStrategy.get(key);
  43. if (result) {
  44. Logger.debug(`CacheService hit for key [${key}]`);
  45. }
  46. return result as T;
  47. } catch (e: any) {
  48. Logger.error(`Could not get key [${key}] from CacheService`, undefined, e.stack);
  49. }
  50. }
  51. /**
  52. * @description
  53. * Sets a key-value pair in the cache. The value must be serializable, so cannot contain
  54. * things like functions, circular data structures, class instances etc.
  55. *
  56. * Optionally a "time to live" (ttl) can be specified, which means that the key will
  57. * be considered stale after that many milliseconds.
  58. */
  59. async set<T extends JsonCompatible<T>>(
  60. key: string,
  61. value: T,
  62. options?: SetCacheKeyOptions,
  63. ): Promise<void> {
  64. try {
  65. await this.cacheStrategy.set(key, value, options);
  66. Logger.debug(`Set key [${key}] in CacheService`);
  67. } catch (e: any) {
  68. Logger.error(`Could not set key [${key}] in CacheService`, undefined, e.stack);
  69. }
  70. }
  71. /**
  72. * @description
  73. * Deletes an item from the cache.
  74. */
  75. async delete(key: string): Promise<void> {
  76. try {
  77. await this.cacheStrategy.delete(key);
  78. Logger.debug(`Deleted key [${key}] from CacheService`);
  79. } catch (e: any) {
  80. Logger.error(`Could not delete key [${key}] from CacheService`, undefined, e.stack);
  81. }
  82. }
  83. /**
  84. * @description
  85. * Deletes all items from the cache which contain at least one matching tag.
  86. */
  87. async invalidateTags(tags: string[]): Promise<void> {
  88. try {
  89. await this.cacheStrategy.invalidateTags(tags);
  90. Logger.debug(`Invalidated tags [${tags.join(', ')}] from CacheService`);
  91. } catch (e: any) {
  92. Logger.error(
  93. `Could not invalidate tags [${tags.join(', ')}] from CacheService`,
  94. undefined,
  95. e.stack,
  96. );
  97. }
  98. }
  99. }