Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UBERF-7690: Trigger improvements #6340

Merged
merged 8 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
"ACCOUNT_PORT": "3000",
"FRONT_URL": "http://localhost:8080",
"outputCapture": "std",
"SES_URL": "http://localhost:8091",
"SES_URL": "",
"MINIO_ACCESS_KEY": "minioadmin",
"MINIO_SECRET_KEY": "minioadmin",
"MINIO_ENDPOINT": "localhost"
Expand Down
118 changes: 52 additions & 66 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
"compression-webpack-plugin": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
"fork-ts-checker-webpack-plugin": "~7.3.0",
"update-browserslist-db": "~1.0.11",
"browserslist": "4.21.5",
"update-browserslist-db": "^1.1.0",
"browserslist": "^4.23.3",
"typescript": "^5.3.3",
"ts-node": "^10.8.0",
"ts-node-dev": "^2.0.0",
Expand Down
4 changes: 2 additions & 2 deletions dev/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ services:
- LAST_NAME_FIRST=true
- ACCOUNTS_URL=http://localhost:3000
- BRANDING_PATH=/var/cfg/branding.json
- INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml
- INIT_WORKSPACE=onboarding
# - INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml
# - INIT_WORKSPACE=onboarding
restart: unless-stopped
collaborator:
image: hardcoreeng/collaborator
Expand Down
4 changes: 2 additions & 2 deletions dev/prod/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@
"compression-webpack-plugin": "^10.0.0",
"html-webpack-plugin": "^5.5.0",
"fork-ts-checker-webpack-plugin": "~7.3.0",
"update-browserslist-db": "~1.0.11",
"browserslist": "4.21.5",
"update-browserslist-db": "^1.1.0",
"browserslist": "^4.23.3",
"esbuild": "^0.20.0",
"esbuild-loader": "^4.0.3",
"typescript": "^5.3.3",
Expand Down
10 changes: 5 additions & 5 deletions models/contact/src/migration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ async function createEmployeeEmail (client: TxOperations): Promise<void> {
).filter((it) => it.provider === contact.channelProvider.Email)
const channelsMap = new Map(channels.map((p) => [p.attachedTo, p]))
for (const employee of employees) {
const acc = await client.findOne(contact.class.PersonAccount, { person: employee._id })
if (acc === undefined) continue
const acc = client.getModel().getAccountByPersonId(employee._id)
if (acc.length === 0) continue
const current = channelsMap.get(employee._id)
if (current === undefined) {
await client.addCollection(
Expand All @@ -49,13 +49,13 @@ async function createEmployeeEmail (client: TxOperations): Promise<void> {
'channels',
{
provider: contact.channelProvider.Email,
value: acc.email.trim()
value: acc[0].email.trim()
},
undefined,
employee.modifiedOn
)
} else if (current.value !== acc.email.trim()) {
await client.update(current, { value: acc.email.trim() }, false, current.modifiedOn)
} else if (current.value !== acc[0].email.trim()) {
await client.update(current, { value: acc[0].email.trim() }, false, current.modifiedOn)
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions models/server-activity/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import core from '@hcengineering/core/src/component'
import serverActivity from '@hcengineering/server-activity'
import serverNotification from '@hcengineering/server-notification'
import activity from '@hcengineering/activity'
import notification from '@hcengineering/notification'

export { activityServerOperation } from './migration'
export { serverActivityId } from '@hcengineering/server-activity'
Expand All @@ -43,6 +44,9 @@ export function createModel (builder: Builder): void {

builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverActivity.trigger.ActivityMessagesHandler,
txMatch: {
'tx.objectClass': { $nin: [activity.class.ActivityMessage, notification.class.DocNotifyContext] }
},
isAsync: true
})

Expand All @@ -52,6 +56,10 @@ export function createModel (builder: Builder): void {

builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverActivity.trigger.ReferenceTrigger,
txMatch: {
'tx.objectClass': { $ne: activity.class.ActivityMessage },
objectClass: { $nin: [notification.class.InboxNotification, notification.class.DocNotifyContext] }
},
isAsync: true
})
}
2 changes: 1 addition & 1 deletion models/server-gmail/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ export function createModel (builder: Builder): void {
})

