Find message groups by messageId (#84)

Signed-off-by: Kristina Fefelova <kristin.fefelova@gmail.com>
This commit is contained in:
Kristina
2025-07-07 21:25:40 +04:00
committed by GitHub
parent 317a5cd35b
commit 41c511fffd
6 changed files with 91 additions and 56 deletions
+9 -1
View File
@@ -165,13 +165,21 @@ export function toLinkPreview (raw: LinkPreviewDb): LinkPreview {
}
export function toMessagesGroup (raw: MessagesGroupDb): MessagesGroup {
const patches =
raw.patches == null
? []
: raw.patches
.filter((it: any) => it.message_id != null)
.map(toPatch)
.sort((a, b) => a.created.getTime() - b.created.getTime())
return {
cardId: raw.card_id,
blobId: raw.blob_id,
fromDate: raw.from_date,
toDate: raw.to_date,
count: Number(raw.count),
patches: raw.patches == null ? [] : raw.patches.filter((it: any) => it.message_id != null).map(toPatch)
patches
}
}
+57 -31
View File
@@ -1027,33 +1027,53 @@ export class MessagesDb extends BaseDb {
// Find messages groups
async findMessagesGroups (params: FindMessagesGroupsParams): Promise<MessagesGroup[]> {
const select = `
SELECT mg.card_id,
mg.blob_id,
mg.from_date,
mg.to_date,
mg.count,
patches
FROM ${TableName.MessagesGroup} mg
CROSS JOIN LATERAL (
SELECT jsonb_agg(jsonb_build_object(
'message_id', p.message_id::text,
'type', p.type,
'data', p.data,
'creator', p.creator,
'created', p.created
) ORDER BY p.created) AS patches
FROM ${TableName.Patch} p
WHERE p.workspace_id = mg.workspace_id
AND p.card_id = mg.card_id
AND p.message_created BETWEEN mg.from_date AND mg.to_date
) sub`
const useMessageIdCte = params.messageId != null
const values: any[] = [this.workspace]
if (useMessageIdCte) values.push(params.messageId)
const cte = useMessageIdCte
? `
WITH msg_created AS (
SELECT card_id, created
FROM ${TableName.MessageCreated}
WHERE workspace_id = $1::uuid
AND message_id = $2::varchar
)
`
: ''
const select = `
${cte}
SELECT mg.card_id,
mg.blob_id,
mg.from_date,
mg.to_date,
mg.count,
patches
FROM ${TableName.MessagesGroup} mg
${useMessageIdCte ? 'JOIN msg_created mc ON mg.card_id = mc.card_id AND mc.created BETWEEN mg.from_date AND mg.to_date' : ''}
CROSS JOIN LATERAL (
SELECT jsonb_agg(jsonb_build_object(
'message_id', p.message_id::varchar,
'type', p.type,
'data', p.data,
'creator', p.creator,
'created', p.created
)) AS patches
FROM ${TableName.Patch} p
WHERE p.workspace_id = mg.workspace_id
AND p.card_id = mg.card_id
AND p.message_created BETWEEN mg.from_date AND mg.to_date
) sub
`
const { where, values: additionalValues } = this.buildMessagesGroupWhere(params, values.length + 1)
values.push(...additionalValues)
const { where, values } = this.buildMessagesGroupWhere(params)
const orderBy =
params.orderBy === 'toDate'
? `ORDER BY mg.to_date ${params.order === SortingOrder.Ascending ? 'ASC' : 'DESC'}`
: `ORDER BY mg.from_date ${params.order === SortingOrder.Ascending ? 'ASC' : 'DESC'}`
? `ORDER BY mg.to_date ${params.order === SortingOrder.Descending ? 'DESC' : 'ASC'}`
: `ORDER BY mg.from_date ${params.order === SortingOrder.Descending ? 'DESC' : 'ASC'}`
const limit = params.limit != null ? ` LIMIT ${params.limit}` : ''
const sql = [select, where, orderBy, limit].join(' ')
@@ -1062,14 +1082,17 @@ export class MessagesDb extends BaseDb {
return result.map((it: any) => toMessagesGroup(it))
}
buildMessagesGroupWhere (params: FindMessagesGroupsParams): {
where: string
values: any[]
} {
buildMessagesGroupWhere (
params: FindMessagesGroupsParams,
startIndex = 1
): {
where: string
values: any[]
} {
const where: string[] = ['mg.workspace_id = $1::uuid']
const values: any[] = [this.workspace]
const values: any[] = []
let index = 2
let index = startIndex
if (params.card != null) {
where.push(`mg.card_id = $${index++}::varchar`)
@@ -1099,7 +1122,10 @@ export class MessagesDb extends BaseDb {
where.push('sub.patches IS NOT NULL')
}
return { where: `WHERE ${where.join(' AND ')}`, values }
return {
where: where.length > 0 ? `WHERE ${where.join(' AND ')}` : '',
values
}
}
public async isMessageInDb (cardId: CardID, messageId: MessageID): Promise<boolean> {
@@ -318,7 +318,7 @@ export class NotificationContextsQuery implements PagedQuery<NotificationContext
return
}
await this.addContext(context)
this.addContext(context, this.result)
void this.notify()
}
@@ -457,7 +457,7 @@ export class NotificationContextsQuery implements PagedQuery<NotificationContext
await this.find({ id: notification.contextId, notifications: this.params.notifications, limit: 1 })
)[0]
if (newContext !== undefined) {
await this.addContext(newContext)
this.addContext(newContext, this.result)
void this.notify()
}
}
@@ -550,13 +550,11 @@ export class NotificationContextsQuery implements PagedQuery<NotificationContext
}
this.result.update(updated)
}
if (event.updates.lastNotify != null) {
this.result.sort((a, b) =>
this.params.order === SortingOrder.Descending
? (b.lastNotify?.getTime() ?? 0) - (a.lastNotify?.getTime() ?? 0)
: (a.lastNotify?.getTime() ?? 0) - (b.lastNotify?.getTime() ?? 0)
)
this.sort(this.result)
}
void this.notify()
}
@@ -601,20 +599,29 @@ export class NotificationContextsQuery implements PagedQuery<NotificationContext
return notifications.filter((it) => it.read === read)
}
private async addContext (context: NotificationContext): Promise<void> {
if (this.result instanceof Promise) this.result = await this.result
if (this.result.get(context.id) !== undefined) return
if (this.result.isTail()) {
private addContext (context: NotificationContext, result: QueryResult<NotificationContext>): void {
if (result.get(context.id) !== undefined) return
if (result.isTail()) {
if (this.params.order === SortingOrder.Ascending) {
this.result.push(context)
result.push(context)
} else {
this.result.unshift(context)
result.unshift(context)
}
}
if (this.params.limit != null && this.result.length > this.params.limit) {
this.result.pop()
if (this.params.limit != null && result.length > this.params.limit) {
result.pop()
}
this.sort(result)
}
private sort (result: QueryResult<NotificationContext>): void {
result.sort((a, b) =>
this.params.order === SortingOrder.Descending
? (b.lastNotify?.getTime() ?? 0) - (a.lastNotify?.getTime() ?? 0)
: (a.lastNotify?.getTime() ?? 0) - (b.lastNotify?.getTime() ?? 0)
)
}
private match (context: NotificationContext): boolean {
@@ -216,6 +216,7 @@ const FindMessagesParamsSchema = FindParamsSchema.extend({
}).strict()
const FindMessagesGroupsParamsSchema = FindParamsSchema.extend({
messageId: MessageIDSchema.optional(),
card: CardIDSchema.optional(),
blobId: BlobIDSchema.optional(),
patches: z.boolean().optional(),
+1 -9
View File
@@ -13,7 +13,7 @@
// limitations under the License.
//
import type { AccountID, MessageID, SocialID } from '@hcengineering/communication-types'
import type { AccountID, SocialID } from '@hcengineering/communication-types'
import { generateToken } from '@hcengineering/server-token'
import { systemAccountUuid } from '@hcengineering/core'
import { getClient as getAccountClient } from '@hcengineering/account-client'
@@ -47,11 +47,3 @@ export async function findAccount (ctx: TriggerCtx, socialString: SocialID): Pro
ctx.ctx.warn('Cannot find account', { socialString, err })
}
}
export function isExternalMessageId (messageId: MessageID): boolean {
return messageId.startsWith('e')
}
export function parseMessageIdDate (messageId: MessageID): Date | undefined {
return isExternalMessageId(messageId) ? undefined : new Date(Number(messageId))
}
+1
View File
@@ -52,6 +52,7 @@ export interface FindMessagesParams extends FindParams {
}
export interface FindMessagesGroupsParams extends FindParams {
messageId?: MessageID
card?: CardID
blobId?: BlobID
patches?: boolean