mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-16 05:13:06 +00:00
parent
e3373f9278
commit
4efece2074
@ -13,32 +13,32 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import activity, { type ActivityMessage, type DocUpdateMessage } from '@hcengineering/activity'
|
||||
import core, {
|
||||
DOMAIN_TX,
|
||||
TxOperations,
|
||||
TxProcessor,
|
||||
generateId,
|
||||
type AttachedDoc,
|
||||
type Doc,
|
||||
type Domain,
|
||||
DOMAIN_TX,
|
||||
generateId,
|
||||
type Ref,
|
||||
type TxCollectionCUD,
|
||||
type TxCUD,
|
||||
TxOperations,
|
||||
TxProcessor
|
||||
type TxCollectionCUD
|
||||
} from '@hcengineering/core'
|
||||
import {
|
||||
tryMigrate,
|
||||
type MigrateOperation,
|
||||
type MigrationClient,
|
||||
type MigrationUpgradeClient,
|
||||
tryMigrate
|
||||
type MigrationUpgradeClient
|
||||
} from '@hcengineering/model'
|
||||
import notification, {
|
||||
notificationId,
|
||||
type ActivityInboxNotification,
|
||||
type DocNotifyContext,
|
||||
type DocUpdates,
|
||||
type DocUpdateTx,
|
||||
notificationId
|
||||
type DocUpdates
|
||||
} from '@hcengineering/notification'
|
||||
import activity, { type ActivityMessage, type DocUpdateMessage } from '@hcengineering/activity'
|
||||
|
||||
import { DOMAIN_NOTIFICATION } from './index'
|
||||
|
||||
@ -72,120 +72,157 @@ async function createSpace (client: MigrationUpgradeClient): Promise<void> {
|
||||
|
||||
async function getActivityMessages (
|
||||
client: MigrationClient,
|
||||
tx: DocUpdateTx,
|
||||
context: DocNotifyContext
|
||||
): Promise<ActivityMessage[]> {
|
||||
contexts: {
|
||||
context: DocNotifyContext
|
||||
txes: DocUpdateTx[]
|
||||
}[]
|
||||
): Promise<ActivityInboxNotification[]> {
|
||||
const result: ActivityInboxNotification[] = []
|
||||
const txes = contexts.flatMap((it) => it.txes)
|
||||
const docUpdateMessages = await client.find<DocUpdateMessage>(DOMAIN_ACTIVITY, {
|
||||
_class: activity.class.DocUpdateMessage,
|
||||
txId: tx._id,
|
||||
attachedTo: context.attachedTo
|
||||
txId: { $in: txes.map((it) => it._id) },
|
||||
attachedTo: { $in: contexts.map((it) => it.context.attachedTo) }
|
||||
})
|
||||
|
||||
if (docUpdateMessages.length > 0) {
|
||||
return docUpdateMessages
|
||||
}
|
||||
|
||||
const originTx = (await client.find<TxCUD<Doc>>(DOMAIN_TX, { _id: tx._id }))[0]
|
||||
|
||||
if (originTx === undefined) {
|
||||
return []
|
||||
}
|
||||
|
||||
const innerTx = TxProcessor.extractTx(originTx as TxCollectionCUD<Doc, AttachedDoc>) as TxCUD<Doc>
|
||||
|
||||
return (
|
||||
await client.find<ActivityMessage>(DOMAIN_ACTIVITY, {
|
||||
_id: innerTx.objectId as Ref<ActivityMessage>,
|
||||
attachedTo: context.attachedTo
|
||||
docUpdateMessages.forEach((message) => {
|
||||
const ctx = contexts.find((it) => it.context.attachedTo === message.attachedTo)
|
||||
if (ctx === undefined) {
|
||||
return
|
||||
}
|
||||
const tx = ctx.txes.find((it) => it._id === (message.txId as any))
|
||||
if (tx == null) {
|
||||
return
|
||||
}
|
||||
result.push({
|
||||
_id: generateId(),
|
||||
_class: notification.class.ActivityInboxNotification,
|
||||
space: ctx.context.space,
|
||||
user: ctx.context.user,
|
||||
isViewed: !tx.isNew,
|
||||
attachedTo: message._id,
|
||||
attachedToClass: message._class,
|
||||
docNotifyContext: ctx.context._id,
|
||||
title: tx.title,
|
||||
body: tx.body,
|
||||
intlParams: tx.intlParams,
|
||||
intlParamsNotLocalized: tx.intlParamsNotLocalized,
|
||||
modifiedOn: tx.modifiedOn,
|
||||
modifiedBy: tx.modifiedBy,
|
||||
createdOn: tx.modifiedOn,
|
||||
createdBy: tx.modifiedBy
|
||||
})
|
||||
})
|
||||
).filter(({ _class }) => client.hierarchy.isDerived(_class, activity.class.ActivityMessage))
|
||||
}
|
||||
|
||||
const originTx: TxCUD<Doc>[] = await client.find<TxCUD<Doc>>(DOMAIN_TX, { _id: { $in: txes.map((it) => it._id) } })
|
||||
|
||||
if (originTx.length === 0) {
|
||||
return result
|
||||
}
|
||||
|
||||
const innerTx = originTx.map((it) => TxProcessor.extractTx(it as TxCollectionCUD<Doc, AttachedDoc>) as TxCUD<Doc>)
|
||||
|
||||
;(
|
||||
await client.find<ActivityMessage>(DOMAIN_ACTIVITY, {
|
||||
_id: { $in: innerTx.map((it) => it.objectId as Ref<ActivityMessage>) }
|
||||
})
|
||||
)
|
||||
.filter(({ _class }) => client.hierarchy.isDerived(_class, activity.class.ActivityMessage))
|
||||
.forEach((message) => {
|
||||
const tx = originTx.find((q) => (TxProcessor.extractTx(q) as TxCUD<Doc>).objectId === message._id)
|
||||
if (tx == null) {
|
||||
return
|
||||
}
|
||||
|
||||
const ctx = contexts.find((it) => it.context.attachedTo === message.attachedTo)
|
||||
if (ctx === undefined) {
|
||||
return
|
||||
}
|
||||
const docTx = ctx.txes.find((it) => it._id === tx._id)
|
||||
if (docTx == null) {
|
||||
return
|
||||
}
|
||||
result.push({
|
||||
_id: generateId(),
|
||||
_class: notification.class.ActivityInboxNotification,
|
||||
space: ctx.context.space,
|
||||
user: ctx.context.user,
|
||||
isViewed: !docTx.isNew,
|
||||
attachedTo: message._id,
|
||||
attachedToClass: message._class,
|
||||
docNotifyContext: ctx.context._id,
|
||||
title: docTx.title,
|
||||
body: docTx.body,
|
||||
intlParams: docTx.intlParams,
|
||||
intlParamsNotLocalized: docTx.intlParamsNotLocalized,
|
||||
modifiedOn: docTx.modifiedOn,
|
||||
modifiedBy: docTx.modifiedBy,
|
||||
createdOn: docTx.modifiedOn,
|
||||
createdBy: docTx.modifiedBy
|
||||
})
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
async function getInboxNotifications (
|
||||
client: MigrationClient,
|
||||
tx: DocUpdateTx,
|
||||
context: DocNotifyContext
|
||||
): Promise<ActivityInboxNotification[]> {
|
||||
const messages = await getActivityMessages(client, tx, context)
|
||||
async function getInboxData (client: MigrationClient, docUpdates: DocUpdates[]): Promise<InboxData[]> {
|
||||
const toProcess = docUpdates.filter((it) => !it.hidden && client.hierarchy.hasClass(it.attachedToClass))
|
||||
|
||||
if (messages.length === 0) {
|
||||
return []
|
||||
}
|
||||
const contexts = toProcess.map((docUpdate) => {
|
||||
const newTxIndex = docUpdate.txes.findIndex(({ isNew }) => isNew)
|
||||
|
||||
return messages.map((message) => ({
|
||||
_id: generateId(),
|
||||
_class: notification.class.ActivityInboxNotification,
|
||||
space: context.space,
|
||||
user: context.user,
|
||||
isViewed: !tx.isNew,
|
||||
attachedTo: message._id,
|
||||
attachedToClass: message._class,
|
||||
docNotifyContext: context._id,
|
||||
title: tx.title,
|
||||
body: tx.body,
|
||||
intlParams: tx.intlParams,
|
||||
intlParamsNotLocalized: tx.intlParamsNotLocalized,
|
||||
modifiedOn: tx.modifiedOn,
|
||||
modifiedBy: tx.modifiedBy,
|
||||
createdOn: tx.modifiedOn,
|
||||
createdBy: tx.modifiedBy
|
||||
const context: DocNotifyContext = {
|
||||
_id: docUpdate._id,
|
||||
_class: notification.class.DocNotifyContext,
|
||||
space: docUpdate.space,
|
||||
user: docUpdate.user,
|
||||
attachedTo: docUpdate.attachedTo,
|
||||
attachedToClass: docUpdate.attachedToClass,
|
||||
hidden: docUpdate.hidden,
|
||||
lastViewedTimestamp: newTxIndex !== -1 ? docUpdate.txes[newTxIndex - 1]?.modifiedOn : docUpdate.lastTxTime,
|
||||
lastUpdateTimestamp: docUpdate.lastTxTime,
|
||||
modifiedBy: docUpdate.modifiedBy,
|
||||
modifiedOn: docUpdate.modifiedOn,
|
||||
createdBy: docUpdate.createdBy,
|
||||
createdOn: docUpdate.createdOn
|
||||
}
|
||||
|
||||
return {
|
||||
context,
|
||||
txes: docUpdate.txes
|
||||
}
|
||||
})
|
||||
|
||||
const notifications = await getActivityMessages(client, contexts)
|
||||
return contexts.map((it) => ({
|
||||
context: it.context,
|
||||
notifications: notifications.filter((nit) => nit.docNotifyContext === it.context._id)
|
||||
}))
|
||||
}
|
||||
|
||||
async function getInboxData (client: MigrationClient, docUpdate: DocUpdates): Promise<InboxData | undefined> {
|
||||
if (docUpdate.hidden) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!client.hierarchy.hasClass(docUpdate.attachedToClass)) {
|
||||
console.log('cannot find class: ', docUpdate.attachedToClass)
|
||||
return
|
||||
}
|
||||
|
||||
const { txes } = docUpdate
|
||||
const newTxIndex = txes.findIndex(({ isNew }) => isNew)
|
||||
|
||||
const context: DocNotifyContext = {
|
||||
_id: docUpdate._id,
|
||||
_class: notification.class.DocNotifyContext,
|
||||
space: docUpdate.space,
|
||||
user: docUpdate.user,
|
||||
attachedTo: docUpdate.attachedTo,
|
||||
attachedToClass: docUpdate.attachedToClass,
|
||||
hidden: docUpdate.hidden,
|
||||
lastViewedTimestamp: newTxIndex !== -1 ? txes[newTxIndex - 1]?.modifiedOn : docUpdate.lastTxTime,
|
||||
lastUpdateTimestamp: docUpdate.lastTxTime,
|
||||
modifiedBy: docUpdate.modifiedBy,
|
||||
modifiedOn: docUpdate.modifiedOn,
|
||||
createdBy: docUpdate.createdBy,
|
||||
createdOn: docUpdate.createdOn
|
||||
}
|
||||
|
||||
const notifications = (await Promise.all(txes.map((tx) => getInboxNotifications(client, tx, context)))).flat()
|
||||
|
||||
return {
|
||||
context,
|
||||
notifications
|
||||
}
|
||||
}
|
||||
|
||||
async function migrateInboxNotifications (client: MigrationClient): Promise<void> {
|
||||
let processing = 0
|
||||
while (true) {
|
||||
const docUpdates = await client.find<DocUpdates>(
|
||||
DOMAIN_NOTIFICATION,
|
||||
{
|
||||
_class: notification.class.DocUpdates
|
||||
},
|
||||
{ limit: 500 }
|
||||
{ limit: 1000 }
|
||||
)
|
||||
|
||||
console.log('notifications processing:', processing)
|
||||
|
||||
if (docUpdates.length === 0) {
|
||||
return
|
||||
}
|
||||
|
||||
const data: InboxData[] = (
|
||||
await Promise.all(docUpdates.map((docUpdate) => getInboxData(client, docUpdate)))
|
||||
).filter((data): data is InboxData => data !== undefined)
|
||||
processing += docUpdates.length
|
||||
|
||||
const data: InboxData[] = (await getInboxData(client, docUpdates)).filter(
|
||||
(data): data is InboxData => data !== undefined
|
||||
)
|
||||
|
||||
await client.deleteMany(DOMAIN_NOTIFICATION, { _id: { $in: docUpdates.map(({ _id }) => _id) } })
|
||||
await client.create(
|
||||
|
@ -113,7 +113,7 @@ async function createDocUpdateMessages (client: MigrationClient): Promise<void>
|
||||
async function generateFor (_class: Ref<Class<Doc>>, documents: MigrationIterator<Doc>): Promise<void> {
|
||||
const classNotFound = new Set<string>()
|
||||
while (true) {
|
||||
const docs = await documents.next(50)
|
||||
const docs = await documents.next(100)
|
||||
|
||||
if (docs == null || docs.length === 0) {
|
||||
break
|
||||
|
Loading…
Reference in New Issue
Block a user