builder.mixin(gmail.ids.EmailNotification, notification.class.NotificationType, serverNotification.mixin.TypeMatch, {
func: serverGmail.function.IsIncomingMessage
func: serverGmail.function.IsIncomingMessageTypeMatch
})
}
2 changes: 1 addition & 1 deletion models/server-lead/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function createModel (builder: Builder): void {
notification.class.NotificationType,
serverNotification.mixin.TypeMatch,
{
func: serverNotification.function.IsUserEmployeeInFieldValue
func: serverNotification.function.IsUserEmployeeInFieldValueTypeMatch
}
)

Expand Down
17 changes: 8 additions & 9 deletions models/server-notification/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,22 @@

import { type Builder, Mixin, Model } from '@hcengineering/model'

import core, { type Account, type Doc, type Ref, type Tx } from '@hcengineering/core'
import core, { type Ref } from '@hcengineering/core'
import { TClass, TDoc } from '@hcengineering/model-core'
import { TNotificationType } from '@hcengineering/model-notification'
import notification, { type NotificationProvider, type NotificationType } from '@hcengineering/notification'
import notification, { type NotificationProvider } from '@hcengineering/notification'
import { type Resource } from '@hcengineering/platform'
import serverCore, { type TriggerControl } from '@hcengineering/server-core'
import serverCore from '@hcengineering/server-core'
import serverNotification, {
type HTMLPresenter,
type NotificationContentProvider,
type NotificationPresenter,
type NotificationProviderFunc,
type NotificationProviderResources,
type Presenter,
type TextPresenter,
type TypeMatch,
type NotificationContentProvider,
type NotificationProviderResources,
type NotificationProviderFunc
type TypeMatchFunc
} from '@hcengineering/server-notification'

export { serverNotificationId } from '@hcengineering/server-notification'
Expand All @@ -52,9 +53,7 @@ export class TNotificationPresenter extends TClass implements NotificationPresen

@Mixin(serverNotification.mixin.TypeMatch, notification.class.NotificationType)
export class TTypeMatch extends TNotificationType implements TypeMatch {
func!: Resource<
(tx: Tx, doc: Doc, user: Ref<Account>, type: NotificationType, control: TriggerControl) => Promise<boolean>
>
func!: TypeMatchFunc
}

@Model(serverNotification.class.NotificationProviderResources, core.class.Doc)
Expand Down
2 changes: 1 addition & 1 deletion models/server-recruit/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ export function createModel (builder: Builder): void {
notification.class.NotificationType,
serverNotification.mixin.TypeMatch,
{
func: serverNotification.function.IsUserEmployeeInFieldValue
func: serverNotification.function.IsUserEmployeeInFieldValueTypeMatch
}
)
}
2 changes: 1 addition & 1 deletion models/server-telegram/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function createModel (builder: Builder): void {
notification.class.NotificationType,
serverNotification.mixin.TypeMatch,
{
func: serverTelegram.function.IsIncomingMessage
func: serverTelegram.function.IsIncomingMessageTypeMatch
}
)

