UBERF-7532: Bulk operations for triggers (#6023)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2024-07-09 00:04:05 +07:00
committed by GitHub
parent fa82ee1939
commit 4eac1927f0
49 changed files with 656 additions and 693 deletions
@@ -652,7 +652,7 @@ async function ActivityReferenceCreate (tx: TxCUD<Doc>, control: TriggerControl)
)
if (txes.length !== 0) {
await control.apply(txes, true)
await control.apply(txes)
}
return []
@@ -699,7 +699,7 @@ async function ActivityReferenceUpdate (tx: TxCUD<Doc>, control: TriggerControl)
)
if (txes.length !== 0) {
await control.apply(txes, true)
await control.apply(txes)
}
return []
@@ -723,7 +723,7 @@ async function ActivityReferenceRemove (tx: Tx, control: TriggerControl): Promis
const txes: Tx[] = await getRemoveActivityReferenceTxes(control, txFactory, ctx.objectId)
if (txes.length !== 0) {
await control.apply(txes, true)
await control.apply(txes)
}
}
+24 -13
View File
@@ -13,7 +13,9 @@
// limitations under the License.
//
import activity, { ActivityMessage, ActivityReference } from '@hcengineering/activity'
import chunter, { Channel, ChatMessage, chunterId, ChunterSpace, ThreadMessage } from '@hcengineering/chunter'
import { Person, PersonAccount } from '@hcengineering/contact'
import core, {
Account,
AttachedDoc,
@@ -38,14 +40,12 @@ import notification, { Collaborators, NotificationContent } from '@hcengineering
import { getMetadata, IntlString } from '@hcengineering/platform'
import serverCore, { TriggerControl } from '@hcengineering/server-core'
import {
createCollaboratorNotifications,
getDocCollaborators,
getMixinTx,
createCollaboratorNotifications
getMixinTx
} from '@hcengineering/server-notification-resources'
import { workbenchId } from '@hcengineering/workbench'
import { stripTags } from '@hcengineering/text'
import { Person, PersonAccount } from '@hcengineering/contact'
import activity, { ActivityMessage, ActivityReference } from '@hcengineering/activity'
import { workbenchId } from '@hcengineering/workbench'
import { NOTIFICATION_BODY_SIZE } from '@hcengineering/server-notification'
@@ -258,13 +258,24 @@ async function OnThreadMessageDeleted (tx: Tx, control: TriggerControl): Promise
* @public
*/
export async function ChunterTrigger (tx: TxCUD<Doc>, control: TriggerControl): Promise<Tx[]> {
const res = await Promise.all([
OnThreadMessageCreated(tx, control),
OnThreadMessageDeleted(tx, control),
OnCollaboratorsChanged(tx as TxMixin<Doc, Collaborators>, control),
OnChatMessageCreated(tx, control)
])
return res.flat()
const res: Tx[] = []
res.push(
...(await control.ctx.with('OnThreadMessageCreated', {}, async (ctx) => await OnThreadMessageCreated(tx, control)))
)
res.push(
...(await control.ctx.with('OnThreadMessageDeleted', {}, async (ctx) => await OnThreadMessageDeleted(tx, control)))
)
res.push(
...(await control.ctx.with(
'OnCollaboratorsChanged',
{},
async (ctx) => await OnCollaboratorsChanged(tx as TxMixin<Doc, Collaborators>, control)
))
)
res.push(
...(await control.ctx.with('OnChatMessageCreated', {}, async (ctx) => await OnChatMessageCreated(tx, control)))
)
return res
}
/**
@@ -393,7 +404,7 @@ async function OnChannelMembersChanged (tx: TxUpdateDoc<Channel>, control: Trigg
lastViewedTimestamp: tx.modifiedOn
})
await control.apply([createTx], true)
await control.apply([createTx])
} else {
const updateTx = control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
hidden: false,
@@ -284,7 +284,7 @@ async function createDocumentTrainingRequest (doc: ControlledDocument, control:
// Force space to make transaction persistent and raise notifications
resTx.space = core.space.Tx
await control.apply([resTx], true)
await control.apply([resTx])
return []
}
@@ -368,7 +368,7 @@ export async function OnDocPlannedEffectiveDateChanged (
if (tx.operations.plannedEffectiveDate === 0 && doc.controlledState === ControlledDocumentState.Approved) {
// Create with not derived tx factory in order for notifications to work
const factory = new TxFactory(control.txFactory.account)
await control.apply([makeDocEffective(doc, factory)], true)
await control.apply([makeDocEffective(doc, factory)])
}
return []
@@ -385,7 +385,7 @@ export async function OnDocApprovalRequestApproved (
// Create with not derived tx factory in order for notifications to work
const factory = new TxFactory(control.txFactory.account)
await control.apply([makeDocEffective(doc, factory)], true)
await control.apply([makeDocEffective(doc, factory)])
// make doc effective immediately
return []
+4 -3
View File
@@ -97,9 +97,10 @@ async function createUserInfo (acc: Ref<Account>, control: TriggerControl): Prom
query: { person }
}
],
[tx]
[tx],
'createUserInfo'
)
await control.apply([ptx], true)
await control.apply([ptx])
return []
}
@@ -114,7 +115,7 @@ async function removeUserInfo (acc: Ref<Account>, control: TriggerControl): Prom
const person = account.person
const infos = await control.findAll(love.class.ParticipantInfo, { person })
for (const info of infos) {
await control.apply([control.txFactory.createTxRemoveDoc(info._class, info.space, info._id)], true)
await control.apply([control.txFactory.createTxRemoveDoc(info._class, info.space, info._id)])
}
}
@@ -15,6 +15,7 @@
//
import activity, { ActivityMessage, DocUpdateMessage } from '@hcengineering/activity'
import { Analytics } from '@hcengineering/analytics'
import chunter, { ChatMessage } from '@hcengineering/chunter'
import contact, {
type AvatarInfo,
@@ -42,6 +43,7 @@ import core, {
RefTo,
Space,
Timestamp,
toIdMap,
Tx,
TxCollectionCUD,
TxCreateDoc,
@@ -75,12 +77,11 @@ import serverNotification, {
getPersonAccountById,
NOTIFICATION_BODY_SIZE
} from '@hcengineering/server-notification'
import serverView from '@hcengineering/server-view'
import { stripTags } from '@hcengineering/text'
import { encodeObjectURI } from '@hcengineering/view'
import { workbenchId } from '@hcengineering/workbench'
import webpush, { WebPushError } from 'web-push'
import { encodeObjectURI } from '@hcengineering/view'
import serverView from '@hcengineering/server-view'
import { Analytics } from '@hcengineering/analytics'
import { Content, NotifyParams, NotifyResult, UserInfo } from './types'
import {
@@ -396,14 +397,24 @@ export async function pushInboxNotifications (
hidden: false,
lastUpdateTimestamp: shouldUpdateTimestamp ? modifiedOn : undefined
})
await control.apply([createContextTx], true, [account.email])
await control.apply([createContextTx])
control.operationContext.derived.targets['docNotifyContext' + createContextTx._id] = (it) => {
if (it._id === createContextTx._id) {
return [account.email]
}
}
docNotifyContextId = createContextTx.objectId
} else {
if (shouldUpdateTimestamp && context.lastUpdateTimestamp !== modifiedOn) {
const updateTx = control.txFactory.createTxUpdateDoc(context._class, context.space, context._id, {
lastUpdateTimestamp: modifiedOn
})
await control.apply([updateTx], true, [account.email])
await control.apply([updateTx])
control.operationContext.derived.targets['docNotifyContext' + updateTx._id] = (it) => {
if (it._id === updateTx._id) {
return [account.email]
}
}
}
docNotifyContextId = context._id
}
@@ -636,7 +647,7 @@ async function sendPushToSubscription (
console.log('Cannot send push notification to', targetUser, err)
if (err instanceof WebPushError && err.body.includes('expired')) {
const tx = control.txFactory.createTxRemoveDoc(subscription._class, subscription.space, subscription._id)
await control.apply([tx], true)
await control.apply([tx])
}
}
}
@@ -1286,7 +1297,14 @@ async function applyUserTxes (
if (account !== undefined) {
cache.set(account._id, account)
await control.apply(txs, true, [account.email])
await control.apply(txs)
const m1 = toIdMap(txes)
control.operationContext.derived.targets.docNotifyContext = (it) => {
if (m1.has(it._id)) {
return [account.email]
}
}
}
}
@@ -99,7 +99,7 @@ async function OnRequestUpdate (tx: TxCollectionCUD<Doc, Request>, control: Trig
}
if (applyTxes.length > 0) {
await control.apply(applyTxes, true)
await control.apply(applyTxes)
}
return []
+5 -5
View File
@@ -107,7 +107,7 @@ export async function OnWorkSlotCreate (tx: Tx, control: TriggerControl): Promis
issue.collection,
innerTx
)
await control.apply([outerTx], true)
await control.apply([outerTx])
return []
}
}
@@ -153,7 +153,7 @@ export async function OnToDoRemove (tx: Tx, control: TriggerControl): Promise<Tx
issue.collection,
innerTx
)
await control.apply([outerTx], true)
await control.apply([outerTx])
return []
}
}
@@ -304,7 +304,7 @@ export async function OnToDoUpdate (tx: Tx, control: TriggerControl): Promise<Tx
if (funcs !== undefined) {
const func = await getResource(funcs.onDone)
const todoRes = await func(control, resEvents, todo)
await control.apply(todoRes, true)
await control.apply(todoRes)
}
return res
}
@@ -447,7 +447,7 @@ async function createIssueHandler (issue: Issue, control: TriggerControl): Promi
if (status.category === task.statusCategory.Active || status.category === task.statusCategory.ToDo) {
const tx = await getCreateToDoTx(issue, issue.assignee, control)
if (tx !== undefined) {
await control.apply([tx], true)
await control.apply([tx])
}
}
}
@@ -561,7 +561,7 @@ async function changeIssueStatusHandler (
if (todos.length === 0) {
const tx = await getCreateToDoTx(issue, issue.assignee, control)
if (tx !== undefined) {
await control.apply([tx], true)
await control.apply([tx])
}
}
}