Add logging on currentWorkspaceMember query (#6706)
We are experiencing slow GetCurrentUser endpoint, this is helping us troubleshoot
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { DataSource, DataSourceOptions } from 'typeorm';
|
|
||||||
import { config } from 'dotenv';
|
import { config } from 'dotenv';
|
||||||
|
import { DataSource, DataSourceOptions } from 'typeorm';
|
||||||
config();
|
config();
|
||||||
|
|
||||||
export const typeORMCoreModuleOptions: TypeOrmModuleOptions = {
|
export const typeORMCoreModuleOptions: TypeOrmModuleOptions = {
|
||||||
|
|||||||
@ -40,18 +40,24 @@ export class UserService extends TypeOrmQueryService<User> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.time('loadWorkspaceMember repo');
|
||||||
const workspaceMemberRepository =
|
const workspaceMemberRepository =
|
||||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||||
user.defaultWorkspaceId,
|
user.defaultWorkspaceId,
|
||||||
'workspaceMember',
|
'workspaceMember',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.timeEnd('loadWorkspaceMember repo');
|
||||||
|
|
||||||
|
console.time('loadWorkspaceMember find');
|
||||||
const workspaceMember = await workspaceMemberRepository.findOne({
|
const workspaceMember = await workspaceMemberRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
userId: user.id,
|
userId: user.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.timeEnd('loadWorkspaceMember find');
|
||||||
|
|
||||||
return workspaceMember;
|
return workspaceMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,13 +66,22 @@ export class UserService extends TypeOrmQueryService<User> {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.time('loadWorkspaceMembers repo');
|
||||||
const workspaceMemberRepository =
|
const workspaceMemberRepository =
|
||||||
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
await this.twentyORMGlobalManager.getRepositoryForWorkspace<WorkspaceMemberWorkspaceEntity>(
|
||||||
workspace.id,
|
workspace.id,
|
||||||
'workspaceMember',
|
'workspaceMember',
|
||||||
);
|
);
|
||||||
|
|
||||||
return workspaceMemberRepository.find();
|
console.timeEnd('loadWorkspaceMembers repo');
|
||||||
|
|
||||||
|
console.time('loadWorkspaceMembers find');
|
||||||
|
|
||||||
|
const workspaceMembers = workspaceMemberRepository.find();
|
||||||
|
|
||||||
|
console.timeEnd('loadWorkspaceMembers find');
|
||||||
|
|
||||||
|
return workspaceMembers;
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteUser(userId: string): Promise<User> {
|
async deleteUser(userId: string): Promise<User> {
|
||||||
|
|||||||
@ -98,6 +98,7 @@ export class UserResolver {
|
|||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
async workspaceMember(@Parent() user: User): Promise<WorkspaceMember | null> {
|
async workspaceMember(@Parent() user: User): Promise<WorkspaceMember | null> {
|
||||||
|
console.time('resolver workspaceMember');
|
||||||
const workspaceMember = await this.userService.loadWorkspaceMember(user);
|
const workspaceMember = await this.userService.loadWorkspaceMember(user);
|
||||||
|
|
||||||
if (workspaceMember && workspaceMember.avatarUrl) {
|
if (workspaceMember && workspaceMember.avatarUrl) {
|
||||||
@ -108,6 +109,7 @@ export class UserResolver {
|
|||||||
|
|
||||||
workspaceMember.avatarUrl = `${workspaceMember.avatarUrl}?token=${avatarUrlToken}`;
|
workspaceMember.avatarUrl = `${workspaceMember.avatarUrl}?token=${avatarUrlToken}`;
|
||||||
}
|
}
|
||||||
|
console.timeEnd('resolver workspaceMember');
|
||||||
|
|
||||||
// TODO: Fix typing disrepency between Entity and DTO
|
// TODO: Fix typing disrepency between Entity and DTO
|
||||||
return workspaceMember as WorkspaceMember | null;
|
return workspaceMember as WorkspaceMember | null;
|
||||||
@ -117,6 +119,7 @@ export class UserResolver {
|
|||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
async workspaceMembers(@Parent() user: User): Promise<WorkspaceMember[]> {
|
async workspaceMembers(@Parent() user: User): Promise<WorkspaceMember[]> {
|
||||||
|
console.time('resolver workspaceMembers');
|
||||||
const workspaceMembers = await this.userService.loadWorkspaceMembers(
|
const workspaceMembers = await this.userService.loadWorkspaceMembers(
|
||||||
user.defaultWorkspace,
|
user.defaultWorkspace,
|
||||||
);
|
);
|
||||||
@ -132,6 +135,8 @@ export class UserResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.timeEnd('resolver workspaceMembers');
|
||||||
|
|
||||||
// TODO: Fix typing disrepency between Entity and DTO
|
// TODO: Fix typing disrepency between Entity and DTO
|
||||||
return workspaceMembers as WorkspaceMember[];
|
return workspaceMembers as WorkspaceMember[];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ export class WorkspaceEntityManager extends EntityManager {
|
|||||||
target: EntityTarget<Entity>,
|
target: EntityTarget<Entity>,
|
||||||
): WorkspaceRepository<Entity> {
|
): WorkspaceRepository<Entity> {
|
||||||
// find already created repository instance and return it if found
|
// find already created repository instance and return it if found
|
||||||
|
|
||||||
const repoFromMap = this.repositories.get(target);
|
const repoFromMap = this.repositories.get(target);
|
||||||
|
|
||||||
if (repoFromMap) {
|
if (repoFromMap) {
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
|
||||||
import { EntitySchema, Repository } from 'typeorm';
|
import { EntitySchema, Repository } from 'typeorm';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
@ -28,11 +29,19 @@ export class WorkspaceDatasourceFactory {
|
|||||||
workspaceId: string,
|
workspaceId: string,
|
||||||
workspaceMetadataVersion: string | null,
|
workspaceMetadataVersion: string | null,
|
||||||
): Promise<WorkspaceDataSource> {
|
): Promise<WorkspaceDataSource> {
|
||||||
const desiredWorkspaceMetadataVersion =
|
const logId = v4();
|
||||||
workspaceMetadataVersion ??
|
|
||||||
(await this.workspaceMetadataVersionService.getMetadataVersion(
|
console.time(`fetch in datasource factory ${logId}`);
|
||||||
|
|
||||||
|
const latestWorkspaceMetadataVersion =
|
||||||
|
await this.workspaceMetadataVersionService.getMetadataVersion(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
));
|
);
|
||||||
|
|
||||||
|
console.timeEnd(`fetch in datasource factory ${logId}`);
|
||||||
|
|
||||||
|
const desiredWorkspaceMetadataVersion =
|
||||||
|
workspaceMetadataVersion ?? latestWorkspaceMetadataVersion;
|
||||||
|
|
||||||
if (!desiredWorkspaceMetadataVersion) {
|
if (!desiredWorkspaceMetadataVersion) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
@ -40,11 +49,6 @@ export class WorkspaceDatasourceFactory {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const latestWorkspaceMetadataVersion =
|
|
||||||
await this.workspaceMetadataVersionService.getMetadataVersion(
|
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) {
|
if (latestWorkspaceMetadataVersion !== desiredWorkspaceMetadataVersion) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
|
`Workspace metadata version mismatch detected for workspace ${workspaceId}. Current version: ${latestWorkspaceMetadataVersion}. Desired version: ${desiredWorkspaceMetadataVersion}`,
|
||||||
@ -80,6 +84,9 @@ export class WorkspaceDatasourceFactory {
|
|||||||
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
|
const workspaceDataSource = await workspaceDataSourceCacheInstance.execute(
|
||||||
`${workspaceId}-${latestWorkspaceMetadataVersion}`,
|
`${workspaceId}-${latestWorkspaceMetadataVersion}`,
|
||||||
async () => {
|
async () => {
|
||||||
|
const logId = v4();
|
||||||
|
|
||||||
|
console.log('Creating workspace fresh data source...' + logId);
|
||||||
const dataSourceMetadata =
|
const dataSourceMetadata =
|
||||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
|
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceId(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -97,6 +104,7 @@ export class WorkspaceDatasourceFactory {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.time('create entity schema' + logId);
|
||||||
const cachedEntitySchemaOptions =
|
const cachedEntitySchemaOptions =
|
||||||
await this.workspaceCacheStorageService.getORMEntitySchema(
|
await this.workspaceCacheStorageService.getORMEntitySchema(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -122,7 +130,9 @@ export class WorkspaceDatasourceFactory {
|
|||||||
|
|
||||||
cachedEntitySchemas = entitySchemas;
|
cachedEntitySchemas = entitySchemas;
|
||||||
}
|
}
|
||||||
|
console.timeEnd('create entity schema' + logId);
|
||||||
|
|
||||||
|
console.time('create workspace data source' + logId);
|
||||||
const workspaceDataSource = new WorkspaceDataSource(
|
const workspaceDataSource = new WorkspaceDataSource(
|
||||||
{
|
{
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -146,7 +156,11 @@ export class WorkspaceDatasourceFactory {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.timeEnd('create workspace data source' + logId);
|
||||||
|
|
||||||
|
console.time('initialize workspace data source' + logId);
|
||||||
await workspaceDataSource.initialize();
|
await workspaceDataSource.initialize();
|
||||||
|
console.timeEnd('initialize workspace data source' + logId);
|
||||||
|
|
||||||
return workspaceDataSource;
|
return workspaceDataSource;
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Injectable, Type } from '@nestjs/common';
|
import { Injectable, Type } from '@nestjs/common';
|
||||||
|
|
||||||
import { ObjectLiteral } from 'typeorm';
|
import { ObjectLiteral } from 'typeorm';
|
||||||
|
import { v4 } from 'uuid';
|
||||||
|
|
||||||
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
|
import { WorkspaceDatasourceFactory } from 'src/engine/twenty-orm/factories/workspace-datasource.factory';
|
||||||
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
import { WorkspaceRepository } from 'src/engine/twenty-orm/repository/workspace.repository';
|
||||||
@ -36,12 +37,19 @@ export class TwentyORMGlobalManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const logId = v4();
|
||||||
|
|
||||||
|
console.time(`createDataSource in orm ${logId}`);
|
||||||
const workspaceDataSource = await this.workspaceDataSourceFactory.create(
|
const workspaceDataSource = await this.workspaceDataSourceFactory.create(
|
||||||
workspaceId,
|
workspaceId,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
return workspaceDataSource.getRepository<T>(objectMetadataName);
|
console.timeEnd(`createDataSource in orm ${logId}`);
|
||||||
|
|
||||||
|
const repository = workspaceDataSource.getRepository<T>(objectMetadataName);
|
||||||
|
|
||||||
|
return repository;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDataSourceForWorkspace(workspaceId: string) {
|
async getDataSourceForWorkspace(workspaceId: string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user