diff --git a/packages/twenty-server/src/integrations/cache-storage/cache-storage.service.ts b/packages/twenty-server/src/integrations/cache-storage/cache-storage.service.ts index 5ad3641a5..fdc44ff1f 100644 --- a/packages/twenty-server/src/integrations/cache-storage/cache-storage.service.ts +++ b/packages/twenty-server/src/integrations/cache-storage/cache-storage.service.ts @@ -18,4 +18,8 @@ export class CacheStorageService { async set(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}`); + } } diff --git a/packages/twenty-server/src/integrations/cache-storage/types/cache-storage-namespace.enum.ts b/packages/twenty-server/src/integrations/cache-storage/types/cache-storage-namespace.enum.ts index ddf4f8ec1..5ef0221bc 100644 --- a/packages/twenty-server/src/integrations/cache-storage/types/cache-storage-namespace.enum.ts +++ b/packages/twenty-server/src/integrations/cache-storage/types/cache-storage-namespace.enum.ts @@ -1,3 +1,4 @@ export enum CacheStorageNamespace { Messaging = 'messaging', + WorkspaceSchema = 'workspaceSchema', } diff --git a/packages/twenty-server/src/integrations/memory-storage/decorators/inject-memory-storage.decorator.ts b/packages/twenty-server/src/integrations/memory-storage/decorators/inject-memory-storage.decorator.ts deleted file mode 100644 index c4d807087..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/decorators/inject-memory-storage.decorator.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { createMemoryStorageInjectionToken } from 'src/integrations/memory-storage/memory-storage.util'; - -export const InjectMemoryStorage = (identifier: string) => { - const injectionToken = createMemoryStorageInjectionToken(identifier); - - return Inject(injectionToken); -}; diff --git a/packages/twenty-server/src/integrations/memory-storage/drivers/interfaces/memory-storage-driver.interface.ts b/packages/twenty-server/src/integrations/memory-storage/drivers/interfaces/memory-storage-driver.interface.ts deleted file mode 100644 index a2f52e8ad..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/drivers/interfaces/memory-storage-driver.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface MemoryStorageDriver { - read(params: { key: string }): Promise; - write(params: { key: string; data: T }): Promise; - delete(params: { key: string }): Promise; -} diff --git a/packages/twenty-server/src/integrations/memory-storage/drivers/local.driver.ts b/packages/twenty-server/src/integrations/memory-storage/drivers/local.driver.ts deleted file mode 100644 index aed409997..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/drivers/local.driver.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { MemoryStorageSerializer } from 'src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface'; - -import { MemoryStorageDriver } from './interfaces/memory-storage-driver.interface'; - -// eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface LocalMemoryDriverOptions {} - -export class LocalMemoryDriver implements MemoryStorageDriver { - private identifier: string; - private options: LocalMemoryDriverOptions; - private serializer: MemoryStorageSerializer; - private storage: Map = new Map(); - - constructor( - identifier: string, - options: LocalMemoryDriverOptions, - serializer: MemoryStorageSerializer, - ) { - this.identifier = identifier; - this.options = options; - this.serializer = serializer; - } - - async write(params: { key: string; data: T }): Promise { - const compositeKey = this.generateCompositeKey(params.key); - const serializedData = this.serializer.serialize(params.data); - - this.storage.set(compositeKey, serializedData); - } - - async read(params: { key: string }): Promise { - const compositeKey = this.generateCompositeKey(params.key); - - if (!this.storage.has(compositeKey)) { - return null; - } - - const data = this.storage.get(compositeKey); - - if (!data) { - return null; - } - - const deserializeData = this.serializer.deserialize(data); - - return deserializeData; - } - - async delete(params: { key: string }): Promise { - const compositeKey = this.generateCompositeKey(params.key); - - if (!this.storage.has(compositeKey)) { - return; - } - - this.storage.delete(compositeKey); - } - - private generateCompositeKey(key: string): string { - return `${this.identifier}:${key}`; - } -} diff --git a/packages/twenty-server/src/integrations/memory-storage/interfaces/index.ts b/packages/twenty-server/src/integrations/memory-storage/interfaces/index.ts deleted file mode 100644 index 05ba64022..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/interfaces/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './memory-storage.interface'; diff --git a/packages/twenty-server/src/integrations/memory-storage/interfaces/memory-storage.interface.ts b/packages/twenty-server/src/integrations/memory-storage/interfaces/memory-storage.interface.ts deleted file mode 100644 index eca29d1d2..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/interfaces/memory-storage.interface.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { FactoryProvider, ModuleMetadata } from '@nestjs/common'; - -import { MemoryStorageSerializer } from 'src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface'; - -import { LocalMemoryDriverOptions } from 'src/integrations/memory-storage/drivers/local.driver'; - -export enum MemoryStorageDriverType { - Local = 'local', -} - -export interface LocalMemoryDriverFactoryOptions { - type: MemoryStorageDriverType.Local; - options: LocalMemoryDriverOptions; -} - -interface MemoryStorageModuleBaseOptions { - identifier: string; - serializer?: MemoryStorageSerializer; -} - -export type MemoryStorageModuleOptions = MemoryStorageModuleBaseOptions & - LocalMemoryDriverFactoryOptions; - -export type MemoryStorageModuleAsyncOptions = { - identifier: string; - useFactory: ( - ...args: any[] - ) => - | Omit - | Promise>; -} & Pick & - Pick; diff --git a/packages/twenty-server/src/integrations/memory-storage/memory-storage.constants.ts b/packages/twenty-server/src/integrations/memory-storage/memory-storage.constants.ts deleted file mode 100644 index 68881644b..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/memory-storage.constants.ts +++ /dev/null @@ -1 +0,0 @@ -export const MEMORY_STORAGE_SERVICE = 'MEMORY_STORAGE_SERVICE'; diff --git a/packages/twenty-server/src/integrations/memory-storage/memory-storage.module.ts b/packages/twenty-server/src/integrations/memory-storage/memory-storage.module.ts deleted file mode 100644 index 74e994452..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/memory-storage.module.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { DynamicModule, Global } from '@nestjs/common'; - -import { MemoryStorageDefaultSerializer } from 'src/integrations/memory-storage/serializers/default.serializer'; -import { createMemoryStorageInjectionToken } from 'src/integrations/memory-storage/memory-storage.util'; - -import { - MemoryStorageDriverType, - MemoryStorageModuleAsyncOptions, - MemoryStorageModuleOptions, -} from './interfaces'; - -import { LocalMemoryDriver } from './drivers/local.driver'; - -@Global() -export class MemoryStorageModule { - static forRoot(options: MemoryStorageModuleOptions): DynamicModule { - // Dynamic injection token to allow multiple instances of the same driver - const injectionToken = createMemoryStorageInjectionToken( - options.identifier, - ); - const provider = { - provide: injectionToken, - useValue: this.createStorageDriver(options), - }; - - return { - module: MemoryStorageModule, - providers: [provider], - exports: [provider], - }; - } - - static forRootAsync(options: MemoryStorageModuleAsyncOptions): DynamicModule { - // Dynamic injection token to allow multiple instances of the same driver - const injectionToken = createMemoryStorageInjectionToken( - options.identifier, - ); - const provider = { - provide: injectionToken, - useFactory: async (...args: any[]) => { - const config = await options.useFactory(...args); - - return this.createStorageDriver({ - identifier: options.identifier, - ...config, - }); - }, - inject: options.inject || [], - }; - - return { - module: MemoryStorageModule, - imports: options.imports || [], - providers: [provider], - exports: [provider], - }; - } - - private static createStorageDriver(options: MemoryStorageModuleOptions) { - switch (options.type) { - case MemoryStorageDriverType.Local: - return new LocalMemoryDriver( - options.identifier, - options.options, - options.serializer ?? new MemoryStorageDefaultSerializer(), - ); - // Future case for Redis or other types - default: - throw new Error(`Unsupported storage type: ${options.type}`); - } - } -} diff --git a/packages/twenty-server/src/integrations/memory-storage/memory-storage.service.spec.ts b/packages/twenty-server/src/integrations/memory-storage/memory-storage.service.spec.ts deleted file mode 100644 index b9e4ef90e..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/memory-storage.service.spec.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; - -import { MemoryStorageService } from './memory-storage.service'; - -describe('MemoryStorageService', () => { - let service: MemoryStorageService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [MemoryStorageService], - }).compile(); - - service = module.get>(MemoryStorageService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/packages/twenty-server/src/integrations/memory-storage/memory-storage.service.ts b/packages/twenty-server/src/integrations/memory-storage/memory-storage.service.ts deleted file mode 100644 index 89fdf0bbd..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/memory-storage.service.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { MemoryStorageDriver } from 'src/integrations/memory-storage/drivers/interfaces/memory-storage-driver.interface'; - -export class MemoryStorageService implements MemoryStorageDriver { - private driver: MemoryStorageDriver; - - constructor(driver: MemoryStorageDriver) { - this.driver = driver; - } - - write(params: { key: string; data: T }): Promise { - return this.driver.write(params); - } - - read(params: { key: string }): Promise { - return this.driver.read(params); - } - - delete(params: { key: string }): Promise { - return this.driver.delete(params); - } -} diff --git a/packages/twenty-server/src/integrations/memory-storage/memory-storage.util.ts b/packages/twenty-server/src/integrations/memory-storage/memory-storage.util.ts deleted file mode 100644 index 6fea200de..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/memory-storage.util.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { MEMORY_STORAGE_SERVICE } from 'src/integrations/memory-storage/memory-storage.constants'; - -export const createMemoryStorageInjectionToken = (identifier: string) => { - return `${MEMORY_STORAGE_SERVICE}_${identifier}`; -}; diff --git a/packages/twenty-server/src/integrations/memory-storage/serializers/default.serializer.ts b/packages/twenty-server/src/integrations/memory-storage/serializers/default.serializer.ts deleted file mode 100644 index 06475f71e..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/serializers/default.serializer.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { MemoryStorageSerializer } from 'src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface'; - -export class MemoryStorageDefaultSerializer - implements MemoryStorageSerializer -{ - serialize(item: T): string { - if (typeof item !== 'string') { - throw new Error('DefaultSerializer can only serialize strings'); - } - - return item; - } - - deserialize(data: string): T { - return data as unknown as T; - } -} diff --git a/packages/twenty-server/src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface.ts b/packages/twenty-server/src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface.ts deleted file mode 100644 index 838de317d..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface MemoryStorageSerializer { - serialize(item: T): string; - deserialize(data: string): T; -} diff --git a/packages/twenty-server/src/integrations/memory-storage/serializers/json.serializer.ts b/packages/twenty-server/src/integrations/memory-storage/serializers/json.serializer.ts deleted file mode 100644 index ef0b3e436..000000000 --- a/packages/twenty-server/src/integrations/memory-storage/serializers/json.serializer.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { MemoryStorageSerializer } from 'src/integrations/memory-storage/serializers/interfaces/memory-storage-serializer.interface'; - -export class MemoryStorageJsonSerializer - implements MemoryStorageSerializer -{ - serialize(item: T): string { - return JSON.stringify(item); - } - - deserialize(data: string): T { - return JSON.parse(data) as T; - } -} diff --git a/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.module.ts b/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.module.ts index dd3f7b6e7..0e13ed973 100644 --- a/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.module.ts +++ b/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.module.ts @@ -1,40 +1,11 @@ import { Module } from '@nestjs/common'; -import { MemoryStorageDriverType } from 'src/integrations/memory-storage/interfaces'; -import { MemoryStorageModule } from 'src/integrations/memory-storage/memory-storage.module'; -import { MemoryStorageJsonSerializer } from 'src/integrations/memory-storage/serializers/json.serializer'; -import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity'; import { ObjectMetadataModule } from 'src/metadata/object-metadata/object-metadata.module'; import { WorkspaceCacheVersionModule } from 'src/metadata/workspace-cache-version/workspace-cache-version.module'; import { WorkspaceSchemaStorageService } from 'src/workspace/workspace-schema-storage/workspace-schema-storage.service'; @Module({ - imports: [ - ObjectMetadataModule, - WorkspaceCacheVersionModule, - MemoryStorageModule.forRoot({ - identifier: 'objectMetadataCollection', - type: MemoryStorageDriverType.Local, - options: {}, - serializer: new MemoryStorageJsonSerializer(), - }), - MemoryStorageModule.forRoot({ - identifier: 'typeDefs', - type: MemoryStorageDriverType.Local, - options: {}, - }), - MemoryStorageModule.forRoot({ - identifier: 'usedScalarNames', - type: MemoryStorageDriverType.Local, - options: {}, - serializer: new MemoryStorageJsonSerializer(), - }), - MemoryStorageModule.forRoot({ - identifier: 'cacheVersion', - type: MemoryStorageDriverType.Local, - options: {}, - }), - ], + imports: [ObjectMetadataModule, WorkspaceCacheVersionModule], providers: [WorkspaceSchemaStorageService], exports: [WorkspaceSchemaStorageService], }) diff --git a/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.service.ts b/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.service.ts index f51478527..449746e1e 100644 --- a/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.service.ts +++ b/packages/twenty-server/src/workspace/workspace-schema-storage/workspace-schema-storage.service.ts @@ -1,33 +1,25 @@ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable } from '@nestjs/common'; -import { InjectMemoryStorage } from 'src/integrations/memory-storage/decorators/inject-memory-storage.decorator'; -import { MemoryStorageService } from 'src/integrations/memory-storage/memory-storage.service'; +import { CacheStorageService } from 'src/integrations/cache-storage/cache-storage.service'; +import { CacheStorageNamespace } from 'src/integrations/cache-storage/types/cache-storage-namespace.enum'; import { ObjectMetadataEntity } from 'src/metadata/object-metadata/object-metadata.entity'; import { WorkspaceCacheVersionService } from 'src/metadata/workspace-cache-version/workspace-cache-version.service'; @Injectable() export class WorkspaceSchemaStorageService { constructor( - @InjectMemoryStorage('objectMetadataCollection') - private readonly objectMetadataMemoryStorageService: MemoryStorageService< - ObjectMetadataEntity[] - >, - @InjectMemoryStorage('typeDefs') - private readonly typeDefsMemoryStorageService: MemoryStorageService, - @InjectMemoryStorage('usedScalarNames') - private readonly usedScalarNamesMemoryStorageService: MemoryStorageService< - string[] - >, - @InjectMemoryStorage('cacheVersion') - private readonly cacheVersionMemoryStorageService: MemoryStorageService, + @Inject(CacheStorageNamespace.WorkspaceSchema) + private readonly workspaceSchemaCache: CacheStorageService, + private readonly workspaceCacheVersionService: WorkspaceCacheVersionService, ) {} async validateCacheVersion(workspaceId: string): Promise { const currentVersion = - (await this.cacheVersionMemoryStorageService.read({ - key: workspaceId, - })) ?? '0'; + (await this.workspaceSchemaCache.get( + `cacheVersion:${workspaceId}`, + )) ?? '0'; + let latestVersion = await this.workspaceCacheVersionService.getVersion(workspaceId); @@ -40,63 +32,63 @@ export class WorkspaceSchemaStorageService { await this.workspaceCacheVersionService.incrementVersion(workspaceId); // Update the cache version after invalidation - await this.cacheVersionMemoryStorageService.write({ - key: workspaceId, - data: latestVersion, - }); + await this.workspaceSchemaCache.set( + `cacheVersion:${workspaceId}`, + latestVersion, + ); } } - setObjectMetadata( + setObjectMetadataCollection( workspaceId: string, - objectMetadata: ObjectMetadataEntity[], + objectMetadataCollection: ObjectMetadataEntity[], ) { - return this.objectMetadataMemoryStorageService.write({ - key: workspaceId, - data: objectMetadata, - }); + return this.workspaceSchemaCache.set( + `objectMetadataCollection:${workspaceId}`, + objectMetadataCollection, + ); } - getObjectMetadata( + getObjectMetadataCollection( workspaceId: string, - ): Promise { - return this.objectMetadataMemoryStorageService.read({ - key: workspaceId, - }); + ): Promise { + return this.workspaceSchemaCache.get( + `objectMetadataCollection:${workspaceId}`, + ); } setTypeDefs(workspaceId: string, typeDefs: string): Promise { - return this.typeDefsMemoryStorageService.write({ - key: workspaceId, - data: typeDefs, - }); + return this.workspaceSchemaCache.set( + `typeDefs:${workspaceId}`, + typeDefs, + ); } - getTypeDefs(workspaceId: string): Promise { - return this.typeDefsMemoryStorageService.read({ - key: workspaceId, - }); + getTypeDefs(workspaceId: string): Promise { + return this.workspaceSchemaCache.get(`typeDefs:${workspaceId}`); } setUsedScalarNames( workspaceId: string, scalarsUsed: string[], ): Promise { - return this.usedScalarNamesMemoryStorageService.write({ - key: workspaceId, - data: scalarsUsed, - }); + return this.workspaceSchemaCache.set( + `usedScalarNames:${workspaceId}`, + scalarsUsed, + ); } - getUsedScalarNames(workspaceId: string): Promise { - return this.usedScalarNamesMemoryStorageService.read({ - key: workspaceId, - }); + getUsedScalarNames(workspaceId: string): Promise { + return this.workspaceSchemaCache.get( + `usedScalarNames:${workspaceId}`, + ); } async invalidateCache(workspaceId: string): Promise { - await this.objectMetadataMemoryStorageService.delete({ key: workspaceId }); - await this.typeDefsMemoryStorageService.delete({ key: workspaceId }); - await this.usedScalarNamesMemoryStorageService.delete({ key: workspaceId }); + await this.workspaceSchemaCache.del( + `objectMetadataCollection:${workspaceId}`, + ); + await this.workspaceSchemaCache.del(`typeDefs:${workspaceId}`); + await this.workspaceSchemaCache.del(`usedScalarNames:${workspaceId}`); } } diff --git a/packages/twenty-server/src/workspace/workspace.factory.ts b/packages/twenty-server/src/workspace/workspace.factory.ts index bbc4b758d..ac9d7c710 100644 --- a/packages/twenty-server/src/workspace/workspace.factory.ts +++ b/packages/twenty-server/src/workspace/workspace.factory.ts @@ -47,14 +47,16 @@ export class WorkspaceFactory { // Get object metadata from cache let objectMetadataCollection = - await this.workspaceSchemaStorageService.getObjectMetadata(workspaceId); + await this.workspaceSchemaStorageService.getObjectMetadataCollection( + workspaceId, + ); // If object metadata is not cached, get it from the database if (!objectMetadataCollection) { objectMetadataCollection = await this.objectMetadataService.findManyWithinWorkspace(workspaceId); - await this.workspaceSchemaStorageService.setObjectMetadata( + await this.workspaceSchemaStorageService.setObjectMetadataCollection( workspaceId, objectMetadataCollection, );