4020 timebox improve performances on messages read (#4140)
* adding console.time to monitor queries time * improve query by removing unnecessary JOIN * improve queries by removing unnecessary JOINs * improve queries by removing unnecessary JOINs * remove console.time * remove logs * use groupBy from lodash * modify SELECT * Revert "use groupBy from lodash" This reverts commit 852fd3c19367dff79147490b7eaa9fd348d101a1. * use WorkspaceDataSourceModule
This commit is contained in:
@ -2,11 +2,10 @@ import { Module } from '@nestjs/common';
|
|||||||
|
|
||||||
import { TimelineMessagingResolver } from 'src/core/messaging/timeline-messaging.resolver';
|
import { TimelineMessagingResolver } from 'src/core/messaging/timeline-messaging.resolver';
|
||||||
import { TimelineMessagingService } from 'src/core/messaging/timeline-messaging.service';
|
import { TimelineMessagingService } from 'src/core/messaging/timeline-messaging.service';
|
||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { WorkspaceDataSourceModule } from 'src/workspace/workspace-datasource/workspace-datasource.module';
|
||||||
import { DataSourceModule } from 'src/metadata/data-source/data-source.module';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [DataSourceModule, TypeORMModule],
|
imports: [WorkspaceDataSourceModule],
|
||||||
exports: [],
|
exports: [],
|
||||||
providers: [TimelineMessagingResolver, TimelineMessagingService],
|
providers: [TimelineMessagingResolver, TimelineMessagingService],
|
||||||
})
|
})
|
||||||
|
|||||||
@ -2,8 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||||||
|
|
||||||
import { TIMELINE_THREADS_DEFAULT_PAGE_SIZE } from 'src/core/messaging/constants/messaging.constants';
|
import { TIMELINE_THREADS_DEFAULT_PAGE_SIZE } from 'src/core/messaging/constants/messaging.constants';
|
||||||
import { TimelineThreadsWithTotal } from 'src/core/messaging/dtos/timeline-threads-with-total.dto';
|
import { TimelineThreadsWithTotal } from 'src/core/messaging/dtos/timeline-threads-with-total.dto';
|
||||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
import { WorkspaceDataSourceService } from 'src/workspace/workspace-datasource/workspace-datasource.service';
|
||||||
import { DataSourceService } from 'src/metadata/data-source/data-source.service';
|
|
||||||
|
|
||||||
type TimelineThreadParticipant = {
|
type TimelineThreadParticipant = {
|
||||||
personId: string;
|
personId: string;
|
||||||
@ -18,8 +17,7 @@ type TimelineThreadParticipant = {
|
|||||||
@Injectable()
|
@Injectable()
|
||||||
export class TimelineMessagingService {
|
export class TimelineMessagingService {
|
||||||
constructor(
|
constructor(
|
||||||
private readonly dataSourceService: DataSourceService,
|
private readonly workspaceDataSourceService: WorkspaceDataSourceService,
|
||||||
private readonly typeORMService: TypeORMService,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getMessagesFromPersonIds(
|
async getMessagesFromPersonIds(
|
||||||
@ -30,13 +28,8 @@ export class TimelineMessagingService {
|
|||||||
): Promise<TimelineThreadsWithTotal> {
|
): Promise<TimelineThreadsWithTotal> {
|
||||||
const offset = (page - 1) * pageSize;
|
const offset = (page - 1) * pageSize;
|
||||||
|
|
||||||
const dataSourceMetadata =
|
const dataSourceSchema =
|
||||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const workspaceDataSource =
|
|
||||||
await this.typeORMService.connectToDataSource(dataSourceMetadata);
|
|
||||||
|
|
||||||
const messageThreads:
|
const messageThreads:
|
||||||
| {
|
| {
|
||||||
@ -46,29 +39,26 @@ export class TimelineMessagingService {
|
|||||||
lastMessageBody: string;
|
lastMessageBody: string;
|
||||||
rowNumber: number;
|
rowNumber: number;
|
||||||
}[]
|
}[]
|
||||||
| undefined = await workspaceDataSource?.query(
|
| undefined = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
`
|
`
|
||||||
SELECT *
|
SELECT id,
|
||||||
|
"lastMessageReceivedAt",
|
||||||
|
"lastMessageId",
|
||||||
|
"lastMessageBody"
|
||||||
FROM
|
FROM
|
||||||
(SELECT "messageThread".id,
|
(SELECT message."messageThreadId" AS id,
|
||||||
MAX(message."receivedAt") AS "lastMessageReceivedAt",
|
MAX(message."receivedAt") AS "lastMessageReceivedAt",
|
||||||
message.id AS "lastMessageId",
|
message.id AS "lastMessageId",
|
||||||
message.text AS "lastMessageBody",
|
message.text AS "lastMessageBody",
|
||||||
ROW_NUMBER() OVER (PARTITION BY "messageThread".id ORDER BY MAX(message."receivedAt") DESC) AS "rowNumber"
|
ROW_NUMBER() OVER (PARTITION BY message."messageThreadId" ORDER BY MAX(message."receivedAt") DESC) AS "rowNumber"
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."message" message
|
${dataSourceSchema}."message" message
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
${dataSourceMetadata.schema}."messageThread" "messageThread" ON "messageThread".id = message."messageThreadId"
|
${dataSourceSchema}."messageParticipant" "messageParticipant" ON "messageParticipant"."messageId" = message.id
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."messageParticipant" "messageParticipant" ON "messageParticipant"."messageId" = message.id
|
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."person" person ON person.id = "messageParticipant"."personId"
|
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."workspaceMember" "workspaceMember" ON "workspaceMember".id = "messageParticipant"."workspaceMemberId"
|
|
||||||
WHERE
|
WHERE
|
||||||
person.id = ANY($1)
|
"messageParticipant"."personId" = ANY($1)
|
||||||
GROUP BY
|
GROUP BY
|
||||||
"messageThread".id,
|
message."messageThreadId",
|
||||||
message.id
|
message.id
|
||||||
ORDER BY
|
ORDER BY
|
||||||
message."receivedAt" DESC
|
message."receivedAt" DESC
|
||||||
@ -79,6 +69,7 @@ export class TimelineMessagingService {
|
|||||||
OFFSET $3
|
OFFSET $3
|
||||||
`,
|
`,
|
||||||
[personIds, pageSize, offset],
|
[personIds, pageSize, offset],
|
||||||
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!messageThreads) {
|
if (!messageThreads) {
|
||||||
@ -97,22 +88,20 @@ export class TimelineMessagingService {
|
|||||||
id: string;
|
id: string;
|
||||||
subject: string;
|
subject: string;
|
||||||
}[]
|
}[]
|
||||||
| undefined = await workspaceDataSource?.query(
|
| undefined = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
`
|
`
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM
|
FROM
|
||||||
(SELECT
|
(SELECT
|
||||||
"messageThread".id,
|
message."messageThreadId" AS id,
|
||||||
message.subject,
|
message.subject,
|
||||||
ROW_NUMBER() OVER (PARTITION BY "messageThread".id ORDER BY MAX(message."receivedAt") ASC) AS "rowNumber"
|
ROW_NUMBER() OVER (PARTITION BY message."messageThreadId" ORDER BY MAX(message."receivedAt") ASC) AS "rowNumber"
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."message" message
|
${dataSourceSchema}."message" message
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."messageThread" "messageThread" ON "messageThread".id = message."messageThreadId"
|
|
||||||
WHERE
|
WHERE
|
||||||
"messageThread".id = ANY($1)
|
message."messageThreadId" = ANY($1)
|
||||||
GROUP BY
|
GROUP BY
|
||||||
"messageThread".id,
|
message."messageThreadId",
|
||||||
message.id
|
message.id
|
||||||
ORDER BY
|
ORDER BY
|
||||||
message."receivedAt" DESC
|
message."receivedAt" DESC
|
||||||
@ -121,6 +110,7 @@ export class TimelineMessagingService {
|
|||||||
"rowNumber" = 1
|
"rowNumber" = 1
|
||||||
`,
|
`,
|
||||||
[messageThreadIds],
|
[messageThreadIds],
|
||||||
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const numberOfMessagesInThread:
|
const numberOfMessagesInThread:
|
||||||
@ -128,21 +118,20 @@ export class TimelineMessagingService {
|
|||||||
id: string;
|
id: string;
|
||||||
numberOfMessagesInThread: number;
|
numberOfMessagesInThread: number;
|
||||||
}[]
|
}[]
|
||||||
| undefined = await workspaceDataSource?.query(
|
| undefined = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
"messageThread".id,
|
message."messageThreadId" AS id,
|
||||||
COUNT(message.id) AS "numberOfMessagesInThread"
|
COUNT(message.id) AS "numberOfMessagesInThread"
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."message" message
|
${dataSourceSchema}."message" message
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."messageThread" "messageThread" ON "messageThread".id = message."messageThreadId"
|
|
||||||
WHERE
|
WHERE
|
||||||
"messageThread".id = ANY($1)
|
message."messageThreadId" = ANY($1)
|
||||||
GROUP BY
|
GROUP BY
|
||||||
"messageThread".id
|
message."messageThreadId"
|
||||||
`,
|
`,
|
||||||
[messageThreadIds],
|
[messageThreadIds],
|
||||||
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const messageThreadsByMessageThreadId: {
|
const messageThreadsByMessageThreadId: {
|
||||||
@ -207,9 +196,9 @@ export class TimelineMessagingService {
|
|||||||
workspaceMemberAvatarUrl: string;
|
workspaceMemberAvatarUrl: string;
|
||||||
messageDisplayName: string;
|
messageDisplayName: string;
|
||||||
}[]
|
}[]
|
||||||
| undefined = await workspaceDataSource?.query(
|
| undefined = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
`
|
`
|
||||||
SELECT DISTINCT "messageThread".id,
|
SELECT DISTINCT message."messageThreadId" AS id,
|
||||||
message.id AS "messageId",
|
message.id AS "messageId",
|
||||||
message."receivedAt",
|
message."receivedAt",
|
||||||
message.text,
|
message.text,
|
||||||
@ -225,39 +214,36 @@ export class TimelineMessagingService {
|
|||||||
"workspaceMember"."avatarUrl" as "workspaceMemberAvatarUrl",
|
"workspaceMember"."avatarUrl" as "workspaceMemberAvatarUrl",
|
||||||
"messageParticipant"."displayName" as "messageDisplayName"
|
"messageParticipant"."displayName" as "messageDisplayName"
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."message" message
|
${dataSourceSchema}."message" message
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
${dataSourceMetadata.schema}."messageThread" "messageThread" ON "messageThread".id = message."messageThreadId"
|
(SELECT * FROM ${dataSourceSchema}."messageParticipant" WHERE "messageParticipant".role = 'from') "messageParticipant" ON "messageParticipant"."messageId" = message.id
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
(SELECT * FROM ${dataSourceMetadata.schema}."messageParticipant" WHERE "messageParticipant".role = 'from') "messageParticipant" ON "messageParticipant"."messageId" = message.id
|
${dataSourceSchema}."person" person ON person."id" = "messageParticipant"."personId"
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
${dataSourceMetadata.schema}."person" person ON person."id" = "messageParticipant"."personId"
|
${dataSourceSchema}."workspaceMember" "workspaceMember" ON "workspaceMember".id = "messageParticipant"."workspaceMemberId"
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."workspaceMember" "workspaceMember" ON "workspaceMember".id = "messageParticipant"."workspaceMemberId"
|
|
||||||
WHERE
|
WHERE
|
||||||
"messageThread".id = ANY($1)
|
message."messageThreadId" = ANY($1)
|
||||||
ORDER BY
|
ORDER BY
|
||||||
message."receivedAt" DESC
|
message."receivedAt" DESC
|
||||||
`,
|
`,
|
||||||
[messageThreadIds],
|
[messageThreadIds],
|
||||||
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalNumberOfThreads = await workspaceDataSource?.query(
|
const totalNumberOfThreads =
|
||||||
`
|
await this.workspaceDataSourceService.executeRawQuery(
|
||||||
SELECT COUNT(DISTINCT "messageThread".id)
|
`
|
||||||
|
SELECT COUNT(DISTINCT message."messageThreadId")
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."message" message
|
${dataSourceSchema}."message" message
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
${dataSourceMetadata.schema}."messageThread" "messageThread" ON "messageThread".id = message."messageThreadId"
|
${dataSourceSchema}."messageParticipant" "messageParticipant" ON "messageParticipant"."messageId" = message.id
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."messageParticipant" "messageParticipant" ON "messageParticipant"."messageId" = message.id
|
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."person" person ON person.id = "messageParticipant"."personId"
|
|
||||||
WHERE
|
WHERE
|
||||||
person.id = ANY($1)
|
"messageParticipant"."personId" = ANY($1)
|
||||||
`,
|
`,
|
||||||
[personIds],
|
[personIds],
|
||||||
);
|
workspaceId,
|
||||||
|
);
|
||||||
|
|
||||||
const threadParticipantsByThreadId: {
|
const threadParticipantsByThreadId: {
|
||||||
[key: string]: TimelineThreadParticipant[];
|
[key: string]: TimelineThreadParticipant[];
|
||||||
@ -322,23 +308,22 @@ export class TimelineMessagingService {
|
|||||||
id: string;
|
id: string;
|
||||||
visibility: 'metadata' | 'subject' | 'share_everything';
|
visibility: 'metadata' | 'subject' | 'share_everything';
|
||||||
}[]
|
}[]
|
||||||
| undefined = await workspaceDataSource?.query(
|
| undefined = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
"messageThread".id,
|
message."messageThreadId" AS id,
|
||||||
"messageChannel".visibility
|
"messageChannel".visibility
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."messageThread" "messageThread"
|
${dataSourceSchema}."message" message
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
${dataSourceMetadata.schema}."message" message ON "message"."messageThreadId" = "messageThread".id
|
${dataSourceSchema}."messageChannelMessageAssociation" "messageChannelMessageAssociation" ON "messageChannelMessageAssociation"."messageId" = message.id
|
||||||
LEFT JOIN
|
LEFT JOIN
|
||||||
${dataSourceMetadata.schema}."messageChannelMessageAssociation" "messageChannelMessageAssociation" ON "messageChannelMessageAssociation"."messageId" = message.id
|
${dataSourceSchema}."messageChannel" "messageChannel" ON "messageChannel".id = "messageChannelMessageAssociation"."messageChannelId"
|
||||||
LEFT JOIN
|
|
||||||
${dataSourceMetadata.schema}."messageChannel" "messageChannel" ON "messageChannel".id = "messageChannelMessageAssociation"."messageChannelId"
|
|
||||||
WHERE
|
WHERE
|
||||||
"messageThread".id = ANY($1)
|
message."messageThreadId" = ANY($1)
|
||||||
`,
|
`,
|
||||||
[messageThreadIds],
|
[messageThreadIds],
|
||||||
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const visibilityValues = ['metadata', 'subject', 'share_everything'];
|
const visibilityValues = ['metadata', 'subject', 'share_everything'];
|
||||||
@ -430,24 +415,20 @@ export class TimelineMessagingService {
|
|||||||
page: number = 1,
|
page: number = 1,
|
||||||
pageSize: number = TIMELINE_THREADS_DEFAULT_PAGE_SIZE,
|
pageSize: number = TIMELINE_THREADS_DEFAULT_PAGE_SIZE,
|
||||||
): Promise<TimelineThreadsWithTotal> {
|
): Promise<TimelineThreadsWithTotal> {
|
||||||
const dataSourceMetadata =
|
const dataSourceSchema =
|
||||||
await this.dataSourceService.getLastDataSourceMetadataFromWorkspaceIdOrFail(
|
this.workspaceDataSourceService.getSchemaName(workspaceId);
|
||||||
workspaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const workspaceDataSource =
|
const personIds = await this.workspaceDataSourceService.executeRawQuery(
|
||||||
await this.typeORMService.connectToDataSource(dataSourceMetadata);
|
|
||||||
|
|
||||||
const personIds = await workspaceDataSource?.query(
|
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
p."id"
|
p."id"
|
||||||
FROM
|
FROM
|
||||||
${dataSourceMetadata.schema}."person" p
|
${dataSourceSchema}."person" p
|
||||||
WHERE
|
WHERE
|
||||||
p."companyId" = $1
|
p."companyId" = $1
|
||||||
`,
|
`,
|
||||||
[companyId],
|
[companyId],
|
||||||
|
workspaceId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!personIds) {
|
if (!personIds) {
|
||||||
|
|||||||
Reference in New Issue
Block a user