Refactor backend folder structure (#4505)
* Refactor backend folder structure Co-authored-by: Charles Bochet <charles@twenty.com> * fix tests * fix * move yoga hooks --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -0,0 +1,78 @@
|
||||
import { Cache } from '@nestjs/cache-manager';
|
||||
|
||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||
|
||||
const cacheStorageNamespace = CacheStorageNamespace.Messaging;
|
||||
|
||||
describe('CacheStorageService', () => {
|
||||
let cacheStorageService: CacheStorageService;
|
||||
let cacheManagerMock: Partial<Cache>;
|
||||
|
||||
beforeEach(() => {
|
||||
cacheManagerMock = {
|
||||
get: jest.fn(),
|
||||
set: jest.fn(),
|
||||
};
|
||||
|
||||
cacheStorageService = new CacheStorageService(
|
||||
cacheManagerMock as Cache,
|
||||
cacheStorageNamespace,
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('get', () => {
|
||||
it('should call cacheManager.get with the correct namespaced key', async () => {
|
||||
const key = 'testKey';
|
||||
const namespacedKey = `${cacheStorageNamespace}:${key}`;
|
||||
|
||||
await cacheStorageService.get(key);
|
||||
|
||||
expect(cacheManagerMock.get).toHaveBeenCalledWith(namespacedKey);
|
||||
});
|
||||
|
||||
it('should return the value returned by cacheManager.get', async () => {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
|
||||
jest.spyOn(cacheManagerMock, 'get').mockResolvedValue(value);
|
||||
|
||||
const result = await cacheStorageService.get(key);
|
||||
|
||||
expect(result).toBe(value);
|
||||
});
|
||||
});
|
||||
|
||||
describe('set', () => {
|
||||
it('should call cacheManager.set with the correct namespaced key, value, and optional ttl', async () => {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
const ttl = 60;
|
||||
const namespacedKey = `${cacheStorageNamespace}:${key}`;
|
||||
|
||||
await cacheStorageService.set(key, value, ttl);
|
||||
|
||||
expect(cacheManagerMock.set).toHaveBeenCalledWith(
|
||||
namespacedKey,
|
||||
value,
|
||||
ttl,
|
||||
);
|
||||
});
|
||||
|
||||
it('should not throw if cacheManager.set resolves successfully', async () => {
|
||||
const key = 'testKey';
|
||||
const value = 'testValue';
|
||||
const ttl = 60;
|
||||
|
||||
jest.spyOn(cacheManagerMock, 'set').mockResolvedValue(undefined);
|
||||
|
||||
await expect(
|
||||
cacheStorageService.set(key, value, ttl),
|
||||
).resolves.not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,46 @@
|
||||
import { CacheModuleOptions } from '@nestjs/common';
|
||||
|
||||
import { redisStore } from 'cache-manager-redis-yet';
|
||||
|
||||
import { CacheStorageType } from 'src/engine/integrations/cache-storage/types/cache-storage-type.enum';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
|
||||
export const cacheStorageModuleFactory = (
|
||||
environmentService: EnvironmentService,
|
||||
): CacheModuleOptions => {
|
||||
const cacheStorageType = environmentService.get('CACHE_STORAGE_TYPE');
|
||||
const cacheStorageTtl = environmentService.get('CACHE_STORAGE_TTL');
|
||||
const cacheModuleOptions: CacheModuleOptions = {
|
||||
isGlobal: true,
|
||||
ttl: cacheStorageTtl * 1000,
|
||||
};
|
||||
|
||||
switch (cacheStorageType) {
|
||||
case CacheStorageType.Memory: {
|
||||
return cacheModuleOptions;
|
||||
}
|
||||
case CacheStorageType.Redis: {
|
||||
const host = environmentService.get('REDIS_HOST');
|
||||
const port = environmentService.get('REDIS_PORT');
|
||||
|
||||
if (!(host && port)) {
|
||||
throw new Error(
|
||||
`${cacheStorageType} cache storage requires host: ${host} and port: ${port} to be defined, check your .env file`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
...cacheModuleOptions,
|
||||
store: redisStore,
|
||||
socket: {
|
||||
host,
|
||||
port,
|
||||
},
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw new Error(
|
||||
`Invalid cache-storage (${cacheStorageType}), check your .env file`,
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -0,0 +1,31 @@
|
||||
import { Module, Global } from '@nestjs/common';
|
||||
import { CacheModule, CACHE_MANAGER, Cache } from '@nestjs/cache-manager';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { cacheStorageModuleFactory } from 'src/engine/integrations/cache-storage/cache-storage.module-factory';
|
||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
imports: [
|
||||
CacheModule.registerAsync({
|
||||
isGlobal: true,
|
||||
imports: [ConfigModule],
|
||||
useFactory: cacheStorageModuleFactory,
|
||||
inject: [EnvironmentService],
|
||||
}),
|
||||
],
|
||||
providers: [
|
||||
...Object.values(CacheStorageNamespace).map((cacheStorageNamespace) => ({
|
||||
provide: cacheStorageNamespace,
|
||||
useFactory: (cacheManager: Cache) => {
|
||||
return new CacheStorageService(cacheManager, cacheStorageNamespace);
|
||||
},
|
||||
inject: [CACHE_MANAGER],
|
||||
})),
|
||||
],
|
||||
exports: [...Object.values(CacheStorageNamespace)],
|
||||
})
|
||||
export class CacheStorageModule {}
|
||||
@ -0,0 +1,25 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { CACHE_MANAGER, Cache } from '@nestjs/cache-manager';
|
||||
|
||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||
|
||||
@Injectable()
|
||||
export class CacheStorageService {
|
||||
constructor(
|
||||
@Inject(CACHE_MANAGER)
|
||||
private readonly cacheManager: Cache,
|
||||
private readonly namespace: CacheStorageNamespace,
|
||||
) {}
|
||||
|
||||
async get<T>(key: string): Promise<T | undefined> {
|
||||
return this.cacheManager.get(`${this.namespace}:${key}`);
|
||||
}
|
||||
|
||||
async set<T>(key: string, value: T, ttl?: number) {
|
||||
return this.cacheManager.set(`${this.namespace}:${key}`, value, ttl);
|
||||
}
|
||||
|
||||
async del(key: string) {
|
||||
return this.cacheManager.del(`${this.namespace}:${key}`);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
export enum CacheStorageNamespace {
|
||||
Messaging = 'messaging',
|
||||
WorkspaceSchema = 'workspaceSchema',
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
export enum CacheStorageType {
|
||||
Memory = 'memory',
|
||||
Redis = 'redis',
|
||||
}
|
||||
Reference in New Issue
Block a user