Refactor global datasource part 2 (#16399)
## Context Deprecating TwentyORMManager in favor of TwentyORMGlobalManager (temporarily, as this will simplify the ultimate goal to later replace all usages with the new TwentyORMGlobalManagerV2 which will have a similar signature) This means this PR had to refactor a bit of code to pass down the workspaceId when not available directly as it is now a requirement, meaning we also deprecated scopedWorkspaceContextFactory to have a less obscure way to fetch the workspaceId and have something more declarative. Step 3 will be to update TwentyORMGlobalManager to use a featureFlag toggling and use the new GlobalWorkspaceOrmManager internally using the new cache service Step 4 will be to remove the feature flag and pg_pool patch
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { EntitySchemaColumnFactory } from 'src/engine/twenty-orm/factories/entity-schema-column.factory';
|
||||
import { EntitySchemaRelationFactory } from 'src/engine/twenty-orm/factories/entity-schema-relation.factory';
|
||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
|
||||
|
||||
export const entitySchemaFactories = [
|
||||
@@ -9,5 +8,4 @@ export const entitySchemaFactories = [
|
||||
EntitySchemaRelationFactory,
|
||||
EntitySchemaFactory,
|
||||
WorkspaceDatasourceFactory,
|
||||
ScopedWorkspaceContextFactory,
|
||||
];
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
import { Inject, Injectable, Optional, Scope } from '@nestjs/common';
|
||||
import { REQUEST } from '@nestjs/core';
|
||||
|
||||
@Injectable({ scope: Scope.REQUEST })
|
||||
export class ScopedWorkspaceContextFactory {
|
||||
constructor(
|
||||
@Optional()
|
||||
@Inject(REQUEST)
|
||||
private readonly request: Request | null,
|
||||
) {}
|
||||
|
||||
public create(): {
|
||||
workspaceId: string | null;
|
||||
userWorkspaceId: string | null;
|
||||
isExecutedByApiKey: boolean;
|
||||
apiKeyId: string | null;
|
||||
} {
|
||||
const workspaceId: string | undefined =
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['req']?.['workspaceId'] ||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['params']?.['workspaceId'] ||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['workspace']?.['id']; // rest api
|
||||
|
||||
// Extract API key ID (same pattern as userWorkspaceId)
|
||||
const apiKey =
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['req']?.['apiKey'] ||
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['apiKey']; // rest api
|
||||
|
||||
return {
|
||||
workspaceId: workspaceId ?? null,
|
||||
userWorkspaceId:
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['req']?.['userWorkspaceId'] ??
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
this.request?.['userWorkspaceId'] ?? // rest api
|
||||
null,
|
||||
isExecutedByApiKey: !!apiKey,
|
||||
apiKeyId: apiKey?.id ?? null,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
import { Injectable, type Type } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type ObjectLiteral, Repository } from 'typeorm';
|
||||
|
||||
import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-target.entity';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
|
||||
import { type WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||
import { convertClassNameToObjectMetadataName } from 'src/engine/workspace-manager/workspace-sync-metadata/utils/convert-class-to-object-metadata-name.util';
|
||||
|
||||
@Injectable()
|
||||
export class TwentyORMManager {
|
||||
constructor(
|
||||
@InjectRepository(RoleTargetEntity)
|
||||
private readonly roleTargetRepository: Repository<RoleTargetEntity>,
|
||||
private readonly workspaceDataSourceFactory: WorkspaceDatasourceFactory,
|
||||
private readonly scopedWorkspaceContextFactory: ScopedWorkspaceContextFactory,
|
||||
) {}
|
||||
|
||||
async getRepository<T extends ObjectLiteral>(
|
||||
workspaceEntity: Type<T>,
|
||||
): Promise<WorkspaceRepository<T>>;
|
||||
|
||||
async getRepository<T extends ObjectLiteral>(
|
||||
objectMetadataName: string,
|
||||
): Promise<WorkspaceRepository<T>>;
|
||||
|
||||
async getRepository<T extends ObjectLiteral>(
|
||||
workspaceEntityOrObjectMetadataName: Type<T> | string,
|
||||
): Promise<WorkspaceRepository<T>> {
|
||||
const { workspaceId, userWorkspaceId, apiKeyId } =
|
||||
this.scopedWorkspaceContextFactory.create();
|
||||
|
||||
let objectMetadataName: string;
|
||||
|
||||
if (typeof workspaceEntityOrObjectMetadataName === 'string') {
|
||||
objectMetadataName = workspaceEntityOrObjectMetadataName;
|
||||
} else {
|
||||
objectMetadataName = convertClassNameToObjectMetadataName(
|
||||
workspaceEntityOrObjectMetadataName.name,
|
||||
);
|
||||
}
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace not found');
|
||||
}
|
||||
|
||||
const workspaceDataSource =
|
||||
await this.workspaceDataSourceFactory.create(workspaceId);
|
||||
|
||||
let roleId: string | undefined;
|
||||
|
||||
if (isDefined(userWorkspaceId)) {
|
||||
const roleTarget = await this.roleTargetRepository.findOne({
|
||||
where: {
|
||||
userWorkspaceId,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
roleId = roleTarget?.roleId;
|
||||
} else if (isDefined(apiKeyId)) {
|
||||
const roleTarget = await this.roleTargetRepository.findOne({
|
||||
where: {
|
||||
apiKeyId,
|
||||
workspaceId,
|
||||
},
|
||||
});
|
||||
|
||||
roleId = roleTarget?.roleId;
|
||||
}
|
||||
|
||||
return workspaceDataSource.getRepository<T>(
|
||||
objectMetadataName,
|
||||
roleId ? { unionOf: [roleId] } : undefined,
|
||||
);
|
||||
}
|
||||
|
||||
async getDatasource() {
|
||||
const { workspaceId } = this.scopedWorkspaceContextFactory.create();
|
||||
|
||||
if (!workspaceId) {
|
||||
throw new Error('Workspace not found');
|
||||
}
|
||||
|
||||
return this.workspaceDataSourceFactory.create(workspaceId);
|
||||
}
|
||||
}
|
||||
@@ -12,9 +12,7 @@ import { RoleTargetEntity } from 'src/engine/metadata-modules/role-target/role-t
|
||||
import { WorkspaceFeatureFlagsMapCacheModule } from 'src/engine/metadata-modules/workspace-feature-flags-map-cache/workspace-feature-flags-map-cache.module';
|
||||
import { entitySchemaFactories } from 'src/engine/twenty-orm/factories';
|
||||
import { EntitySchemaFactory } from 'src/engine/twenty-orm/factories/entity-schema.factory';
|
||||
import { ScopedWorkspaceContextFactory } from 'src/engine/twenty-orm/factories/scoped-workspace-context.factory';
|
||||
import { TwentyORMGlobalManager } from 'src/engine/twenty-orm/twenty-orm-global.manager';
|
||||
import { TwentyORMManager } from 'src/engine/twenty-orm/twenty-orm.manager';
|
||||
import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module';
|
||||
import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module';
|
||||
|
||||
@@ -38,17 +36,7 @@ import { PgPoolSharedModule } from './pg-shared-pool/pg-shared-pool.module';
|
||||
PgPoolSharedModule,
|
||||
WorkspaceCacheModule,
|
||||
],
|
||||
providers: [
|
||||
...entitySchemaFactories,
|
||||
TwentyORMManager,
|
||||
TwentyORMGlobalManager,
|
||||
],
|
||||
exports: [
|
||||
EntitySchemaFactory,
|
||||
TwentyORMManager,
|
||||
TwentyORMGlobalManager,
|
||||
PgPoolSharedModule,
|
||||
ScopedWorkspaceContextFactory,
|
||||
],
|
||||
providers: [...entitySchemaFactories, TwentyORMGlobalManager],
|
||||
exports: [EntitySchemaFactory, TwentyORMGlobalManager, PgPoolSharedModule],
|
||||
})
|
||||
export class TwentyORMModule {}
|
||||
|
||||
Reference in New Issue
Block a user