diff --git a/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts b/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts index c075bccaa1..d15671d5d2 100644 --- a/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts +++ b/packages/backend-defaults/src/entrypoints/cache/CacheManager.test.ts @@ -25,15 +25,21 @@ import { CacheManager } from './CacheManager'; // Contrived code because it's hard to spy on a default export jest.mock('@keyv/redis', () => { const Actual = jest.requireActual('@keyv/redis'); - return jest.fn((...args: any[]) => { - return new Actual(...args); - }); + const DefaultConstructor = Actual.default; + return { + ...Actual, + __esModule: true, + default: jest.fn((...args: any[]) => new DefaultConstructor(...args)), + }; }); jest.mock('@keyv/memcache', () => { const Actual = jest.requireActual('@keyv/memcache'); - return jest.fn((...args: any[]) => { - return new Actual(...args); - }); + const DefaultConstructor = Actual.default; + return { + ...Actual, + __esModule: true, + default: jest.fn((...args: any[]) => new DefaultConstructor(...args)), + }; }); describe('CacheManager integration', () => { @@ -42,7 +48,7 @@ describe('CacheManager integration', () => { afterEach(jest.clearAllMocks); it.each(caches.eachSupportedId())( - 'only creates one underlying connection, %p', + 'only creates one underlying connection per plugin, %p', async cacheId => { const { store, connection } = await caches.init(cacheId); @@ -59,10 +65,10 @@ describe('CacheManager integration', () => { if (store === 'redis') { // eslint-disable-next-line jest/no-conditional-expect - expect(KeyvRedis).toHaveBeenCalledTimes(1); + expect(KeyvRedis).toHaveBeenCalledTimes(3); } else if (store === 'memcache') { // eslint-disable-next-line jest/no-conditional-expect - expect(KeyvMemcache).toHaveBeenCalledTimes(1); + expect(KeyvMemcache).toHaveBeenCalledTimes(3); } }, ); diff --git a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts index 4746035b10..57c326f00d 100644 --- a/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts +++ b/packages/backend-defaults/src/entrypoints/cache/CacheManager.ts @@ -140,14 +140,15 @@ export class CacheManager { private createRedisStoreFactory(): StoreFactory { const KeyvRedis = require('@keyv/redis').default; - let store: typeof KeyvRedis | undefined; + const stores: Record = {}; + return (pluginId, defaultTtl) => { - if (!store) { - store = new KeyvRedis(this.connection, { + if (!stores[pluginId]) { + stores[pluginId] = new KeyvRedis(this.connection, { keyPrefixSeparator: ':', }); // Always provide an error handler to avoid stopping the process - store.on('error', (err: Error) => { + stores[pluginId].on('error', (err: Error) => { this.logger?.error('Failed to create redis cache client', err); this.errorHandler?.(err); }); @@ -155,7 +156,7 @@ export class CacheManager { return new Keyv({ namespace: pluginId, ttl: defaultTtl, - store, + store: stores[pluginId], emitErrors: false, useKeyPrefix: false, }); @@ -163,13 +164,14 @@ export class CacheManager { } private createMemcacheStoreFactory(): StoreFactory { - const KeyvMemcache = require('@keyv/memcache'); - let store: typeof KeyvMemcache | undefined; + const KeyvMemcache = require('@keyv/memcache').default; + const stores: Record = {}; + return (pluginId, defaultTtl) => { - if (!store) { - store = new KeyvMemcache(this.connection); + if (!stores[pluginId]) { + stores[pluginId] = new KeyvMemcache(this.connection); // Always provide an error handler to avoid stopping the process - store.on('error', (err: Error) => { + stores[pluginId].on('error', (err: Error) => { this.logger?.error('Failed to create memcache cache client', err); this.errorHandler?.(err); }); @@ -178,7 +180,7 @@ export class CacheManager { namespace: pluginId, ttl: defaultTtl, emitErrors: false, - store, + store: stores[pluginId], }); }; }