[TSK-779] Use txMatch (#3101)

Signed-off-by: Ruslan Bayandinov <wazsone@ya.ru>
This commit is contained in:
Ruslan Bayandinov 2023-05-03 18:03:36 +04:00 committed by GitHub
parent 8c16a542ce
commit cf1e8b284f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 143 additions and 117 deletions

View File

@ -25,6 +25,7 @@
"@rushstack/heft": "^0.47.9"
},
"dependencies": {
"@hcengineering/attachment": "^0.6.4",
"@hcengineering/core": "^0.6.23",
"@hcengineering/model": "^0.6.2",
"@hcengineering/platform": "^0.6.8",

View File

@ -16,6 +16,7 @@
import { Builder } from '@hcengineering/model'
import attachment from '@hcengineering/attachment'
import core from '@hcengineering/core'
import serverAttachment from '@hcengineering/server-attachment'
import serverCore from '@hcengineering/server-core'
@ -24,6 +25,11 @@ export { serverAttachmentId } from '@hcengineering/server-attachment'
export function createModel (builder: Builder): void {
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverAttachment.trigger.OnAttachmentDelete
trigger: serverAttachment.trigger.OnAttachmentDelete,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': attachment.class.Attachment,
'tx._class': core.class.TxRemoveDoc
}
})
}

View File

@ -41,11 +41,19 @@ export function createModel (builder: Builder): void {
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverContact.trigger.OnContactDelete
trigger: serverContact.trigger.OnContactDelete,
txMatch: {
objectClass: contact.class.Contact,
_class: core.class.TxRemoveDoc
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverContact.trigger.OnChannelUpdate
trigger: serverContact.trigger.OnChannelUpdate,
txMatch: {
objectClass: contact.class.Channel,
_class: core.class.TxUpdateDoc
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {

View File

@ -26,6 +26,7 @@
},
"dependencies": {
"@hcengineering/core": "^0.6.23",
"@hcengineering/gmail": "^0.6.8",
"@hcengineering/model": "^0.6.2",
"@hcengineering/contact": "^0.6.14",
"@hcengineering/platform": "^0.6.8",

View File

@ -17,6 +17,7 @@ import { Builder } from '@hcengineering/model'
import contact from '@hcengineering/contact'
import core, { Class, Doc } from '@hcengineering/core'
import gmail from '@hcengineering/gmail'
import serverCore, { ObjectDDParticipant } from '@hcengineering/server-core'
import serverGmail from '@hcengineering/server-gmail'
export { serverGmailId } from '@hcengineering/server-gmail'
@ -32,6 +33,11 @@ export function createModel (builder: Builder): void {
)
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverGmail.trigger.OnMessageCreate
trigger: serverGmail.trigger.OnMessageCreate,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': gmail.class.Message,
'tx._class': core.class.TxCreateDoc
}
})
}

View File

@ -25,23 +25,48 @@ export { serverHrId } from '@hcengineering/server-hr'
export function createModel (builder: Builder): void {
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverHr.trigger.OnDepartmentStaff
trigger: serverHr.trigger.OnDepartmentStaff,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': hr.mixin.Staff,
'tx._class': core.class.TxMixin
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverHr.trigger.OnRequestCreate
trigger: serverHr.trigger.OnRequestCreate,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': hr.class.Request,
'tx._class': core.class.TxCreateDoc
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverHr.trigger.OnRequestUpdate
trigger: serverHr.trigger.OnRequestUpdate,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': hr.class.Request,
'tx._class': core.class.TxUpdateDoc
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverHr.trigger.OnRequestRemove
trigger: serverHr.trigger.OnRequestRemove,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': hr.class.Request,
'tx._class': core.class.TxRemoveDoc
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverHr.trigger.OnPublicHolidayCreate
trigger: serverHr.trigger.OnPublicHolidayCreate,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': hr.class.PublicHoliday,
'tx._class': core.class.TxCreateDoc
}
})
builder.mixin(hr.class.Request, core.class.Class, serverNotification.mixin.HTMLPresenter, {

View File

@ -60,10 +60,18 @@ export function createModel (builder: Builder): void {
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverNotification.trigger.OnAttributeCreate
trigger: serverNotification.trigger.OnAttributeCreate,
txMatch: {
objectClass: core.class.Attribute,
_class: core.class.TxCreateDoc
}
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverNotification.trigger.OnAttributeUpdate
trigger: serverNotification.trigger.OnAttributeUpdate,
txMatch: {
objectClass: core.class.Attribute,
_class: core.class.TxUpdateDoc
}
})
}