Expand Down
2 changes: 1 addition & 1 deletion models/server-tracker/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function createModel (builder: Builder): void {
notification.class.NotificationType,
serverNotification.mixin.TypeMatch,
{
func: serverNotification.function.IsUserEmployeeInFieldValue
func: serverNotification.function.IsUserEmployeeInFieldValueTypeMatch
}
)
}
2 changes: 1 addition & 1 deletion packages/core/src/__tests__/minmodel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ export function genMinModel (): TxCUD<Doc>[] {
txes.push(
createClass(core.class.Blob, {
label: 'Blob' as IntlString,
extends: core.class.Blob,
extends: core.class.Doc,
kind: ClassifierKind.CLASS
})
)
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,8 @@ export interface Permission extends Doc {
export interface Account extends Doc {
email: string
role: AccountRole

person?: Ref<Doc>
haiodo marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
28 changes: 11 additions & 17 deletions packages/core/src/hierarchy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export class Hierarchy {
private readonly attributes = new Map<Ref<Classifier>, Map<string, AnyAttribute>>()
private readonly attributesById = new Map<Ref<AnyAttribute>, AnyAttribute>()
private readonly descendants = new Map<Ref<Classifier>, Ref<Classifier>[]>()
private readonly ancestors = new Map<Ref<Classifier>, Ref<Classifier>[]>()
private readonly ancestors = new Map<Ref<Classifier>, { ordered: Ref<Classifier>[], set: Set<Ref<Classifier>> }>()
private readonly proxies = new Map<Ref<Mixin<Doc>>, ProxyHandler<Doc>>()

private readonly classifierProperties = new Map<Ref<Classifier>, Record<string, any>>()
Expand Down Expand Up @@ -166,7 +166,7 @@ export class Hierarchy {
if (result === undefined) {
throw new Error('ancestors not found: ' + _class)
}
return result
return result.ordered
}

getClass<T extends Obj = Obj>(_class: Ref<Class<T>>): Class<T> {
Expand Down Expand Up @@ -301,17 +301,7 @@ export class Hierarchy {
* It will iterate over parents.
*/
isDerived<T extends Obj>(_class: Ref<Class<T>>, from: Ref<Class<T>>): boolean {
let cl: Ref<Class<T>> | undefined = _class
while (cl !== undefined) {
if (cl === from) return true

const cll = this.classifiers.get(cl)
if (cll === undefined || this.isInterface(cll)) {
return false
}
cl = (cll as Class<T>).extends
}
return false
return this.ancestors.get(_class)?.set?.has(from) ?? false
}

/**
Expand Down Expand Up @@ -398,15 +388,19 @@ export class Hierarchy {
const list = this.ancestors.get(_class)
if (list === undefined) {
if (add) {
this.ancestors.set(_class, [classifier])
this.ancestors.set(_class, { ordered: [classifier], set: new Set([classifier]) })
}
} else {
if (add) {
addIf(list, classifier)
if (!list.set.has(classifier)) {
list.ordered.push(classifier)
list.set.add(classifier)
}
} else {
const pos = list.indexOf(classifier)
const pos = list.ordered.indexOf(classifier)
if (pos !== -1) {
list.splice(pos, 1)
list.ordered.splice(pos, 1)
list.set.delete(classifier)
}
}
}
Expand Down
59 changes: 53 additions & 6 deletions packages/core/src/memdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

import { PlatformError, Severity, Status } from '@hcengineering/platform'
import { Lookup, MeasureContext, ReverseLookups, getObjectValue } from '.'
import type { AttachedDoc, Class, Doc, Ref } from './classes'
import type { Account, AttachedDoc, Class, Doc, Ref } from './classes'
import core from './component'
import { Hierarchy } from './hierarchy'
import { checkMixinKey, matchQuery, resultSort } from './query'
Expand All @@ -31,6 +31,8 @@ export abstract class MemDb extends TxProcessor implements Storage {
private readonly objectsByClass = new Map<Ref<Class<Doc>>, Map<Ref<Doc>, Doc>>()
private readonly objectById = new Map<Ref<Doc>, Doc>()

private readonly accountByPersonId = new Map<Ref<Doc>, Account[]>()

constructor (protected readonly hierarchy: Hierarchy) {
super()
}
Expand Down Expand Up @@ -75,6 +77,10 @@ export abstract class MemDb extends TxProcessor implements Storage {
return doc as T
}

getAccountByPersonId (ref: Ref<Doc>): Account[] {
return this.accountByPersonId.get(ref) ?? []
}

findObject<T extends Doc>(_id: Ref<T>): T | undefined {
const doc = this.objectById.get(_id)
return doc as T
Expand Down Expand Up @@ -214,6 +220,12 @@ export abstract class MemDb extends TxProcessor implements Storage {
const arr = this.getObjectsByClass(_class)
arr.set(doc._id, doc)
})
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
const account = doc as Account
if (account.person !== undefined) {
this.accountByPersonId.set(account.person, [...(this.accountByPersonId.get(account.person) ?? []), account])
}
}
this.objectById.set(doc._id, doc)
}

Expand All @@ -226,6 +238,37 @@ export abstract class MemDb extends TxProcessor implements Storage {
this.hierarchy.getAncestors(doc._class).forEach((_class) => {
this.cleanObjectByClass(_class, _id)
})
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
const account = doc as Account
if (account.person !== undefined) {
const acc = this.accountByPersonId.get(account.person) ?? []
this.accountByPersonId.set(
account.person,
acc.filter((it) => it._id !== _id)
)
}
}
}

updateDoc (_id: Ref<Doc>, doc: Doc, update: TxUpdateDoc<Doc> | TxMixin<Doc, Doc>): void {
if (
this.hierarchy.isDerived(doc._class, core.class.Account) &&
update._class === core.class.TxUpdateDoc &&
(update as TxUpdateDoc<Account>).operations.person !== undefined
) {
const account = doc as Account
if (account.person !== undefined) {
const acc = this.accountByPersonId.get(account.person) ?? []
this.accountByPersonId.set(
account.person,
acc.filter((it) => it._id !== _id)
)
}
const newPerson = (update as TxUpdateDoc<Account>).operations.person
if (newPerson !== undefined) {
this.accountByPersonId.set(newPerson, [...(this.accountByPersonId.get(newPerson) ?? []), account])
}
}
}
}

Expand Down Expand Up @@ -297,6 +340,7 @@ export class ModelDb extends MemDb {
const cud = tx as TxUpdateDoc<Doc>
const doc = this.findObject(cud.objectId)
if (doc !== undefined) {
this.updateDoc(cud.objectId, doc, cud)
TxProcessor.updateDoc2Doc(doc, cud)
} else {
ctx.error('no document found, failed to apply model transaction, skipping', {
Expand All @@ -320,9 +364,10 @@ export class ModelDb extends MemDb {
break
case core.class.TxMixin: {
const mix = tx as TxMixin<Doc, Doc>
const obj = this.findObject(mix.objectId)
if (obj !== undefined) {
TxProcessor.updateMixin4Doc(obj, mix)
const doc = this.findObject(mix.objectId)
if (doc !== undefined) {
this.updateDoc(mix.objectId, doc, mix)
TxProcessor.updateMixin4Doc(doc, mix)
} else {
ctx.error('no document found, failed to apply model transaction, skipping', {
_id: tx._id,
Expand All @@ -339,6 +384,7 @@ export class ModelDb extends MemDb {
protected async txUpdateDoc (tx: TxUpdateDoc<Doc>): Promise<TxResult> {
try {
const doc = this.getObject(tx.objectId) as any
this.updateDoc(tx.objectId, doc, tx)
TxProcessor.updateDoc2Doc(doc, tx)
return tx.retrieve === true ? { object: doc } : {}
} catch (err: any) {}
Expand All @@ -354,8 +400,9 @@ export class ModelDb extends MemDb {

// TODO: process ancessor mixins
protected async txMixin (tx: TxMixin<Doc, Doc>): Promise<TxResult> {
const obj = this.getObject(tx.objectId) as any
TxProcessor.updateMixin4Doc(obj, tx)
const doc = this.getObject(tx.objectId) as any
this.updateDoc(tx.objectId, doc, tx)
TxProcessor.updateMixin4Doc(doc, tx)
return {}
}
}
Loading