mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-10 22:54:05 -08:00
f53c482939
Story: https://linear.app/n8n/issue/PAY-1188 - Implement Redis hashes on the caching service, based on Micha's work in #7747, adapted from `node-cache-manager-ioredis-yet`. Optimize workflow ownership lookups and manual webhook lookups with Redis hashes. - Simplify the caching service by removing all currently unused methods and options: `enable`, `disable`, `getCache`, `keys`, `keyValues`, `refreshFunctionEach`, `refreshFunctionMany`, `refreshTtl`, etc. - Remove the flag `N8N_CACHE_ENABLED`. Currently some features on `master` are broken with caching disabled, and test webhooks now rely entirely on caching, for multi-main setup support. We originally introduced this flag to protect against excessive memory usage, but total cache usage is low enough that we decided to drop this setting. Apparently this flag was also never documented. - Overall caching service refactor: use generics, reduce branching, add discriminants for cache kinds for better type safety, type caching events, improve readability, remove outdated docs, etc. Also refactor and expand caching service tests. Follow-up to: https://github.com/n8n-io/n8n/pull/8176 --------- Co-authored-by: Michael Auerswald <michael.auerswald@gmail.com>
68 lines
2 KiB
TypeScript
68 lines
2 KiB
TypeScript
import Container from 'typedi';
|
|
import { mock } from 'jest-mock-extended';
|
|
import { CacheService } from '@/services/cache/cache.service';
|
|
|
|
const cacheService = Container.get(CacheService);
|
|
const store = mock<NonNullable<CacheService['cache']>['store']>({ isCacheable: () => true });
|
|
Object.assign(cacheService, { cache: { store } });
|
|
|
|
describe('CacheService (Mock)', () => {
|
|
beforeEach(() => jest.clearAllMocks());
|
|
|
|
describe('should prevent use of empty keys', () => {
|
|
test('get', async () => {
|
|
await cacheService.get('');
|
|
expect(store.get).not.toHaveBeenCalled();
|
|
|
|
await cacheService.get('key');
|
|
expect(store.get).toHaveBeenCalledWith('key');
|
|
});
|
|
|
|
test('getMany', async () => {
|
|
await cacheService.getMany([]);
|
|
expect(store.mget).not.toHaveBeenCalled();
|
|
|
|
await cacheService.getMany(['key1', 'key2']);
|
|
expect(store.mget).toHaveBeenCalledWith('key1', 'key2');
|
|
});
|
|
|
|
test('set', async () => {
|
|
await cacheService.set('', '');
|
|
expect(store.set).not.toHaveBeenCalled();
|
|
|
|
await cacheService.set('key', 'value');
|
|
expect(store.set).toHaveBeenCalledWith('key', 'value', undefined);
|
|
|
|
await cacheService.set('key', 'value', 123);
|
|
expect(store.set).toHaveBeenCalledWith('key', 'value', 123);
|
|
});
|
|
|
|
test('setMany', async () => {
|
|
await cacheService.setMany([]);
|
|
expect(store.mset).not.toHaveBeenCalled();
|
|
|
|
await cacheService.setMany([['key', 'value']]);
|
|
expect(store.mset).toHaveBeenCalledWith([['key', 'value']], undefined);
|
|
|
|
await cacheService.setMany([['key', 'value']], 123);
|
|
expect(store.mset).toHaveBeenCalledWith([['key', 'value']], 123);
|
|
});
|
|
|
|
test('delete', async () => {
|
|
await cacheService.delete('');
|
|
expect(store.del).not.toHaveBeenCalled();
|
|
|
|
await cacheService.delete('key');
|
|
expect(store.del).toHaveBeenCalledWith('key');
|
|
});
|
|
|
|
test('deleteMany', async () => {
|
|
await cacheService.deleteMany([]);
|
|
expect(store.mdel).not.toHaveBeenCalled();
|
|
|
|
await cacheService.deleteMany(['key1', 'key2']);
|
|
expect(store.mdel).toHaveBeenCalledWith('key1', 'key2');
|
|
});
|
|
});
|
|
});
|