Improve performance twenty orm (#6691)
## Context As we grow, the messaging scripts are experiencing performance issues forcing us to temporarily disable them on the cloud. While investigating the performance, I have noticed that generating the entity schema (for twentyORM) in the repository is taking ~500ms locally on my Mac M2 so likely more on pods. Caching the entitySchema then! I'm also clarifying naming around schemaVersion and cacheVersions ==> both are renamed workspaceMetadataVersion and migrated to the workspace table (the workspaceCacheVersion table is dropped).
This commit is contained in:
@ -1,11 +1,12 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
||||
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
|
||||
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
||||
import { WorkspaceSchemaFactory } from 'src/engine/api/graphql/workspace-schema.factory';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
describe('WorkspaceSchemaFactory', () => {
|
||||
@ -39,6 +40,10 @@ describe('WorkspaceSchemaFactory', () => {
|
||||
provide: WorkspaceCacheStorageService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: WorkspaceMetadataVersionService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
||||
import { WorkspaceSchemaBuilderModule } from 'src/engine/api/graphql/workspace-schema-builder/workspace-schema-builder.module';
|
||||
import { WorkspaceResolverBuilderModule } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver-builder.module';
|
||||
import { WorkspaceSchemaBuilderModule } from 'src/engine/api/graphql/workspace-schema-builder/workspace-schema-builder.module';
|
||||
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
|
||||
import { WorkspaceSchemaFactory } from './workspace-schema.factory';
|
||||
|
||||
@ -21,6 +22,7 @@ import { WorkspaceSchemaFactory } from './workspace-schema.factory';
|
||||
WorkspaceSchemaBuilderModule,
|
||||
WorkspaceResolverBuilderModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
providers: [WorkspaceSchemaFactory, ScalarsExplorerService],
|
||||
exports: [WorkspaceSchemaFactory],
|
||||
|
||||
@ -9,10 +9,11 @@ export type CacheMetadataPluginConfig = {
|
||||
export function useCachedMetadata(config: CacheMetadataPluginConfig): Plugin {
|
||||
const computeCacheKey = (serverContext: any) => {
|
||||
const workspaceId = serverContext.req.workspace?.id ?? 'anonymous';
|
||||
const cacheVersion = serverContext.req.cacheVersion ?? '0';
|
||||
const workspaceMetadataVersion =
|
||||
serverContext.req.workspaceMetadataVersion ?? '0';
|
||||
const operationName = getOperationName(serverContext);
|
||||
|
||||
return `cachedOperations:${operationName}:${workspaceId}:${cacheVersion}`;
|
||||
return `graphql:operations:${operationName}:${workspaceId}:${workspaceMetadataVersion}`;
|
||||
};
|
||||
|
||||
const getOperationName = (serverContext: any) =>
|
||||
|
||||
@ -1,19 +1,18 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { GraphQLModule } from '@nestjs/graphql';
|
||||
|
||||
import { YogaDriverConfig, YogaDriver } from '@graphql-yoga/nestjs';
|
||||
import { YogaDriver, YogaDriverConfig } from '@graphql-yoga/nestjs';
|
||||
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
||||
import { GraphQLConfigModule } from 'src/engine/api/graphql/graphql-config/graphql-config.module';
|
||||
import { metadataModuleFactory } from 'src/engine/api/graphql/metadata.module-factory';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
||||
import { DataloaderModule } from 'src/engine/dataloaders/dataloader.module';
|
||||
import { DataloaderService } from 'src/engine/dataloaders/dataloader.service';
|
||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { CacheStorageModule } from 'src/engine/integrations/cache-storage/cache-storage.module';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
||||
import { MetadataEngineModule } from 'src/engine/metadata-modules/metadata-engine.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -25,13 +24,12 @@ import { CacheStorageModule } from 'src/engine/integrations/cache-storage/cache-
|
||||
EnvironmentService,
|
||||
ExceptionHandlerService,
|
||||
DataloaderService,
|
||||
CacheStorageNamespace.WorkspaceSchema,
|
||||
CacheStorageNamespace.EngineWorkspace,
|
||||
],
|
||||
}),
|
||||
MetadataEngineModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMigrationModule,
|
||||
CacheStorageModule,
|
||||
],
|
||||
})
|
||||
export class MetadataGraphQLApiModule {}
|
||||
|
||||
@ -15,7 +15,7 @@ export const metadataModuleFactory = async (
|
||||
environmentService: EnvironmentService,
|
||||
exceptionHandlerService: ExceptionHandlerService,
|
||||
dataloaderService: DataloaderService,
|
||||
workspaceSchemaCacheStorage: CacheStorageService,
|
||||
cacheStorageService: CacheStorageService,
|
||||
): Promise<YogaDriverConfig> => {
|
||||
const config: YogaDriverConfig = {
|
||||
autoSchemaFile: true,
|
||||
@ -36,12 +36,8 @@ export const metadataModuleFactory = async (
|
||||
exceptionHandlerService,
|
||||
}),
|
||||
useCachedMetadata({
|
||||
cacheGetter: workspaceSchemaCacheStorage.get.bind(
|
||||
workspaceSchemaCacheStorage,
|
||||
),
|
||||
cacheSetter: workspaceSchemaCacheStorage.set.bind(
|
||||
workspaceSchemaCacheStorage,
|
||||
),
|
||||
cacheGetter: cacheStorageService.get.bind(cacheStorageService),
|
||||
cacheSetter: cacheStorageService.set.bind(cacheStorageService),
|
||||
operationsToCache: ['ObjectMetadataItems'],
|
||||
}),
|
||||
],
|
||||
|
||||
@ -1,17 +1,18 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { GraphQLSchema, printSchema } from 'graphql';
|
||||
import { makeExecutableSchema } from '@graphql-tools/schema';
|
||||
import { GraphQLSchema, printSchema } from 'graphql';
|
||||
import { gql } from 'graphql-tag';
|
||||
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { ScalarsExplorerService } from 'src/engine/api/graphql/services/scalars-explorer.service';
|
||||
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
||||
import { workspaceResolverBuilderMethodNames } from 'src/engine/api/graphql/workspace-resolver-builder/factories/factories';
|
||||
import { WorkspaceResolverFactory } from 'src/engine/api/graphql/workspace-resolver-builder/workspace-resolver.factory';
|
||||
import { WorkspaceGraphQLSchemaFactory } from 'src/engine/api/graphql/workspace-schema-builder/workspace-graphql-schema.factory';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceSchemaFactory {
|
||||
@ -22,6 +23,7 @@ export class WorkspaceSchemaFactory {
|
||||
private readonly workspaceGraphQLSchemaFactory: WorkspaceGraphQLSchemaFactory,
|
||||
private readonly workspaceResolverFactory: WorkspaceResolverFactory,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {}
|
||||
|
||||
async createGraphQLSchema(authContext: AuthContext): Promise<GraphQLSchema> {
|
||||
@ -40,7 +42,7 @@ export class WorkspaceSchemaFactory {
|
||||
}
|
||||
|
||||
// Validate cache version
|
||||
await this.workspaceCacheStorageService.validateCacheVersion(
|
||||
await this.workspaceMetadataVersionService.flushCacheIfMetadataVersionIsOutdated(
|
||||
authContext.workspace.id,
|
||||
);
|
||||
|
||||
@ -64,11 +66,11 @@ export class WorkspaceSchemaFactory {
|
||||
}
|
||||
|
||||
// Get typeDefs from cache
|
||||
let typeDefs = await this.workspaceCacheStorageService.getTypeDefs(
|
||||
let typeDefs = await this.workspaceCacheStorageService.getGraphQLTypeDefs(
|
||||
authContext.workspace.id,
|
||||
);
|
||||
let usedScalarNames =
|
||||
await this.workspaceCacheStorageService.getUsedScalarNames(
|
||||
await this.workspaceCacheStorageService.getGraphQLUsedScalarNames(
|
||||
authContext.workspace.id,
|
||||
);
|
||||
|
||||
@ -84,11 +86,11 @@ export class WorkspaceSchemaFactory {
|
||||
this.scalarsExplorerService.getUsedScalarNames(autoGeneratedSchema);
|
||||
typeDefs = printSchema(autoGeneratedSchema);
|
||||
|
||||
await this.workspaceCacheStorageService.setTypeDefs(
|
||||
await this.workspaceCacheStorageService.setGraphQLTypeDefs(
|
||||
authContext.workspace.id,
|
||||
typeDefs,
|
||||
);
|
||||
await this.workspaceCacheStorageService.setUsedScalarNames(
|
||||
await this.workspaceCacheStorageService.setGraphQLUsedScalarNames(
|
||||
authContext.workspace.id,
|
||||
usedScalarNames,
|
||||
);
|
||||
|
||||
@ -21,7 +21,6 @@ import { TokenService } from 'src/engine/core-modules/auth/services/token.servic
|
||||
import { GoogleAPIsRequest } from 'src/engine/core-modules/auth/types/google-api-request.type';
|
||||
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
||||
|
||||
@Controller('auth/google-apis')
|
||||
@UseFilters(AuthRestApiExceptionFilter)
|
||||
@ -31,7 +30,6 @@ export class GoogleAPIsAuthController {
|
||||
private readonly tokenService: TokenService,
|
||||
private readonly environmentService: EnvironmentService,
|
||||
private readonly onboardingService: OnboardingService,
|
||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
||||
) {}
|
||||
|
||||
@Get()
|
||||
@ -80,13 +78,7 @@ export class GoogleAPIsAuthController {
|
||||
|
||||
const handle = emails[0].value;
|
||||
|
||||
const googleAPIsServiceInstance =
|
||||
await this.loadServiceWithWorkspaceContext.load(
|
||||
this.googleAPIsService,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await googleAPIsServiceInstance.refreshGoogleRefreshToken({
|
||||
await this.googleAPIsService.refreshGoogleRefreshToken({
|
||||
handle,
|
||||
workspaceMemberId: workspaceMemberId,
|
||||
workspaceId: workspaceId,
|
||||
@ -97,13 +89,7 @@ export class GoogleAPIsAuthController {
|
||||
});
|
||||
|
||||
if (userId) {
|
||||
const onboardingServiceInstance =
|
||||
await this.loadServiceWithWorkspaceContext.load(
|
||||
this.onboardingService,
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await onboardingServiceInstance.setOnboardingConnectAccountPending({
|
||||
await this.onboardingService.setOnboardingConnectAccountPending({
|
||||
userId,
|
||||
workspaceId,
|
||||
value: false,
|
||||
|
||||
@ -8,7 +8,7 @@ import { InjectMessageQueue } from 'src/engine/integrations/message-queue/decora
|
||||
import { MessageQueue } from 'src/engine/integrations/message-queue/message-queue.constants';
|
||||
import { MessageQueueService } from 'src/engine/integrations/message-queue/services/message-queue.service';
|
||||
import { InjectObjectMetadataRepository } from 'src/engine/object-metadata-repository/object-metadata-repository.decorator';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import {
|
||||
CalendarEventListFetchJob,
|
||||
CalendarEventsImportJobData,
|
||||
@ -39,7 +39,7 @@ import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/sta
|
||||
@Injectable()
|
||||
export class GoogleAPIsService {
|
||||
constructor(
|
||||
private readonly twentyORMManager: TwentyORMManager,
|
||||
private readonly twentyORMGlobalManager: TwentyORMGlobalManager,
|
||||
@InjectMessageQueue(MessageQueue.messagingQueue)
|
||||
private readonly messageQueueService: MessageQueueService,
|
||||
@InjectMessageQueue(MessageQueue.calendarQueue)
|
||||
@ -82,16 +82,19 @@ export class GoogleAPIsService {
|
||||
const newOrExistingConnectedAccountId = existingAccountId ?? v4();
|
||||
|
||||
const calendarChannelRepository =
|
||||
await this.twentyORMManager.getRepository<CalendarChannelWorkspaceEntity>(
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<CalendarChannelWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'calendarChannel',
|
||||
);
|
||||
|
||||
const messageChannelRepository =
|
||||
await this.twentyORMManager.getRepository<MessageChannelWorkspaceEntity>(
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<MessageChannelWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'messageChannel',
|
||||
);
|
||||
|
||||
const workspaceDataSource = await this.twentyORMManager.getDatasource();
|
||||
const workspaceDataSource =
|
||||
await this.twentyORMGlobalManager.getDataSourceForWorkspace(workspaceId);
|
||||
|
||||
await workspaceDataSource.transaction(async (manager: EntityManager) => {
|
||||
if (!existingAccountId) {
|
||||
@ -146,7 +149,8 @@ export class GoogleAPIsService {
|
||||
);
|
||||
|
||||
const workspaceMemberRepository =
|
||||
await this.twentyORMManager.getRepository<WorkspaceMemberWorkspaceEntity>(
|
||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||
workspaceId,
|
||||
'workspaceMember',
|
||||
);
|
||||
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { PassportStrategy } from '@nestjs/passport';
|
||||
|
||||
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
|
||||
import { Request } from 'express';
|
||||
import { Strategy, VerifyCallback } from 'passport-google-oauth20';
|
||||
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
|
||||
export type GoogleRequest = Omit<
|
||||
Request,
|
||||
'user' | 'workspace' | 'cacheVersion'
|
||||
'user' | 'workspace' | 'workspaceMetadataVersion'
|
||||
> & {
|
||||
user: {
|
||||
firstName?: string | null;
|
||||
|
||||
@ -12,7 +12,7 @@ import { EnvironmentService } from 'src/engine/integrations/environment/environm
|
||||
|
||||
export type MicrosoftRequest = Omit<
|
||||
Request,
|
||||
'user' | 'workspace' | 'cacheVersion'
|
||||
'user' | 'workspace' | 'workspaceMetadataVersion'
|
||||
> & {
|
||||
user: {
|
||||
firstName?: string | null;
|
||||
|
||||
@ -5,7 +5,7 @@ import { MessageChannelVisibility } from 'src/modules/messaging/common/standard-
|
||||
|
||||
export type GoogleAPIsRequest = Omit<
|
||||
Request,
|
||||
'user' | 'workspace' | 'cacheVersion'
|
||||
'user' | 'workspace' | 'workspaceMetadataVersion'
|
||||
> & {
|
||||
user: {
|
||||
firstName?: string | null;
|
||||
|
||||
@ -44,6 +44,10 @@ export class FileController {
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
fileStream.on('error', () => {
|
||||
res.status(500).send({ error: 'Internal server error' });
|
||||
});
|
||||
|
||||
fileStream.pipe(res);
|
||||
} catch (error) {
|
||||
if (
|
||||
|
||||
@ -119,13 +119,13 @@ export const useGraphQLErrorHandlerHook = <
|
||||
|
||||
if (Array.isArray(errors) && errors.length > 0) {
|
||||
const headers = context.req.headers;
|
||||
const currentSchemaVersion = context.req.cacheVersion;
|
||||
const currentMetadataVersion = context.req.workspaceMetadataVersion;
|
||||
|
||||
const requestSchemaVersion = headers['x-schema-version'];
|
||||
const requestMetadataVersion = headers['x-schema-version'];
|
||||
|
||||
if (
|
||||
requestSchemaVersion &&
|
||||
requestSchemaVersion !== currentSchemaVersion
|
||||
requestMetadataVersion &&
|
||||
requestMetadataVersion !== `${currentMetadataVersion}`
|
||||
) {
|
||||
throw new GraphQLError(
|
||||
`Schema version mismatch, please refresh the page.`,
|
||||
|
||||
@ -33,7 +33,6 @@ import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorat
|
||||
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
||||
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||
|
||||
const getHMACKey = (email?: string, key?: string | null) => {
|
||||
@ -54,7 +53,6 @@ export class UserResolver {
|
||||
private readonly environmentService: EnvironmentService,
|
||||
private readonly fileUploadService: FileUploadService,
|
||||
private readonly onboardingService: OnboardingService,
|
||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
||||
private readonly userVarService: UserVarsService,
|
||||
private readonly fileService: FileService,
|
||||
) {}
|
||||
@ -189,11 +187,6 @@ export class UserResolver {
|
||||
|
||||
@ResolveField(() => OnboardingStatus)
|
||||
async onboardingStatus(@Parent() user: User): Promise<OnboardingStatus> {
|
||||
const contextInstance = await this.loadServiceWithWorkspaceContext.load(
|
||||
this.onboardingService,
|
||||
user.defaultWorkspaceId,
|
||||
);
|
||||
|
||||
return contextInstance.getOnboardingStatus(user);
|
||||
return this.onboardingService.getOnboardingStatus(user);
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,4 +117,16 @@ export class Workspace {
|
||||
(postgresCredentials) => postgresCredentials.workspace,
|
||||
)
|
||||
allPostgresCredentials: Relation<PostgresCredentials[]>;
|
||||
|
||||
@Field()
|
||||
@Column({ default: 1 })
|
||||
metadataVersion: number;
|
||||
|
||||
@Field()
|
||||
@Column({ default: '' })
|
||||
databaseUrl: string;
|
||||
|
||||
@Field()
|
||||
@Column({ default: '' })
|
||||
databaseSchema: string;
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@ import { User } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceWorkspaceMemberListener } from 'src/engine/core-modules/workspace/workspace-workspace-member.listener';
|
||||
import { WorkspaceResolver } from 'src/engine/core-modules/workspace/workspace.resolver';
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceManagerModule } from 'src/engine/workspace-manager/workspace-manager.module';
|
||||
|
||||
import { workspaceAutoResolverOpts } from './workspace.auto-resolver-opts';
|
||||
@ -32,7 +32,7 @@ import { WorkspaceService } from './services/workspace.service';
|
||||
BillingModule,
|
||||
FileModule,
|
||||
FileUploadModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
NestjsQueryTypeOrmModule.forFeature(
|
||||
[User, Workspace, UserWorkspace, FeatureFlagEntity],
|
||||
'core',
|
||||
|
||||
@ -26,7 +26,7 @@ import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { DemoEnvGuard } from 'src/engine/guards/demo.env.guard';
|
||||
import { JwtAuthGuard } from 'src/engine/guards/jwt.auth.guard';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { assert } from 'src/utils/assert';
|
||||
import { streamToBuffer } from 'src/utils/stream-to-buffer';
|
||||
|
||||
@ -39,7 +39,7 @@ import { WorkspaceService } from './services/workspace.service';
|
||||
export class WorkspaceResolver {
|
||||
constructor(
|
||||
private readonly workspaceService: WorkspaceService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
private readonly userWorkspaceService: UserWorkspaceService,
|
||||
private readonly fileUploadService: FileUploadService,
|
||||
private readonly fileService: FileService,
|
||||
@ -107,13 +107,6 @@ export class WorkspaceResolver {
|
||||
return this.workspaceService.deleteWorkspace(id);
|
||||
}
|
||||
|
||||
@ResolveField(() => String, { nullable: true })
|
||||
async currentCacheVersion(
|
||||
@Parent() workspace: Workspace,
|
||||
): Promise<string | null> {
|
||||
return this.workspaceCacheVersionService.getVersion(workspace.id);
|
||||
}
|
||||
|
||||
@ResolveField(() => BillingSubscription, { nullable: true })
|
||||
async currentBillingSubscription(
|
||||
@Parent() workspace: Workspace,
|
||||
@ -133,11 +126,15 @@ export class WorkspaceResolver {
|
||||
@ResolveField(() => String)
|
||||
async logo(@Parent() workspace: Workspace): Promise<string> {
|
||||
if (workspace.logo) {
|
||||
const workspaceLogoToken = await this.fileService.encodeFileToken({
|
||||
workspace_id: workspace.id,
|
||||
});
|
||||
try {
|
||||
const workspaceLogoToken = await this.fileService.encodeFileToken({
|
||||
workspace_id: workspace.id,
|
||||
});
|
||||
|
||||
return `${workspace.logo}?token=${workspaceLogoToken}`;
|
||||
return `${workspace.logo}?token=${workspaceLogoToken}`;
|
||||
} catch (e) {
|
||||
return workspace.logo;
|
||||
}
|
||||
}
|
||||
|
||||
return workspace.logo ?? '';
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export enum CacheStorageNamespace {
|
||||
Messaging = 'messaging',
|
||||
Calendar = 'calendar',
|
||||
WorkspaceSchema = 'workspaceSchema',
|
||||
ModuleMessaging = 'module:messaging',
|
||||
ModuleCalendar = 'module:calendar',
|
||||
EngineWorkspace = 'engine:workspace',
|
||||
}
|
||||
|
||||
@ -13,15 +13,15 @@ import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-s
|
||||
import { FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
import { FieldMetadataResolver } from 'src/engine/metadata-modules/field-metadata/field-metadata.resolver';
|
||||
import { FieldMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/field-metadata/interceptors/field-metadata-graphql-api-exception.interceptor';
|
||||
import { CreatedByPreQueryHook } from 'src/engine/metadata-modules/field-metadata/query-hooks/created-by.pre-query-hook';
|
||||
import { IsFieldMetadataDefaultValue } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-default-value.validator';
|
||||
import { IsFieldMetadataOptions } from 'src/engine/metadata-modules/field-metadata/validators/is-field-metadata-options.validator';
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { TwentyORMModule } from 'src/engine/twenty-orm/twenty-orm.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
import { WorkspaceStatusModule } from 'src/engine/workspace-manager/workspace-status/workspace-manager.module';
|
||||
import { CreatedByPreQueryHook } from 'src/engine/metadata-modules/field-metadata/query-hooks/created-by.pre-query-hook';
|
||||
|
||||
import { FieldMetadataEntity } from './field-metadata.entity';
|
||||
import { FieldMetadataService } from './field-metadata.service';
|
||||
@ -38,7 +38,7 @@ import { UpdateFieldInput } from './dtos/update-field.input';
|
||||
WorkspaceStatusModule,
|
||||
TwentyORMModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
ObjectMetadataModule,
|
||||
DataSourceModule,
|
||||
TypeORMModule,
|
||||
|
||||
@ -40,7 +40,7 @@ import {
|
||||
NameTooLongException,
|
||||
validateMetadataNameOrThrow,
|
||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
@ -76,7 +76,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly typeORMService: TypeORMService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(fieldMetadataRepository);
|
||||
}
|
||||
@ -274,7 +274,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
await this.workspaceCacheVersionService.incrementVersion(
|
||||
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||
fieldMetadataInput.workspaceId,
|
||||
);
|
||||
}
|
||||
@ -426,7 +426,7 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
await this.workspaceCacheVersionService.incrementVersion(
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
fieldMetadataInput.workspaceId,
|
||||
);
|
||||
}
|
||||
@ -545,7 +545,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
throw error;
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -586,7 +588,9 @@ export class FieldMetadataService extends TypeOrmQueryService<FieldMetadataEntit
|
||||
|
||||
public async deleteFieldsMetadata(workspaceId: string) {
|
||||
await this.fieldMetadataRepository.delete({ workspaceId });
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
private buildUpdatableStandardFieldInput(
|
||||
|
||||
@ -5,9 +5,9 @@ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { RelationMetadataModule } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.module';
|
||||
import { RemoteServerModule } from 'src/engine/metadata-modules/remote-server/remote-server.module';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless-function/serverless-function.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@ -16,7 +16,7 @@ import { ServerlessFunctionModule } from 'src/engine/metadata-modules/serverless
|
||||
ObjectMetadataModule,
|
||||
RelationMetadataModule,
|
||||
ServerlessFunctionModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
WorkspaceMigrationModule,
|
||||
RemoteServerModule,
|
||||
],
|
||||
|
||||
@ -19,7 +19,7 @@ import { ObjectMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadat
|
||||
import { ObjectMetadataResolver } from 'src/engine/metadata-modules/object-metadata/object-metadata.resolver';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { RemoteTableRelationsModule } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.module';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@ -43,7 +43,7 @@ import { UpdateObjectPayload } from './dtos/update-object.input';
|
||||
DataSourceModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
FeatureFlagModule,
|
||||
RemoteTableRelationsModule,
|
||||
],
|
||||
|
||||
@ -32,7 +32,7 @@ import {
|
||||
import { RelationToDelete } from 'src/engine/metadata-modules/relation-metadata/types/relation-to-delete';
|
||||
import { RemoteTableRelationsService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-relations/remote-table-relations.service';
|
||||
import { mapUdtNameToFieldType } from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
@ -80,7 +80,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
private readonly typeORMService: TypeORMService,
|
||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(objectMetadataRepository);
|
||||
}
|
||||
@ -144,7 +144,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
return objectMetadata;
|
||||
}
|
||||
@ -352,7 +354,7 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
);
|
||||
});
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
objectMetadataInput.workspaceId,
|
||||
);
|
||||
|
||||
@ -367,7 +369,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
|
||||
const updatedObject = await super.updateOne(input.id, input.update);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
return updatedObject;
|
||||
}
|
||||
@ -452,7 +456,9 @@ export class ObjectMetadataService extends TypeOrmQueryService<ObjectMetadataEnt
|
||||
|
||||
public async deleteObjectsMetadata(workspaceId: string) {
|
||||
await this.objectMetadataRepository.delete({ workspaceId });
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
private async createObjectRelationsMetadataAndMigrations(
|
||||
|
||||
@ -12,7 +12,7 @@ import { FieldMetadataModule } from 'src/engine/metadata-modules/field-metadata/
|
||||
import { ObjectMetadataModule } from 'src/engine/metadata-modules/object-metadata/object-metadata.module';
|
||||
import { RelationMetadataGraphqlApiExceptionInterceptor } from 'src/engine/metadata-modules/relation-metadata/interceptors/relation-metadata-graphql-api-exception.interceptor';
|
||||
import { RelationMetadataResolver } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.resolver';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
|
||||
@ -34,7 +34,7 @@ import { RelationMetadataDTO } from './dtos/relation-metadata.dto';
|
||||
FieldMetadataModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
services: [RelationMetadataService],
|
||||
resolvers: [
|
||||
|
||||
@ -22,7 +22,7 @@ import {
|
||||
InvalidStringException,
|
||||
validateMetadataNameOrThrow,
|
||||
} from 'src/engine/metadata-modules/utils/validate-metadata-name.utils';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnActionType,
|
||||
@ -50,7 +50,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
private readonly fieldMetadataService: FieldMetadataService,
|
||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {
|
||||
super(relationMetadataRepository);
|
||||
}
|
||||
@ -120,7 +120,7 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
relationMetadataInput.workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
relationMetadataInput.workspaceId,
|
||||
);
|
||||
|
||||
@ -394,7 +394,9 @@ export class RelationMetadataService extends TypeOrmQueryService<RelationMetadat
|
||||
relationMetadata.workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
// TODO: Return id for delete endpoints
|
||||
return relationMetadata;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
@ -11,7 +11,7 @@ import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/wor
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceMigrationRunnerModule,
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
providers: [ForeignTableService],
|
||||
exports: [ForeignTableService],
|
||||
|
||||
@ -11,7 +11,7 @@ import {
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.exception';
|
||||
import { getForeignTableColumnName } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/utils/get-foreign-table-column-name.util';
|
||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { generateMigrationName } from 'src/engine/metadata-modules/workspace-migration/utils/generate-migration-name.util';
|
||||
import {
|
||||
ReferencedTable,
|
||||
@ -30,7 +30,7 @@ export class ForeignTableService {
|
||||
private readonly workspaceMigrationService: WorkspaceMigrationService,
|
||||
private readonly workspaceMigrationRunnerService: WorkspaceMigrationRunnerService,
|
||||
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {}
|
||||
|
||||
public async fetchForeignTableNamesWithinWorkspace(
|
||||
@ -127,7 +127,9 @@ export class ForeignTableService {
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
return {
|
||||
name: foreignTableName,
|
||||
|
||||
@ -11,7 +11,7 @@ import { RemoteTableSchemaUpdateModule } from 'src/engine/metadata-modules/remot
|
||||
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
||||
import { RemoteTableResolver } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.resolver';
|
||||
import { RemoteTableService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.service';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
|
||||
@Module({
|
||||
@ -24,7 +24,7 @@ import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/works
|
||||
DataSourceModule,
|
||||
ObjectMetadataModule,
|
||||
FieldMetadataModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
WorkspaceDataSourceModule,
|
||||
ForeignTableModule,
|
||||
RemoteTableSchemaUpdateModule,
|
||||
|
||||
@ -1,49 +1,49 @@
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
import { plural } from 'pluralize';
|
||||
import isEmpty from 'lodash.isempty';
|
||||
import { plural } from 'pluralize';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import {
|
||||
RemoteServerType,
|
||||
RemoteServerEntity,
|
||||
RemoteServerType,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-server.entity';
|
||||
import { DistantTableService } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service';
|
||||
import { sortDistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/sort-distant-tables.util';
|
||||
import { RemoteTableInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table-input';
|
||||
import {
|
||||
DistantTableUpdate,
|
||||
RemoteTableStatus,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table.dto';
|
||||
import {
|
||||
mapUdtNameToFieldSettings,
|
||||
mapUdtNameToFieldType,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
||||
import { RemoteTableInput } from 'src/engine/metadata-modules/remote-server/remote-table/dtos/remote-table-input';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { ObjectMetadataService } from 'src/engine/metadata-modules/object-metadata/object-metadata.service';
|
||||
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
import { FieldMetadataService } from 'src/engine/metadata-modules/field-metadata/field-metadata.service';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
import { camelToTitleCase } from 'src/utils/camel-to-title-case';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
||||
import { getRemoteTableLocalName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-remote-table-local-name.util';
|
||||
import { DistantTableService } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/distant-table.service';
|
||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||
import { fetchTableColumns } from 'src/engine/metadata-modules/remote-server/remote-table/utils/fetch-table-columns.util';
|
||||
import { ForeignTableService } from 'src/engine/metadata-modules/remote-server/remote-table/foreign-table/foreign-table.service';
|
||||
import { RemoteTableSchemaUpdateService } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table-schema-update/remote-table-schema-update.service';
|
||||
import { sortDistantTables } from 'src/engine/metadata-modules/remote-server/remote-table/distant-table/utils/sort-distant-tables.util';
|
||||
import {
|
||||
WorkspaceMigrationColumnAction,
|
||||
WorkspaceMigrationColumnActionType,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { RemoteTableEntity } from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.entity';
|
||||
import {
|
||||
RemoteTableException,
|
||||
RemoteTableExceptionCode,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/remote-table.exception';
|
||||
import { fetchTableColumns } from 'src/engine/metadata-modules/remote-server/remote-table/utils/fetch-table-columns.util';
|
||||
import { getRemoteTableLocalName } from 'src/engine/metadata-modules/remote-server/remote-table/utils/get-remote-table-local-name.util';
|
||||
import {
|
||||
mapUdtNameToFieldSettings,
|
||||
mapUdtNameToFieldType,
|
||||
} from 'src/engine/metadata-modules/remote-server/remote-table/utils/udt-name-mapper.util';
|
||||
import { PostgresTableSchemaColumn } from 'src/engine/metadata-modules/remote-server/types/postgres-table-schema-column';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import {
|
||||
WorkspaceMigrationColumnAction,
|
||||
WorkspaceMigrationColumnActionType,
|
||||
} from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceDataSourceService } from 'src/engine/workspace-datasource/workspace-datasource.service';
|
||||
import { camelCase } from 'src/utils/camel-case';
|
||||
import { camelToTitleCase } from 'src/utils/camel-to-title-case';
|
||||
|
||||
export class RemoteTableService {
|
||||
private readonly logger = new Logger(RemoteTableService.name);
|
||||
@ -55,7 +55,7 @@ export class RemoteTableService {
|
||||
private readonly remoteServerRepository: Repository<
|
||||
RemoteServerEntity<RemoteServerType>
|
||||
>,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly objectMetadataService: ObjectMetadataService,
|
||||
private readonly fieldMetadataService: FieldMetadataService,
|
||||
@ -250,7 +250,9 @@ export class RemoteTableService {
|
||||
|
||||
await this.remoteTableRepository.save(remoteTableEntity);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
return {
|
||||
id: remoteTableEntity.id,
|
||||
@ -435,7 +437,9 @@ export class RemoteTableService {
|
||||
|
||||
await this.remoteTableRepository.delete(remoteTable.id);
|
||||
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
private async createRemoteTableMetadata(
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
import {
|
||||
Column,
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
||||
@Entity('workspaceCacheVersion')
|
||||
export class WorkspaceCacheVersionEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column({ unique: true, nullable: false, type: 'uuid' })
|
||||
workspaceId: string;
|
||||
|
||||
@Column()
|
||||
version: string;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
@UpdateDateColumn({ type: 'timestamptz' })
|
||||
updatedAt: Date;
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { WorkspaceCacheVersionEntity } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.entity';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([WorkspaceCacheVersionEntity], 'metadata'),
|
||||
],
|
||||
exports: [WorkspaceCacheVersionService],
|
||||
providers: [WorkspaceCacheVersionService],
|
||||
})
|
||||
export class WorkspaceCacheVersionModule {}
|
||||
@ -1,42 +0,0 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceCacheVersionEntity } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.entity';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceCacheVersionService {
|
||||
constructor(
|
||||
@InjectRepository(WorkspaceCacheVersionEntity, 'metadata')
|
||||
private readonly workspaceCacheVersionRepository: Repository<WorkspaceCacheVersionEntity>,
|
||||
) {}
|
||||
|
||||
async incrementVersion(workspaceId: string): Promise<string> {
|
||||
const workspaceCacheVersion = (await this.getVersion(workspaceId)) ?? '0';
|
||||
const newVersion = `${+workspaceCacheVersion + 1}`;
|
||||
|
||||
await this.workspaceCacheVersionRepository.upsert(
|
||||
{
|
||||
workspaceId,
|
||||
version: `${+workspaceCacheVersion + 1}`,
|
||||
},
|
||||
['workspaceId'],
|
||||
);
|
||||
|
||||
return newVersion;
|
||||
}
|
||||
|
||||
async getVersion(workspaceId: string): Promise<string | null> {
|
||||
const workspaceCacheVersion =
|
||||
await this.workspaceCacheVersionRepository.findOne({
|
||||
where: { workspaceId },
|
||||
});
|
||||
|
||||
return workspaceCacheVersion?.version ?? null;
|
||||
}
|
||||
|
||||
async deleteVersion(workspaceId: string): Promise<void> {
|
||||
await this.workspaceCacheVersionRepository.delete({ workspaceId });
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Workspace], 'core'),
|
||||
WorkspaceCacheStorageModule,
|
||||
],
|
||||
exports: [WorkspaceMetadataVersionService],
|
||||
providers: [WorkspaceMetadataVersionService],
|
||||
})
|
||||
export class WorkspaceMetadataVersionModule {}
|
||||
@ -0,0 +1,79 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceMetadataVersionService {
|
||||
logger = new Logger(WorkspaceMetadataVersionService.name);
|
||||
|
||||
constructor(
|
||||
@InjectRepository(Workspace, 'core')
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
) {}
|
||||
|
||||
async flushCacheIfMetadataVersionIsOutdated(
|
||||
workspaceId: string,
|
||||
): Promise<void> {
|
||||
const currentVersion =
|
||||
(await this.workspaceCacheStorageService.getMetadataVersion(
|
||||
workspaceId,
|
||||
)) ?? 1;
|
||||
|
||||
let latestVersion = await this.getMetadataVersion(workspaceId);
|
||||
|
||||
if (latestVersion === undefined || currentVersion !== latestVersion) {
|
||||
this.logger.log(
|
||||
`Metadata version mismatch detected for workspace ${workspaceId}. Current version: ${currentVersion}. Latest version: ${latestVersion}. Invalidating cache...`,
|
||||
);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
|
||||
latestVersion = await this.incrementMetadataVersion(workspaceId);
|
||||
|
||||
await this.workspaceCacheStorageService.setMetadataVersion(
|
||||
workspaceId,
|
||||
latestVersion,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async incrementMetadataVersion(workspaceId: string): Promise<number> {
|
||||
const metadataVersion = (await this.getMetadataVersion(workspaceId)) ?? 0;
|
||||
const newMetadataVersion = metadataVersion + 1;
|
||||
|
||||
await this.workspaceRepository.update(
|
||||
{ id: workspaceId },
|
||||
{ metadataVersion: newMetadataVersion },
|
||||
);
|
||||
|
||||
await this.workspaceCacheStorageService.setMetadataVersion(
|
||||
workspaceId,
|
||||
newMetadataVersion,
|
||||
);
|
||||
|
||||
return newMetadataVersion;
|
||||
}
|
||||
|
||||
async getMetadataVersion(workspaceId: string): Promise<number | undefined> {
|
||||
const workspace = await this.workspaceRepository.findOne({
|
||||
where: { id: workspaceId },
|
||||
});
|
||||
|
||||
return workspace?.metadataVersion;
|
||||
}
|
||||
|
||||
async resetMetadataVersion(workspaceId: string): Promise<void> {
|
||||
await this.workspaceRepository.update(
|
||||
{ id: workspaceId },
|
||||
{ metadataVersion: 1 },
|
||||
);
|
||||
|
||||
await this.workspaceCacheStorageService.flush(workspaceId);
|
||||
await this.workspaceCacheStorageService.setMetadataVersion(workspaceId, 1);
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@ import { AuthGraphqlApiExceptionFilter } from 'src/engine/core-modules/auth/filt
|
||||
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
||||
import { AuthContext } from 'src/engine/core-modules/auth/types/auth-context.type';
|
||||
import { ExceptionHandlerService } from 'src/engine/integrations/exception-handler/exception-handler.service';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { handleExceptionAndConvertToGraphQLError } from 'src/engine/utils/global-exception-handler.util';
|
||||
|
||||
class GraphqlTokenValidationProxy {
|
||||
@ -33,7 +33,7 @@ export class GraphQLHydrateRequestFromTokenMiddleware
|
||||
{
|
||||
constructor(
|
||||
private readonly tokenService: TokenService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
private readonly exceptionHandlerService: ExceptionHandlerService,
|
||||
) {}
|
||||
|
||||
@ -72,15 +72,16 @@ export class GraphQLHydrateRequestFromTokenMiddleware
|
||||
);
|
||||
|
||||
data = await graphqlTokenValidationProxy.validateToken(req);
|
||||
const cacheVersion = await this.workspaceCacheVersionService.getVersion(
|
||||
data.workspace.id,
|
||||
);
|
||||
const metadataVersion =
|
||||
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||
data.workspace.id,
|
||||
);
|
||||
|
||||
req.user = data.user;
|
||||
req.apiKey = data.apiKey;
|
||||
req.workspace = data.workspace;
|
||||
req.workspaceId = data.workspace.id;
|
||||
req.cacheVersion = cacheVersion;
|
||||
req.workspaceMetadataVersion = metadataVersion;
|
||||
} catch (error) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.write(
|
||||
|
||||
@ -1,44 +0,0 @@
|
||||
import { Inject, Type } from '@nestjs/common';
|
||||
import { ModuleRef, createContextId } from '@nestjs/core';
|
||||
import { Injector } from '@nestjs/core/injector/injector';
|
||||
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
|
||||
export class LoadServiceWithWorkspaceContext {
|
||||
private readonly injector = new Injector();
|
||||
|
||||
constructor(
|
||||
@Inject(ModuleRef)
|
||||
private readonly moduleRef: ModuleRef,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
) {}
|
||||
|
||||
async load<T>(service: T, workspaceId: string): Promise<T> {
|
||||
const modules = this.moduleRef['container'].getModules();
|
||||
const host = [...modules.values()].find((module) =>
|
||||
module.providers.has((service as Type<T>).constructor),
|
||||
);
|
||||
|
||||
if (!host) {
|
||||
throw new Error('Host module not found for the service');
|
||||
}
|
||||
|
||||
const contextId = createContextId();
|
||||
const cacheVersion =
|
||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
||||
|
||||
if (this.moduleRef.registerRequestByContextId) {
|
||||
this.moduleRef.registerRequestByContextId(
|
||||
{ req: { workspaceId, cacheVersion } },
|
||||
contextId,
|
||||
);
|
||||
}
|
||||
|
||||
return this.injector.loadPerContext(
|
||||
service,
|
||||
host,
|
||||
new Map(host.providers),
|
||||
contextId,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -11,16 +11,16 @@ export class ScopedWorkspaceContextFactory {
|
||||
|
||||
public create(): {
|
||||
workspaceId: string | null;
|
||||
cacheVersion: string | null;
|
||||
workspaceMetadataVersion: string | null;
|
||||
} {
|
||||
const workspaceId: string | undefined =
|
||||
this.request?.['req']?.['workspaceId'];
|
||||
const cacheVersion: string | undefined =
|
||||
this.request?.['req']?.['cacheVersion'];
|
||||
const workspaceMetadataVersion: string | undefined =
|
||||
this.request?.['req']?.['workspaceMetadataVersion'];
|
||||
|
||||
return {
|
||||
workspaceId: workspaceId ?? null,
|
||||
cacheVersion: cacheVersion ?? null,
|
||||
workspaceMetadataVersion: workspaceMetadataVersion ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Repository } from 'typeorm';
|
||||
import { EntitySchema, Repository } from 'typeorm';
|
||||
|
||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||
import { workspaceDataSourceCacheInstance } from 'src/engine/twenty-orm/twenty-orm-core.module';
|
||||
@ -18,7 +18,7 @@ export class WorkspaceDatasourceFactory {
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
private readonly environmentService: EnvironmentService,
|
||||
private readonly workspaceCacheStorageService: WorkspaceCacheStorageService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
@InjectRepository(ObjectMetadataEntity, 'metadata')
|
||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
private readonly entitySchemaFactory: EntitySchemaFactory,
|
||||
@ -26,21 +26,29 @@ export class WorkspaceDatasourceFactory {
|
||||
|
||||
public async create(
|
||||
workspaceId: string,
|
||||
workspaceSchemaVersion: string | null,
|
||||
workspaceMetadataVersion: string | null,
|
||||
): Promise<WorkspaceDataSource> {
|
||||
const desiredWorkspaceSchemaVersion =
|
||||
workspaceSchemaVersion ??
|
||||
(await this.workspaceCacheVersionService.getVersion(workspaceId));
|
||||
const desiredWorkspaceMetadataVersion =
|
||||
workspaceMetadataVersion ??
|
||||
(await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||
workspaceId,
|
||||
));
|
||||
|
||||
if (!desiredWorkspaceSchemaVersion) {
|
||||
throw new Error('Cache version not found');
|
||||
if (!desiredWorkspaceMetadataVersion) {
|
||||
throw new Error(
|
||||
`Desired workspace metadata version not found while creating workspace data source for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const latestWorkspaceSchemaVersion =
|
||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
||||
const latestWorkspaceMetadataVersion =
|
||||
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
if (latestWorkspaceSchemaVersion !== desiredWorkspaceSchemaVersion) {
|
||||
throw new Error('Cache version mismatch');
|
||||
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) {
|
||||
throw new Error(
|
||||
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
|
||||
);
|
||||
}
|
||||
|
||||
let cachedObjectMetadataCollection =
|
||||
@ -70,7 +78,7 @@ export class WorkspaceDatasourceFactory {
|
||||
}
|
||||
|
||||
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
|
||||
`${workspaceId}-${latestWorkspaceSchemaVersion}`,
|
||||
`${workspaceId}-${latestWorkspaceMetadataVersion}`,
|
||||
async () => {
|
||||
const dataSourceMetadata =
|
||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
|
||||
@ -78,18 +86,43 @@ export class WorkspaceDatasourceFactory {
|
||||
);
|
||||
|
||||
if (!dataSourceMetadata) {
|
||||
throw new Error('Data source metadata not found');
|
||||
throw new Error(
|
||||
`Data source metadata not found for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!cachedObjectMetadataCollection) {
|
||||
throw new Error('Object metadata collection not found');
|
||||
throw new Error(
|
||||
`Object metadata collection not found for workspace ${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const cachedEntitySchemaOptions =
|
||||
await this.workspaceCacheStorageService.getORMEntitySchema(
|
||||
workspaceId,
|
||||
);
|
||||
|
||||
let cachedEntitySchemas: EntitySchema[];
|
||||
|
||||
if (cachedEntitySchemaOptions) {
|
||||
cachedEntitySchemas = cachedEntitySchemaOptions.map(
|
||||
(option) => new EntitySchema(option),
|
||||
);
|
||||
} else {
|
||||
const entitySchemas = await Promise.all(
|
||||
cachedObjectMetadataCollection.map((objectMetadata) =>
|
||||
this.entitySchemaFactory.create(workspaceId, objectMetadata),
|
||||
),
|
||||
);
|
||||
|
||||
await this.workspaceCacheStorageService.setORMEntitySchema(
|
||||
workspaceId,
|
||||
entitySchemas.map((entitySchema) => entitySchema.options),
|
||||
);
|
||||
|
||||
cachedEntitySchemas = entitySchemas;
|
||||
}
|
||||
|
||||
const entities = await Promise.all(
|
||||
cachedObjectMetadataCollection.map((objectMetadata) =>
|
||||
this.entitySchemaFactory.create(workspaceId, objectMetadata),
|
||||
),
|
||||
);
|
||||
const workspaceDataSource = new WorkspaceDataSource(
|
||||
{
|
||||
workspaceId,
|
||||
@ -104,7 +137,7 @@ export class WorkspaceDatasourceFactory {
|
||||
? ['query', 'error']
|
||||
: ['error'],
|
||||
schema: dataSourceMetadata.schema,
|
||||
entities,
|
||||
entities: cachedEntitySchemas,
|
||||
ssl: this.environmentService.get('PG_SSL_ALLOW_SELF_SIGNED')
|
||||
? {
|
||||
rejectUnauthorized: false,
|
||||
|
||||
@ -14,8 +14,7 @@ import {
|
||||
|
||||
import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceDataSource } from 'src/engine/twenty-orm/datasource/workspace.datasource';
|
||||
import { entitySchemaFactories } from 'src/engine/twenty-orm/factories';
|
||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||
@ -33,21 +32,15 @@ export const workspaceDataSourceCacheInstance =
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([ObjectMetadataEntity], 'metadata'),
|
||||
DataSourceModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceCacheStorageModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
providers: [
|
||||
...entitySchemaFactories,
|
||||
TwentyORMManager,
|
||||
TwentyORMGlobalManager,
|
||||
LoadServiceWithWorkspaceContext,
|
||||
],
|
||||
exports: [
|
||||
EntitySchemaFactory,
|
||||
TwentyORMManager,
|
||||
LoadServiceWithWorkspaceContext,
|
||||
TwentyORMGlobalManager,
|
||||
],
|
||||
exports: [EntitySchemaFactory, TwentyORMManager, TwentyORMGlobalManager],
|
||||
})
|
||||
export class TwentyORMCoreModule
|
||||
extends ConfigurableModuleClass
|
||||
|
||||
@ -25,7 +25,7 @@ export class TwentyORMManager {
|
||||
async getRepository<T extends ObjectLiteral>(
|
||||
workspaceEntityOrobjectMetadataName: Type<T> | string,
|
||||
): Promise<WorkspaceRepository<T>> {
|
||||
const { workspaceId, cacheVersion } =
|
||||
const { workspaceId, workspaceMetadataVersion } =
|
||||
this.scopedWorkspaceContextFactory.create();
|
||||
|
||||
let objectMetadataName: string;
|
||||
@ -44,20 +44,23 @@ export class TwentyORMManager {
|
||||
|
||||
const workspaceDataSource = await this.workspaceDataSourceFactory.create(
|
||||
workspaceId,
|
||||
cacheVersion,
|
||||
workspaceMetadataVersion,
|
||||
);
|
||||
|
||||
return workspaceDataSource.getRepository<T>(objectMetadataName);
|
||||
}
|
||||
|
||||
async getDatasource() {
|
||||
const { workspaceId, cacheVersion } =
|
||||
const { workspaceId, workspaceMetadataVersion } =
|
||||
this.scopedWorkspaceContextFactory.create();
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace not found');
|
||||
}
|
||||
|
||||
return this.workspaceDataSourceFactory.create(workspaceId, cacheVersion);
|
||||
return this.workspaceDataSourceFactory.create(
|
||||
workspaceId,
|
||||
workspaceMetadataVersion,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceCacheStorageService } from 'src/engine/workspace-cache-storage/workspace-cache-storage.service';
|
||||
|
||||
@Module({
|
||||
imports: [WorkspaceCacheVersionModule],
|
||||
providers: [WorkspaceCacheStorageService],
|
||||
exports: [WorkspaceCacheStorageService],
|
||||
})
|
||||
|
||||
@ -1,56 +1,67 @@
|
||||
import { Injectable, Logger } from '@nestjs/common';
|
||||
|
||||
import { EntitySchemaOptions } from 'typeorm';
|
||||
|
||||
import { CacheStorageService } from 'src/engine/integrations/cache-storage/cache-storage.service';
|
||||
import { InjectCacheStorage } from 'src/engine/integrations/cache-storage/decorators/cache-storage.decorator';
|
||||
import { CacheStorageNamespace } from 'src/engine/integrations/cache-storage/types/cache-storage-namespace.enum';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
|
||||
enum WorkspaceCacheKeys {
|
||||
GraphQLTypeDefs = 'graphql:type-defs',
|
||||
GraphQLUsedScalarNames = 'graphql:used-scalar-names',
|
||||
GraphQLOperations = 'graphql:operations',
|
||||
ORMEntitySchemas = 'orm:entity-schemas',
|
||||
MetadataObjectMetadataCollection = 'metadata:object-metadata-collection',
|
||||
MetadataVersion = 'metadata:workspace-metadata-version',
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class WorkspaceCacheStorageService {
|
||||
private readonly logger = new Logger(WorkspaceCacheStorageService.name);
|
||||
|
||||
constructor(
|
||||
@InjectCacheStorage(CacheStorageNamespace.WorkspaceSchema)
|
||||
private readonly workspaceSchemaCache: CacheStorageService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
@InjectCacheStorage(CacheStorageNamespace.EngineWorkspace)
|
||||
private readonly cacheStorageService: CacheStorageService,
|
||||
) {}
|
||||
|
||||
async validateCacheVersion(workspaceId: string): Promise<void> {
|
||||
const currentVersion =
|
||||
(await this.workspaceSchemaCache.get<string>(
|
||||
`cacheVersion:${workspaceId}`,
|
||||
)) ?? '0';
|
||||
setORMEntitySchema(
|
||||
workspaceId: string,
|
||||
entitySchemas: EntitySchemaOptions<any>[],
|
||||
) {
|
||||
return this.cacheStorageService.set<EntitySchemaOptions<any>[]>(
|
||||
`${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`,
|
||||
entitySchemas,
|
||||
);
|
||||
}
|
||||
|
||||
let latestVersion =
|
||||
await this.workspaceCacheVersionService.getVersion(workspaceId);
|
||||
getORMEntitySchema(
|
||||
workspaceId: string,
|
||||
): Promise<EntitySchemaOptions<any>[] | undefined> {
|
||||
return this.cacheStorageService.get<EntitySchemaOptions<any>[]>(
|
||||
`${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
if (!latestVersion || currentVersion !== latestVersion) {
|
||||
// Invalidate cache if version mismatch is detected"
|
||||
this.logger.log(
|
||||
`Cache version mismatch detected for workspace ${workspaceId}. Current version: ${currentVersion}. Latest version: ${latestVersion}. Invalidating cache...`,
|
||||
);
|
||||
setMetadataVersion(workspaceId: string, version: number): Promise<void> {
|
||||
return this.cacheStorageService.set<number>(
|
||||
`${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`,
|
||||
version,
|
||||
);
|
||||
}
|
||||
|
||||
await this.invalidateCache(workspaceId);
|
||||
|
||||
// If the latest version is not found, increment the version
|
||||
latestVersion ??=
|
||||
await this.workspaceCacheVersionService.incrementVersion(workspaceId);
|
||||
|
||||
// Update the cache version after invalidation
|
||||
await this.workspaceSchemaCache.set<string>(
|
||||
`cacheVersion:${workspaceId}`,
|
||||
latestVersion,
|
||||
);
|
||||
}
|
||||
getMetadataVersion(workspaceId: string): Promise<number | undefined> {
|
||||
return this.cacheStorageService.get<number>(
|
||||
`${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
setObjectMetadataCollection(
|
||||
workspaceId: string,
|
||||
objectMetadataCollection: ObjectMetadataEntity[],
|
||||
) {
|
||||
return this.workspaceSchemaCache.set<ObjectMetadataEntity[]>(
|
||||
`objectMetadataCollection:${workspaceId}`,
|
||||
return this.cacheStorageService.set<ObjectMetadataEntity[]>(
|
||||
`${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`,
|
||||
objectMetadataCollection,
|
||||
);
|
||||
}
|
||||
@ -58,43 +69,57 @@ export class WorkspaceCacheStorageService {
|
||||
getObjectMetadataCollection(
|
||||
workspaceId: string,
|
||||
): Promise<ObjectMetadataEntity[] | undefined> {
|
||||
return this.workspaceSchemaCache.get<ObjectMetadataEntity[]>(
|
||||
`objectMetadataCollection:${workspaceId}`,
|
||||
return this.cacheStorageService.get<ObjectMetadataEntity[]>(
|
||||
`${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
setTypeDefs(workspaceId: string, typeDefs: string): Promise<void> {
|
||||
return this.workspaceSchemaCache.set<string>(
|
||||
`typeDefs:${workspaceId}`,
|
||||
setGraphQLTypeDefs(workspaceId: string, typeDefs: string): Promise<void> {
|
||||
return this.cacheStorageService.set<string>(
|
||||
`${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`,
|
||||
typeDefs,
|
||||
);
|
||||
}
|
||||
|
||||
getTypeDefs(workspaceId: string): Promise<string | undefined> {
|
||||
return this.workspaceSchemaCache.get<string>(`typeDefs:${workspaceId}`);
|
||||
getGraphQLTypeDefs(workspaceId: string): Promise<string | undefined> {
|
||||
return this.cacheStorageService.get<string>(
|
||||
`${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
setUsedScalarNames(
|
||||
setGraphQLUsedScalarNames(
|
||||
workspaceId: string,
|
||||
scalarsUsed: string[],
|
||||
usedScalarNames: string[],
|
||||
): Promise<void> {
|
||||
return this.workspaceSchemaCache.set<string[]>(
|
||||
`usedScalarNames:${workspaceId}`,
|
||||
scalarsUsed,
|
||||
return this.cacheStorageService.set<string[]>(
|
||||
`${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`,
|
||||
usedScalarNames,
|
||||
);
|
||||
}
|
||||
|
||||
getUsedScalarNames(workspaceId: string): Promise<string[] | undefined> {
|
||||
return this.workspaceSchemaCache.get<string[]>(
|
||||
`usedScalarNames:${workspaceId}`,
|
||||
getGraphQLUsedScalarNames(
|
||||
workspaceId: string,
|
||||
): Promise<string[] | undefined> {
|
||||
return this.cacheStorageService.get<string[]>(
|
||||
`${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`,
|
||||
);
|
||||
}
|
||||
|
||||
async invalidateCache(workspaceId: string): Promise<void> {
|
||||
await this.workspaceSchemaCache.del(
|
||||
`objectMetadataCollection:${workspaceId}`,
|
||||
async flush(workspaceId: string): Promise<void> {
|
||||
await this.cacheStorageService.del(
|
||||
`${WorkspaceCacheKeys.MetadataObjectMetadataCollection}:${workspaceId}`,
|
||||
);
|
||||
await this.cacheStorageService.del(
|
||||
`${WorkspaceCacheKeys.MetadataVersion}:${workspaceId}`,
|
||||
);
|
||||
await this.cacheStorageService.del(
|
||||
`${WorkspaceCacheKeys.GraphQLTypeDefs}:${workspaceId}`,
|
||||
);
|
||||
await this.cacheStorageService.del(
|
||||
`${WorkspaceCacheKeys.GraphQLUsedScalarNames}:${workspaceId}`,
|
||||
);
|
||||
await this.cacheStorageService.del(
|
||||
`${WorkspaceCacheKeys.ORMEntitySchemas}:${workspaceId}`,
|
||||
);
|
||||
await this.workspaceSchemaCache.del(`typeDefs:${workspaceId}`);
|
||||
await this.workspaceSchemaCache.del(`usedScalarNames:${workspaceId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Logger } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { Command, CommandRunner, Option } from 'nest-commander';
|
||||
import { In, Repository } from 'typeorm';
|
||||
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||
import { getDryRunLogHeader } from 'src/utils/get-dry-run-log-header';
|
||||
import { WorkspaceService } from 'src/engine/core-modules/workspace/services/workspace.service';
|
||||
import { LoadServiceWithWorkspaceContext } from 'src/engine/twenty-orm/context/load-service-with-workspace.context';
|
||||
|
||||
type DeleteWorkspacesCommandOptions = {
|
||||
dryRun?: boolean;
|
||||
@ -24,7 +23,6 @@ export class DeleteWorkspacesCommand extends CommandRunner {
|
||||
|
||||
constructor(
|
||||
private readonly workspaceService: WorkspaceService,
|
||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
||||
@InjectRepository(Workspace, 'core')
|
||||
private readonly workspaceRepository: Repository<Workspace>,
|
||||
private readonly dataSourceService: DataSourceService,
|
||||
@ -81,15 +79,15 @@ export class DeleteWorkspacesCommand extends CommandRunner {
|
||||
workspace.id
|
||||
} name: '${workspace.displayName}'`,
|
||||
);
|
||||
const workspaceServiceInstance =
|
||||
await this.loadServiceWithWorkspaceContext.load(
|
||||
this.workspaceService,
|
||||
workspace.id,
|
||||
);
|
||||
// const workspaceServiceInstance =
|
||||
// await this.loadServiceWithWorkspaceContext.load(
|
||||
// this.workspaceService,
|
||||
// workspace.id,
|
||||
// );
|
||||
|
||||
if (!options.dryRun) {
|
||||
await workspaceServiceInstance.softDeleteWorkspace(workspace.id);
|
||||
}
|
||||
// if (!options.dryRun) {
|
||||
// await workspaceServiceInstance.softDeleteWorkspace(workspace.id);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ import { Module } from '@nestjs/common';
|
||||
|
||||
import { WorkspaceMigrationModule } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.module';
|
||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMigrationEnumService } from 'src/engine/workspace-manager/workspace-migration-runner/services/workspace-migration-enum.service';
|
||||
|
||||
import { WorkspaceMigrationRunnerService } from './workspace-migration-runner.service';
|
||||
@ -10,11 +9,7 @@ import { WorkspaceMigrationRunnerService } from './workspace-migration-runner.se
|
||||
import { WorkspaceMigrationTypeService } from './services/workspace-migration-type.service';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
WorkspaceDataSourceModule,
|
||||
WorkspaceMigrationModule,
|
||||
WorkspaceCacheVersionModule,
|
||||
],
|
||||
imports: [WorkspaceDataSourceModule, WorkspaceMigrationModule],
|
||||
providers: [
|
||||
WorkspaceMigrationRunnerService,
|
||||
WorkspaceMigrationEnumService,
|
||||
|
||||
@ -6,7 +6,7 @@ import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-
|
||||
import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { RelationMetadataEntity } from 'src/engine/metadata-modules/relation-metadata/relation-metadata.entity';
|
||||
import { WorkspaceCacheVersionModule } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.module';
|
||||
import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationBuilderModule } from 'src/engine/workspace-manager/workspace-migration-builder/workspace-migration-builder.module';
|
||||
import { WorkspaceMigrationRunnerModule } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.module';
|
||||
@ -35,7 +35,7 @@ import { WorkspaceSyncMetadataService } from 'src/engine/workspace-manager/works
|
||||
'metadata',
|
||||
),
|
||||
TypeOrmModule.forFeature([FeatureFlagEntity], 'core'),
|
||||
WorkspaceCacheVersionModule,
|
||||
WorkspaceMetadataVersionModule,
|
||||
],
|
||||
providers: [
|
||||
...workspaceSyncMetadataFactories,
|
||||
|
||||
@ -6,7 +6,7 @@ import { DataSource, QueryFailedError } from 'typeorm';
|
||||
import { WorkspaceSyncContext } from 'src/engine/workspace-manager/workspace-sync-metadata/interfaces/workspace-sync-context.interface';
|
||||
|
||||
import { FeatureFlagFactory } from 'src/engine/core-modules/feature-flag/services/feature-flags.factory';
|
||||
import { WorkspaceCacheVersionService } from 'src/engine/metadata-modules/workspace-cache-version/workspace-cache-version.service';
|
||||
import { WorkspaceMetadataVersionService } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.service';
|
||||
import { WorkspaceMigrationEntity } from 'src/engine/metadata-modules/workspace-migration/workspace-migration.entity';
|
||||
import { WorkspaceMigrationRunnerService } from 'src/engine/workspace-manager/workspace-migration-runner/workspace-migration-runner.service';
|
||||
import { WorkspaceSyncFieldMetadataService } from 'src/engine/workspace-manager/workspace-sync-metadata/services/workspace-sync-field-metadata.service';
|
||||
@ -32,9 +32,9 @@ export class WorkspaceSyncMetadataService {
|
||||
private readonly workspaceSyncObjectMetadataService: WorkspaceSyncObjectMetadataService,
|
||||
private readonly workspaceSyncRelationMetadataService: WorkspaceSyncRelationMetadataService,
|
||||
private readonly workspaceSyncFieldMetadataService: WorkspaceSyncFieldMetadataService,
|
||||
private readonly workspaceCacheVersionService: WorkspaceCacheVersionService,
|
||||
private readonly workspaceSyncIndexMetadataService: WorkspaceSyncIndexMetadataService,
|
||||
private readonly workspaceSyncObjectMetadataIdentifiersService: WorkspaceSyncObjectMetadataIdentifiersService,
|
||||
private readonly workspaceMetadataVersionService: WorkspaceMetadataVersionService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
@ -157,7 +157,7 @@ export class WorkspaceSyncMetadataService {
|
||||
await queryRunner.rollbackTransaction();
|
||||
} finally {
|
||||
await queryRunner.release();
|
||||
await this.workspaceCacheVersionService.incrementVersion(
|
||||
await this.workspaceMetadataVersionService.incrementMetadataVersion(
|
||||
context.workspaceId,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user