View File

@ -30,6 +30,7 @@
"@hcengineering/contact": "^0.6.14",
"@hcengineering/platform": "^0.6.8",
"@hcengineering/server-telegram": "^0.6.0",
"@hcengineering/server-core": "^0.6.1"
"@hcengineering/server-core": "^0.6.1",
"@hcengineering/telegram": "^0.6.7"
}
}

View File

@ -19,6 +19,7 @@ import contact from '@hcengineering/contact'
import core, { Class, Doc } from '@hcengineering/core'
import serverCore, { ObjectDDParticipant } from '@hcengineering/server-core'
import serverTelegram from '@hcengineering/server-telegram'
import telegram from '@hcengineering/telegram'
export { serverTelegramId } from '@hcengineering/server-telegram'
@ -33,6 +34,11 @@ export function createModel (builder: Builder): void {
)
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverTelegram.trigger.OnMessageCreate
trigger: serverTelegram.trigger.OnMessageCreate,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx.objectClass': telegram.class.Message,
'tx._class': core.class.TxCreateDoc
}
})
}

View File

@ -37,7 +37,11 @@ export function createModel (builder: Builder): void {
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverTracker.trigger.OnComponentRemove
trigger: serverTracker.trigger.OnComponentRemove,
txMatch: {
_class: core.class.TxCollectionCUD,
'tx._class': core.class.TxCreateDoc
}
})
builder.mixin(

View File

@ -15,9 +15,8 @@
//
import type { Attachment } from '@hcengineering/attachment'
import attachment from '@hcengineering/attachment'
import type { Doc, Ref, Tx, TxRemoveDoc } from '@hcengineering/core'
import core, { TxProcessor } from '@hcengineering/core'
import { TxProcessor } from '@hcengineering/core'
import type { TriggerControl } from '@hcengineering/server-core'
/**
@ -27,16 +26,7 @@ export async function OnAttachmentDelete (
tx: Tx,
{ findAll, hierarchy, fulltextFx, storageFx, removedMap }: TriggerControl
): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (actualTx._class !== core.class.TxRemoveDoc) {
return []
}
const rmTx = actualTx as TxRemoveDoc<Attachment>
if (!hierarchy.isDerived(rmTx.objectClass, attachment.class.Attachment)) {
return []
}
const rmTx = TxProcessor.extractTx(tx) as TxRemoveDoc<Attachment>
// Obtain document being deleted.
const attach = removedMap.get(rmTx.objectId) as Attachment

View File

@ -51,16 +51,8 @@ export async function OnContactDelete (
tx: Tx,
{ findAll, hierarchy, storageFx, removedMap, txFactory }: TriggerControl
): Promise<Tx[]> {
if (tx._class !== core.class.TxRemoveDoc) {
return []
}
const rmTx = tx as TxRemoveDoc<Contact>
if (!hierarchy.isDerived(rmTx.objectClass, contact.class.Contact)) {
return []
}
const removeContact = removedMap.get(rmTx.objectId) as Contact
if (removeContact === undefined) {
return []
@ -322,16 +314,8 @@ export async function OnEmployeeUpdate (tx: Tx, control: TriggerControl): Promis
* @public
*/
export async function OnChannelUpdate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
if (tx._class !== core.class.TxUpdateDoc) {
return []
}
const uTx = tx as TxUpdateDoc<Channel>
if (!control.hierarchy.isDerived(uTx.objectClass, contact.class.Channel)) {
return []
}
const result: Tx[] = []
if (uTx.operations.$inc?.items !== undefined) {

View File

@ -14,7 +14,7 @@
//
import contact, { Channel } from '@hcengineering/contact'
import core, {
import {
Class,
Doc,
DocumentQuery,
@ -57,16 +57,9 @@ export async function FindMessages (
*/
export async function OnMessageCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const res: Tx[] = []
const actualTx = TxProcessor.extractTx(tx)
if (actualTx._class !== core.class.TxCreateDoc) {
return []
}
const createTx = tx as TxCreateDoc<Message>
if (!control.hierarchy.isDerived(createTx.objectClass, gmail.class.Message)) {
return []
}
const message = TxProcessor.createDoc2Doc<Message>(createTx)
const channel = (await control.findAll(contact.class.Channel, { _id: message.attachedTo }, { limit: 1 }))[0]

View File

@ -116,14 +116,7 @@ function getTxes (
* @public
*/
export async function OnDepartmentStaff (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (core.class.TxMixin !== actualTx._class) {
return []
}
const ctx = actualTx as TxMixin<Employee, Staff>
if (ctx.mixin !== hr.mixin.Staff) {
return []
}
const ctx = TxProcessor.extractTx(tx) as TxMixin<Employee, Staff>
const targetAccount = (
await control.modelDb.findAll(contact.class.EmployeeAccount, {
@ -252,14 +245,7 @@ async function getEmailNotification (
* @public
*/
export async function OnRequestCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (core.class.TxCreateDoc !== actualTx._class) {
return []
}
const ctx = actualTx as TxCreateDoc<Request>
if (ctx.objectClass !== hr.class.Request) {
return []
}
const ctx = TxProcessor.extractTx(tx) as TxCreateDoc<Request>
const sender = await getEmployeeAccountById(ctx.modifiedBy, control)
if (sender === undefined) return []
@ -279,14 +265,7 @@ export async function OnRequestCreate (tx: Tx, control: TriggerControl): Promise
* @public
*/
export async function OnRequestUpdate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (core.class.TxUpdateDoc !== actualTx._class) {
return []
}
const ctx = actualTx as TxUpdateDoc<Request>
if (ctx.objectClass !== hr.class.Request) {
return []
}
const ctx = TxProcessor.extractTx(tx) as TxUpdateDoc<Request>
const sender = await getEmployeeAccountById(ctx.modifiedBy, control)
if (sender === undefined) return []
@ -307,14 +286,7 @@ export async function OnRequestUpdate (tx: Tx, control: TriggerControl): Promise
* @public
*/
export async function OnRequestRemove (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (core.class.TxRemoveDoc !== actualTx._class) {
return []
}
const ctx = actualTx as TxCreateDoc<Request>
if (ctx.objectClass !== hr.class.Request) {
return []
}
const ctx = TxProcessor.extractTx(tx) as TxCreateDoc<Request>
const sender = await getEmployeeAccountById(ctx.modifiedBy, control)
if (sender === undefined) return []
@ -371,14 +343,7 @@ export async function RequestTextPresenter (doc: Doc, control: TriggerControl):
* @public
*/
export async function OnPublicHolidayCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (core.class.TxCreateDoc !== actualTx._class) {
return []
}
const ctx = actualTx as TxCreateDoc<PublicHoliday>
if (ctx.objectClass !== hr.class.PublicHoliday) {
return []
}
const ctx = TxProcessor.extractTx(tx) as TxCreateDoc<PublicHoliday>
const sender = await getEmployeeAccountById(ctx.modifiedBy, control)
if (sender === undefined) return []

View File

@ -756,10 +756,7 @@ export async function isUserEmployeeInFieldValue (
* @public
*/
export async function OnAttributeCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
if (tx._class !== core.class.TxCreateDoc) return []
const ctx = tx as TxCreateDoc<AnyAttribute>
if (ctx.objectClass !== core.class.Attribute) return []
const attribute = TxProcessor.createDoc2Doc(ctx)
const attribute = TxProcessor.createDoc2Doc(tx as TxCreateDoc<AnyAttribute>)
const group = (
await control.modelDb.findAll(notification.class.NotificationGroup, { objectClass: attribute.attributeOf })
)[0]
@ -795,9 +792,7 @@ export async function OnAttributeCreate (tx: Tx, control: TriggerControl): Promi
* @public
*/
export async function OnAttributeUpdate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
if (tx._class !== core.class.TxUpdateDoc) return []
const ctx = tx as TxUpdateDoc<AnyAttribute>
if (ctx.objectClass !== core.class.Attribute) return []
if (ctx.operations.hidden === undefined) return []
const type = (await control.findAll(notification.class.NotificationType, { attribute: ctx.objectId }))[0]
if (type === undefined) return []

View File

@ -14,7 +14,7 @@
//
import contact, { Channel } from '@hcengineering/contact'
import core, {
import {
Class,
Doc,
DocumentQuery,
@ -57,18 +57,8 @@ export async function FindMessages (
*/
export async function OnMessageCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const res: Tx[] = []
const actualTx = TxProcessor.extractTx(tx)
if (actualTx._class !== core.class.TxCreateDoc) {
return []
}
const createTx = tx as TxCreateDoc<TelegramMessage>
if (!control.hierarchy.isDerived(createTx.objectClass, telegram.class.Message)) {
return []
}
const message = TxProcessor.createDoc2Doc<TelegramMessage>(createTx)
const message = TxProcessor.createDoc2Doc<TelegramMessage>(tx as TxCreateDoc<TelegramMessage>)
const channel = (await control.findAll(contact.class.Channel, { _id: message.attachedTo }, { limit: 1 }))[0]
if (channel !== undefined) {
if (channel.lastMessage === undefined || channel.lastMessage < message.sendOn) {

View File

@ -73,12 +73,7 @@ export async function issueTextPresenter (doc: Doc, control: TriggerControl): Pr
* @public
*/
export async function OnComponentRemove (tx: Tx, control: TriggerControl): Promise<Tx[]> {
const actualTx = TxProcessor.extractTx(tx)
if (actualTx._class !== core.class.TxRemoveDoc) {
return []
}
const ctx = actualTx as TxUpdateDoc<Component>
const ctx = TxProcessor.extractTx(tx) as TxUpdateDoc<Component>
const issues = await control.findAll(tracker.class.Issue, {
component: ctx.objectId

View File

@ -762,7 +762,7 @@ export async function createServerStorage (
options: ServerStorageOptions
): Promise<ServerStorage> {
const hierarchy = new Hierarchy()
const triggers = new Triggers()
const triggers = new Triggers(hierarchy)
const adapters = new Map<string, DbAdapter>()
const modelDb = new ModelDb(hierarchy)

View File

@ -24,7 +24,10 @@ import core, {
AttachedDoc,
DocumentQuery,
matchQuery,
TxFactory
TxFactory,
Hierarchy,
Class,
Obj
} from '@hcengineering/core'
import { getResource } from '@hcengineering/platform'
@ -38,6 +41,8 @@ import serverCore from './plugin'
export class Triggers {
private readonly triggers: [DocumentQuery<Tx> | undefined, TriggerFunc][] = []
constructor (protected readonly hierarchy: Hierarchy) {}
async tx (tx: Tx): Promise<void> {
if (tx._class === core.class.TxCollectionCUD) {
tx = (tx as TxCollectionCUD<Doc, AttachedDoc>).tx
@ -56,9 +61,52 @@ export class Triggers {
async apply (account: Ref<Account>, tx: Tx, ctrl: Omit<TriggerControl, 'txFactory'>): Promise<Tx[]> {
const control = { ...ctrl, txFactory: new TxFactory(account, true) }
const derived = this.triggers
.filter(([query]) => query === undefined || matchQuery([tx], query, core.class.Tx, control.hierarchy).length > 0)
.filter(([query]) => {
if (query === undefined) {
return true
}
this.addDerived(query, 'objectClass')
this.addDerived(query, 'tx.objectClass')
return matchQuery([tx], query, core.class.Tx, control.hierarchy).length > 0
})
.map(([, trigger]) => trigger(tx, control))
const result = await Promise.all(derived)
return result.flatMap((x) => x)
}
private addDerived (q: DocumentQuery<Tx>, key: string): void {
if (q[key] === undefined) {
return
}
if (typeof q[key] === 'string') {
const descendants = this.hierarchy.getDescendants(q[key])
q[key] = {
$in: [...(q[key].$in ?? []), ...descendants]
}
} else {
if (Array.isArray(q[key].$in)) {
const oldIn = q[key].$in
const newIn = new Set(oldIn)
q[key].$in.forEach((element: Ref<Class<Obj>>) => {
const descendants = this.hierarchy.getDescendants(element)
descendants.forEach((d) => newIn.add(d))
})
q[key].$in = Array.from(newIn.values())
}
if (Array.isArray(q[key].$nin)) {
const oldNin = q[key].$nin
const newNin = new Set(oldNin)
q[key].$nin.forEach((element: Ref<Class<Obj>>) => {
const descendants = this.hierarchy.getDescendants(element)
descendants.forEach((d) => newNin.add(d))
})
q[key].$nin = Array.from(newNin.values())
}
if (q[key].$ne !== undefined) {
const descendants = this.hierarchy.getDescendants(q[key].$ne)
delete q[key].$ne
q[key].$nin = [...(q[key].$nin ?? []), ...descendants]
}
}
}
}