diff --git a/.vscode/launch.json b/.vscode/launch.json index 04e28d3981..17bdb15d4c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -48,7 +48,7 @@ "ACCOUNTS_URL": "http://localhost:3000", // "SERVER_PROVIDER":"uweb" "SERVER_PROVIDER":"ws", - "MODEL_VERSION": "v0.6.287", + "MODEL_VERSION": "0.6.287", "ELASTIC_INDEX_NAME": "local_storage_index", "UPLOAD_URL": "/files", diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 868cbd724d..21a7f146bb 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -1551,8 +1551,8 @@ dependencies: specifier: ^8.0.3 version: 8.0.7 fork-ts-checker-webpack-plugin: - specifier: ~7.3.0 - version: 7.3.0(typescript@5.3.3)(webpack@5.90.3) + specifier: ^9.0.2 + version: 9.0.2(typescript@5.3.3)(webpack@5.90.3) form-data: specifier: ^4.0.0 version: 4.0.0 @@ -14802,33 +14802,6 @@ packages: signal-exit: 4.1.0 dev: false - /fork-ts-checker-webpack-plugin@7.3.0(typescript@5.3.3)(webpack@5.90.3): - resolution: {integrity: sha512-IN+XTzusCjR5VgntYFgxbxVx3WraPRnKehBFrf00cMSrtUuW9MsG9dhL6MWpY6MkjC3wVwoujfCDgZZCQwbswA==} - engines: {node: '>=12.13.0', yarn: '>=1.0.0'} - peerDependencies: - typescript: '>3.6.0' - vue-template-compiler: '*' - webpack: ^5.11.0 - peerDependenciesMeta: - vue-template-compiler: - optional: true - dependencies: - '@babel/code-frame': 7.23.5 - chalk: 4.1.2 - chokidar: 3.6.0 - cosmiconfig: 7.1.0 - deepmerge: 4.3.1 - fs-extra: 10.1.0 - memfs: 3.5.3 - minimatch: 3.1.2 - node-abort-controller: 3.1.1 - schema-utils: 3.3.0 - semver: 7.6.0 - tapable: 2.2.1 - typescript: 5.3.3 - webpack: 5.90.3(esbuild@0.20.1)(webpack-cli@5.1.4) - dev: false - /fork-ts-checker-webpack-plugin@8.0.0(typescript@5.3.3)(webpack@5.90.3): resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} engines: {node: '>=12.13.0', yarn: '>=1.0.0'} @@ -14852,6 +14825,29 @@ packages: webpack: 5.90.3(@swc/core@1.4.2)(esbuild@0.20.1)(webpack-cli@5.1.4) dev: false + /fork-ts-checker-webpack-plugin@9.0.2(typescript@5.3.3)(webpack@5.90.3): + resolution: {integrity: sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==} + engines: {node: '>=12.13.0', yarn: '>=1.0.0'} + peerDependencies: + typescript: '>3.6.0' + webpack: ^5.11.0 + dependencies: + '@babel/code-frame': 7.23.5 + chalk: 4.1.2 + chokidar: 3.6.0 + cosmiconfig: 8.3.6(typescript@5.3.3) + deepmerge: 4.3.1 + fs-extra: 10.1.0 + memfs: 3.5.3 + minimatch: 3.1.2 + node-abort-controller: 3.1.1 + schema-utils: 3.3.0 + semver: 7.6.3 + tapable: 2.2.1 + typescript: 5.3.3 + webpack: 5.90.3(esbuild@0.20.1)(webpack-cli@5.1.4) + dev: false + /form-data-encoder@1.7.2: resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} dev: false @@ -23963,6 +23959,18 @@ packages: yjs: 13.6.12 dev: false + /y-leveldb@0.1.2(yjs@13.6.12): + resolution: {integrity: sha512-6ulEn5AXfXJYi89rXPEg2mMHAyyw8+ZfeMMdOtBbV8FJpQ1NOrcgi6DTAcXof0dap84NjHPT2+9d0rb6cFsjEg==} + requiresBuild: true + peerDependencies: + yjs: ^13.0.0 + dependencies: + level: 6.0.1 + lib0: 0.2.89 + yjs: 13.6.12 + dev: false + optional: true + /y-prosemirror@1.2.2(prosemirror-model@1.19.4)(y-protocols@1.0.6)(yjs@13.6.12): resolution: {integrity: sha512-hHdnIAhfa8mIoLWtTkMDb6RBzN3lye1QVkaZwVm58sledAA1zTl+yyEtgkrY/sdH6SaQL0rsLj61zHjgr5D0HQ==} engines: {node: '>=16.0.0', npm: '>=8.0.0'} @@ -25839,7 +25847,7 @@ packages: dev: false file:projects/desktop.tgz(bufferutil@4.0.8)(sass@1.71.1)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-/SB+ER8kNF2XYUvZ61U+U9GSaTya1qsHJWc3FDUdz8d12APYoMYf6c2Ax1+Kqk1GUWMu9+rYRfypLOVyqirjyw==, tarball: file:projects/desktop.tgz} + resolution: {integrity: sha512-W8ImBT7qeJoODsDzoy5ioDFr7A1YJX5S9xa8haLtNxiOce9iZKCyesZ5qK81g5ZgNETfhWXNo1+7u0fCcoG2qw==, tarball: file:projects/desktop.tgz} id: file:projects/desktop.tgz name: '@rush-temp/desktop' version: 0.0.0 @@ -25872,7 +25880,7 @@ packages: eslint-plugin-n: 15.7.0(eslint@8.56.0) eslint-plugin-promise: 6.1.1(eslint@8.56.0) file-loader: 6.2.0(webpack@5.90.3) - fork-ts-checker-webpack-plugin: 7.3.0(typescript@5.3.3)(webpack@5.90.3) + fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.90.3) html-webpack-plugin: 5.6.0(webpack@5.90.3) livekit-client: 2.2.0 mini-css-extract-plugin: 2.8.0(webpack@5.90.3) @@ -25917,7 +25925,6 @@ packages: - supports-color - uglify-js - utf-8-validate - - vue-template-compiler dev: false file:projects/devmodel-resources.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2): @@ -27399,7 +27406,7 @@ packages: dev: false file:projects/middleware.tgz(@types/node@20.11.19)(esbuild@0.20.1)(ts-node@10.9.2): - resolution: {integrity: sha512-bXNowU56V9TLVwVPGlXIIPyOoUfE5eiXJAot0up92iM7uYd6nXdZnylrmPoCPxee4CDCw/3HlGQhuDzq+YFaZw==, tarball: file:projects/middleware.tgz} + resolution: {integrity: sha512-pJ53XVy+R4NqWAWGrAMeHCpgQabQzcs33zhDjBJZmNnlQBQCgUfkjCrqZEh9rMSiUhDGpj2SNiWvhlnUdbz3pg==, tarball: file:projects/middleware.tgz} id: file:projects/middleware.tgz name: '@rush-temp/middleware' version: 0.0.0 @@ -30400,7 +30407,7 @@ packages: dev: false file:projects/prod.tgz(bufferutil@4.0.8)(sass@1.71.1)(ts-node@10.9.2)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-BKzsLd9ugM4rEyUkJyeMG3QjOS0RLA/ipkLIIRC+NUUQi/zMuHMEumvoSok539kpPsVgRrtJdnDBa+3tja5fSA==, tarball: file:projects/prod.tgz} + resolution: {integrity: sha512-cvUyK9P5nMldS6XkLY4agfy2Ch2aFf7Qv7rXU/goSeywHNOwEf/jgffVgsXFU6Z0TFqnWfiB/ey7SJ9pM/mU4Q==, tarball: file:projects/prod.tgz} id: file:projects/prod.tgz name: '@rush-temp/prod' version: 0.0.0 @@ -30416,7 +30423,7 @@ packages: esbuild: 0.20.1 esbuild-loader: 4.0.3(webpack@5.90.3) file-loader: 6.2.0(webpack@5.90.3) - fork-ts-checker-webpack-plugin: 7.3.0(typescript@5.3.3)(webpack@5.90.3) + fork-ts-checker-webpack-plugin: 9.0.2(typescript@5.3.3)(webpack@5.90.3) html-webpack-plugin: 5.6.0(webpack@5.90.3) mini-css-extract-plugin: 2.8.0(webpack@5.90.3) postcss: 8.4.35 @@ -30456,7 +30463,6 @@ packages: - ts-node - uglify-js - utf-8-validate - - vue-template-compiler dev: false file:projects/products-assets.tgz(esbuild@0.20.1)(ts-node@10.9.2): @@ -34224,7 +34230,7 @@ packages: dev: false file:projects/text-editor-resources.tgz(@types/node@20.11.19)(bufferutil@4.0.8)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(prosemirror-model@1.19.4)(ts-node@10.9.2)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-PNeHw/vqYgLq6arghBnAisN4GlvA0DWANKiXTvjahoXM0EhEz6SVX2bh6Fd9xrDqYKWVdfVc2X5o5Zk1dI4qEw==, tarball: file:projects/text-editor-resources.tgz} + resolution: {integrity: sha512-Qyx6oJpj8FfTxV0rqKs4gmH48kx9bYYDHPpdA36B5x71Mtss/cPWvq/fEgzVyNQKhH1qaqzWv9BnpKHCcpBNzQ==, tarball: file:projects/text-editor-resources.tgz} id: file:projects/text-editor-resources.tgz name: '@rush-temp/text-editor-resources' version: 0.0.0 @@ -34568,7 +34574,7 @@ packages: dev: false file:projects/tool.tgz(bufferutil@4.0.8)(utf-8-validate@6.0.4): - resolution: {integrity: sha512-s4tgmvq13d9Vu2xJD59Y4BtMgYqxVoNIlyghB5y5WEqLiTHUr7FZ4nSnaTWkg96K0KOAH6LsUvPOrD4W1eW8NA==, tarball: file:projects/tool.tgz} + resolution: {integrity: sha512-gjmLNkjPV0dXJNjkowQTvuR1ELM+S3aT3t/y9QJScPMxDIUPZRjkXIoM//4Qk3/RqUOFVhcRQTVoZVcTtK6rCg==, tarball: file:projects/tool.tgz} id: file:projects/tool.tgz name: '@rush-temp/tool' version: 0.0.0 @@ -35269,7 +35275,7 @@ packages: dev: false file:projects/workspace-service.tgz: - resolution: {integrity: sha512-WUCtvidfvVcahSFbmbtTZeGvedNNsG4RERSfnG+MWuDnDfyFAYnpBVest9gyO2/jH4cZ/AxeE1tgZKWPqCpSeg==, tarball: file:projects/workspace-service.tgz} + resolution: {integrity: sha512-/ACNv9VVAkel1YYEF3LyqV49qXKzbEzFpO7g5cb1P+f1bmzxQmpfYBc5sDssrHF0nB0o2+Fzqud6BdI7S+n+Uw==, tarball: file:projects/workspace-service.tgz} name: '@rush-temp/workspace-service' version: 0.0.0 dependencies: diff --git a/desktop/package.json b/desktop/package.json index 79eab846c5..d9f6818950 100644 --- a/desktop/package.json +++ b/desktop/package.json @@ -41,7 +41,7 @@ "postcss-load-config": "^4.0.1", "compression-webpack-plugin": "^10.0.0", "html-webpack-plugin": "^5.5.0", - "fork-ts-checker-webpack-plugin": "~7.3.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", "update-browserslist-db": "^1.1.0", "browserslist": "^4.23.3", "typescript": "^5.3.3", diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index 37deb7113e..ad51c2a1ce 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -78,6 +78,8 @@ services: restart: unless-stopped workspace: image: hardcoreeng/workspace + extra_hosts: + - "host.docker.internal:host-gateway" # deploy: # mode: replicated # replicas: 3 @@ -96,7 +98,7 @@ services: - FRONT_URL=http://localhost:8087 - RESERVED_DB_NAMES=telegram,gmail,github - MODEL_ENABLED=* - - ACCOUNTS_URL=http://account:3000 + - ACCOUNTS_URL=http://host.docker.internal:3000 - BRANDING_PATH=/var/cfg/branding.json - NOTIFY_INBOX_ONLY=true # - INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml @@ -151,7 +153,7 @@ services: - GITHUB_URL=http://localhost:3500 - PRINT_URL=http://localhost:4005 - SIGN_URL=http://localhost:4006 - - ANALYTICS_COLLECTOR_URL=http://localhost:4007 + - ANALYTICS_COLLECTOR_URL=http://localhost:4017 - DESKTOP_UPDATES_URL=https://dist.huly.io - DESKTOP_UPDATES_CHANNEL=dev - BRANDING_URL=http://localhost:8087/branding.json @@ -247,10 +249,10 @@ services: - "host.docker.internal:host-gateway" restart: unless-stopped ports: - - 4007:4007 + - 4017:4017 environment: - SECRET=secret - - PORT=4007 + - PORT=4017 - MONGO_URL=${MONGO_URL} - 'MONGO_OPTIONS={"appName":"analytics","maxPoolSize":1}' - SERVICE_ID=analytics-collector-service diff --git a/dev/prod/package.json b/dev/prod/package.json index 6e10a6a868..96ac3bcdc5 100644 --- a/dev/prod/package.json +++ b/dev/prod/package.json @@ -42,7 +42,7 @@ "postcss-load-config": "^4.0.1", "compression-webpack-plugin": "^10.0.0", "html-webpack-plugin": "^5.5.0", - "fork-ts-checker-webpack-plugin": "~7.3.0", + "fork-ts-checker-webpack-plugin": "^9.0.2", "update-browserslist-db": "^1.1.0", "browserslist": "^4.23.3", "esbuild": "^0.20.0", diff --git a/dev/tool/src/clean.ts b/dev/tool/src/clean.ts index 9e8e6a3a93..612dcb0a92 100644 --- a/dev/tool/src/clean.ts +++ b/dev/tool/src/clean.ts @@ -121,7 +121,7 @@ export async function cleanWorkspace ( while (filter.length > 0) { const part = filter.splice(0, 100) - const op = ops.apply('') + const op = ops.apply() for (const c of part) { await op.remove(c) } @@ -146,7 +146,7 @@ export async function cleanWorkspace ( while (issues.length > 0) { const part = issues.splice(0, 5) - const op = ops.apply('') + const op = ops.apply() for (const c of part) { await op.remove(c) } diff --git a/models/server-activity/src/migration.ts b/models/server-activity/src/migration.ts index bcf1a01e81..f570bde1c9 100644 --- a/models/server-activity/src/migration.ts +++ b/models/server-activity/src/migration.ts @@ -50,10 +50,11 @@ function getActivityControl (client: MigrationClient): ActivityControl { const txFactory = new TxFactory(core.account.System, false) return { + ctx: new MeasureMetricsContext('migration', {}), txFactory, modelDb: client.model, hierarchy: client.hierarchy, - findAll: async (_class, query, options) => + findAll: async (ctx, _class, query, options) => toFindResult(await client.find(client.hierarchy.getDomain(_class), query, options)), storageAdapter: client.storageAdapter, workspace: client.workspaceId @@ -111,9 +112,10 @@ async function createDocUpdateMessages (client: MigrationClient): Promise const notificationControl = getActivityControl(client) - const txClient: Pick = { + const txClient: Pick = { hierarchy: notificationControl.hierarchy, - findAll: notificationControl.findAll + findAll: notificationControl.findAll, + ctx: new MeasureMetricsContext('migration', {}) } let processed = 0 @@ -177,7 +179,7 @@ async function createDocUpdateMessages (client: MigrationClient): Promise for (const di of ids) { docIds.set(di, null) } - const edocs = await txClient.findAll(_class, { _id: { $in: ids } }) + const edocs = await txClient.findAll(txClient.ctx, _class, { _id: { $in: ids } }) for (const ed of edocs) { docIds.set(ed._id, ed) } diff --git a/models/server-recruit/src/index.ts b/models/server-recruit/src/index.ts index 25abf15e3d..b627a5ae91 100644 --- a/models/server-recruit/src/index.ts +++ b/models/server-recruit/src/index.ts @@ -61,7 +61,10 @@ export function createModel (builder: Builder): void { }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverRecruit.trigger.OnRecruitUpdate + trigger: serverRecruit.trigger.OnRecruitUpdate, + txMatch: { + objectClass: recruit.class.Vacancy + } }) builder.mixin(recruit.class.Vacancy, core.class.Class, serverCore.mixin.SearchPresenter, { diff --git a/models/server-tracker/src/index.ts b/models/server-tracker/src/index.ts index 784d6fda16..5cbf00948b 100644 --- a/models/server-tracker/src/index.ts +++ b/models/server-tracker/src/index.ts @@ -54,7 +54,10 @@ export function createModel (builder: Builder): void { }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { - trigger: serverTracker.trigger.OnIssueUpdate + trigger: serverTracker.trigger.OnIssueUpdate, + txMatch: { + objectClass: { $in: [tracker.class.Issue, tracker.class.TimeSpendReport] } + } }) builder.createDoc(serverCore.class.Trigger, core.space.Model, { diff --git a/packages/core/src/measurements/context.ts b/packages/core/src/measurements/context.ts index ac95bf4c42..b3b8aff4ee 100644 --- a/packages/core/src/measurements/context.ts +++ b/packages/core/src/measurements/context.ts @@ -1,7 +1,7 @@ // Basic performance metrics suite. import { generateId } from '../utils' -import { childMetrics, measure, newMetrics } from './metrics' +import { childMetrics, newMetrics, updateMeasure } from './metrics' import { FullParamsType, MeasureContext, @@ -12,15 +12,72 @@ import { type OperationLogEntry } from './types' +const errorPrinter = ({ message, stack, ...rest }: Error): object => ({ + message, + stack, + ...rest +}) +function replacer (value: any): any { + return value instanceof Error ? errorPrinter(value) : value +} + +const consoleLogger = (logParams: Record): MeasureLogger => ({ + info: (msg, args) => { + console.info( + msg, + ...Object.entries({ ...(args ?? {}), ...(logParams ?? {}) }).map( + (it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}` + ) + ) + }, + error: (msg, args) => { + console.error( + msg, + ...Object.entries({ ...(args ?? {}), ...(logParams ?? {}) }).map( + (it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}` + ) + ) + }, + warn: (msg, args) => { + console.warn(msg, ...Object.entries(args ?? {}).map((it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}`)) + }, + close: async () => {}, + logOperation: (operation, time, params) => {} +}) + +const noParamsLogger = consoleLogger({}) + /** * @public */ export class MeasureMetricsContext implements MeasureContext { private readonly name: string private readonly params: ParamsType + + private readonly fullParams: FullParamsType | (() => FullParamsType) = {} logger: MeasureLogger metrics: Metrics - private readonly done: (value?: number, override?: boolean) => void + + st = Date.now() + contextData: object = {} + private done (value?: number, override?: boolean): void { + updateMeasure( + this.metrics, + this.st, + this.params, + this.fullParams, + (spend) => { + this.logger.logOperation(this.name, spend, { + ...this.params, + ...(typeof this.fullParams === 'function' ? this.fullParams() : this.fullParams), + ...this.fullParams, + ...(this.logParams ?? {}) + }) + }, + value, + override + ) + } constructor ( name: string, @@ -33,6 +90,7 @@ export class MeasureMetricsContext implements MeasureContext { ) { this.name = name this.params = params + this.fullParams = fullParams this.metrics = metrics this.metrics.namedParams = this.metrics.namedParams ?? {} for (const [k, v] of Object.entries(params)) { @@ -42,51 +100,13 @@ export class MeasureMetricsContext implements MeasureContext { this.metrics.namedParams[k] = '*' } } - this.done = measure(metrics, params, fullParams, (spend) => { - this.logger.logOperation(this.name, spend, { - ...params, - ...(typeof fullParams === 'function' ? fullParams() : fullParams), - ...fullParams, - ...(this.logParams ?? {}) - }) - }) - const errorPrinter = ({ message, stack, ...rest }: Error): object => ({ - message, - stack, - ...rest - }) - function replacer (value: any): any { - return value instanceof Error ? errorPrinter(value) : value - } - - this.logger = logger ?? { - info: (msg, args) => { - console.info( - msg, - ...Object.entries({ ...(args ?? {}), ...(this.logParams ?? {}) }).map( - (it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}` - ) - ) - }, - error: (msg, args) => { - console.error( - msg, - ...Object.entries({ ...(args ?? {}), ...(this.logParams ?? {}) }).map( - (it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}` - ) - ) - }, - warn: (msg, args) => { - console.warn(msg, ...Object.entries(args ?? {}).map((it) => `${it[0]}=${JSON.stringify(replacer(it[1]))}`)) - }, - close: async () => {}, - logOperation: (operation, time, params) => {} - } + this.logger = logger ?? (this.logParams != null ? consoleLogger(this.logParams ?? {}) : noParamsLogger) } measure (name: string, value: number, override?: boolean): void { const c = new MeasureMetricsContext('#' + name, {}, {}, childMetrics(this.metrics, ['#' + name]), this.logger, this) + c.contextData = this.contextData c.done(value, override) } @@ -96,7 +116,7 @@ export class MeasureMetricsContext implements MeasureContext { fullParams?: FullParamsType | (() => FullParamsType), logger?: MeasureLogger ): MeasureContext { - return new MeasureMetricsContext( + const result = new MeasureMetricsContext( name, params, fullParams ?? {}, @@ -105,6 +125,8 @@ export class MeasureMetricsContext implements MeasureContext { this, this.logParams ) + result.contextData = this.contextData + return result } with( @@ -147,15 +169,17 @@ export class MeasureMetricsContext implements MeasureContext { } } - async withLog( + withLog( name: string, params: ParamsType, op: (ctx: MeasureContext) => T | Promise, fullParams?: ParamsType ): Promise { const st = Date.now() - const r = await this.with(name, params, op, fullParams) - this.logger.logOperation(name, Date.now() - st, { ...params, ...fullParams }) + const r = this.with(name, params, op, fullParams) + void r.finally(() => { + this.logger.logOperation(name, Date.now() - st, { ...params, ...fullParams }) + }) return r } @@ -182,13 +206,9 @@ export class MeasureMetricsContext implements MeasureContext { export function withContext (name: string, params: ParamsType = {}): any { return (target: any, propertyKey: string, descriptor: PropertyDescriptor): PropertyDescriptor => { const originalMethod = descriptor.value - descriptor.value = async function (...args: any[]): Promise { + descriptor.value = function (...args: any[]): Promise { const ctx = args[0] as MeasureContext - return await ctx.with( - name, - params, - async (ctx) => await (originalMethod.apply(this, [ctx, ...args.slice(1)]) as Promise) - ) + return ctx.with(name, params, (ctx) => originalMethod.apply(this, [ctx, ...args.slice(1)]) as Promise) } return descriptor } diff --git a/packages/core/src/measurements/metrics.ts b/packages/core/src/measurements/metrics.ts index e60cc2e214..516e0b83d5 100644 --- a/packages/core/src/measurements/metrics.ts +++ b/packages/core/src/measurements/metrics.ts @@ -66,47 +66,58 @@ export function measure ( endOp?: (spend: number) => void ): () => void { const st = Date.now() - return (value?: number, override?: boolean) => { - const ed = Date.now() - - const fParams = typeof fullParams === 'function' ? fullParams() : fullParams - // Update params if required - for (const [k, v] of Object.entries(params)) { - let params = metrics.params[k] - if (params === undefined) { - params = {} - metrics.params[k] = params - } - const vKey = `${v?.toString() ?? ''}` - let param = params[vKey] - if (param === undefined) { - param = { - operations: 0, - value: 0 - } - params[vKey] = param - } - if (override === true) { - metrics.operations = value ?? ed - st - } else { - param.value += value ?? ed - st - param.operations++ - } - - param.topResult = getUpdatedTopResult(param.topResult, ed - st, fParams) - } - // Update leaf data - if (override === true) { - metrics.operations = value ?? ed - st - } else { - metrics.value += value ?? ed - st - metrics.operations++ - } - - metrics.topResult = getUpdatedTopResult(metrics.topResult, ed - st, fParams) - endOp?.(ed - st) + return () => { + updateMeasure(metrics, st, params, fullParams, endOp) } } +export function updateMeasure ( + metrics: Metrics, + st: number, + params: ParamsType, + fullParams: FullParamsType | (() => FullParamsType), + endOp?: (spend: number) => void, + value?: number, + override?: boolean +): void { + const ed = Date.now() + + const fParams = typeof fullParams === 'function' ? fullParams() : fullParams + // Update params if required + for (const [k, v] of Object.entries(params)) { + let params = metrics.params[k] + if (params === undefined) { + params = {} + metrics.params[k] = params + } + const vKey = `${v?.toString() ?? ''}` + let param = params[vKey] + if (param === undefined) { + param = { + operations: 0, + value: 0 + } + params[vKey] = param + } + if (override === true) { + param.operations = value ?? ed - st + } else { + param.value += value ?? ed - st + param.operations++ + } + + param.topResult = getUpdatedTopResult(param.topResult, ed - st, fParams) + } + // Update leaf data + if (override === true) { + metrics.operations = value ?? ed - st + } else { + metrics.value += value ?? ed - st + metrics.operations++ + } + + metrics.topResult = getUpdatedTopResult(metrics.topResult, ed - st, fParams) + endOp?.(ed - st) +} /** * @public diff --git a/packages/core/src/measurements/types.ts b/packages/core/src/measurements/types.ts index 7c6940a96d..85c7cceed3 100644 --- a/packages/core/src/measurements/types.ts +++ b/packages/core/src/measurements/types.ts @@ -66,8 +66,11 @@ export interface MeasureLogger { /** * @public */ -export interface MeasureContext { +export interface MeasureContext { id?: string + + // Context data will be copied referenced for all child contexts. + contextData: Q // Create a child metrics context newChild: (name: string, params: ParamsType, fullParams?: FullParamsType, logger?: MeasureLogger) => MeasureContext @@ -76,21 +79,21 @@ export interface MeasureContext { with: ( name: string, params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, + op: (ctx: MeasureContext) => T | Promise, fullParams?: FullParamsType | (() => FullParamsType) ) => Promise withSync: ( name: string, params: ParamsType, - op: (ctx: MeasureContext) => T, + op: (ctx: MeasureContext) => T, fullParams?: FullParamsType | (() => FullParamsType) ) => T withLog: ( name: string, params: ParamsType, - op: (ctx: MeasureContext) => T | Promise, + op: (ctx: MeasureContext) => T | Promise, fullParams?: FullParamsType ) => Promise diff --git a/packages/core/src/operations.ts b/packages/core/src/operations.ts index 48a2dc416e..5dd2c35e4c 100644 --- a/packages/core/src/operations.ts +++ b/packages/core/src/operations.ts @@ -1,3 +1,4 @@ +import { Analytics } from '@hcengineering/analytics' import { deepEqual } from 'fast-equals' import { DocumentUpdate, DOMAIN_MODEL, Hierarchy, MixinData, MixinUpdate, ModelDb, toFindResult } from '.' import type { @@ -26,7 +27,6 @@ import type { WithLookup } from './storage' import { DocumentClassQuery, Tx, TxApplyResult, TxCUD, TxFactory, TxProcessor } from './tx' -import { Analytics } from '@hcengineering/analytics' /** * @public @@ -313,7 +313,7 @@ export class TxOperations implements Omit { return this.removeDoc(doc._class, doc.space, doc._id) } - apply (scope: string, measure?: string): ApplyOperations { + apply (scope?: string, measure?: string): ApplyOperations { return new ApplyOperations(this, scope, measure) } @@ -443,7 +443,7 @@ export class ApplyOperations extends TxOperations { notMatches: DocumentClassQuery[] = [] constructor ( readonly ops: TxOperations, - readonly scope: string, + readonly scope?: string, readonly measureName?: string ) { const txClient: Client = { @@ -474,24 +474,41 @@ export class ApplyOperations extends TxOperations { } async commit (notify: boolean = true, extraNotify: Ref>[] = []): Promise { + if ( + this.txes.length === 1 && + this.matches.length === 0 && + this.notMatches.length === 0 && + this.measureName == null + ) { + const st = Date.now() + // Individual update, no need for apply + await this.ops.tx(this.txes[0]) + const time = Date.now() - st + this.txes = [] + return { + result: true, + time, + serverTime: time + } + } if (this.txes.length > 0) { const st = Date.now() - const result = await ((await this.ops.tx( - this.ops.txFactory.createTxApplyIf( - core.space.Tx, - this.scope, - this.matches, - this.notMatches, - this.txes, - this.measureName, - notify, - extraNotify - ) - )) as Promise) + const aop = this.ops.txFactory.createTxApplyIf( + core.space.Tx, + this.scope, + this.matches, + this.notMatches, + this.txes, + this.measureName, + notify, + extraNotify + ) + const result = (await this.ops.tx(aop)) as TxApplyResult const dnow = Date.now() - if (typeof window === 'object' && window !== null) { + if (typeof window === 'object' && window !== null && this.measureName != null) { console.log(`measure ${this.measureName}`, dnow - st, 'server time', result.serverTime) } + this.txes = [] return { result: result.success, time: dnow - st, @@ -500,6 +517,11 @@ export class ApplyOperations extends TxOperations { } return { result: true, time: 0, serverTime: 0 } } + + // Apply for this will reuse, same apply context. + apply (scope?: string, measure?: string): ApplyOperations { + return this + } } /** diff --git a/packages/core/src/server.ts b/packages/core/src/server.ts index 79f8885297..1d09a2bd81 100644 --- a/packages/core/src/server.ts +++ b/packages/core/src/server.ts @@ -13,9 +13,10 @@ // limitations under the License. // -import type { Doc, Domain, Ref } from './classes' -import { MeasureContext, type FullParamsType, type ParamsType } from './measurements' +import type { Account, Doc, Domain, Ref } from './classes' +import { MeasureContext } from './measurements' import type { Tx } from './tx' +import type { WorkspaceIdWithUrl } from './utils' /** * @public @@ -35,22 +36,44 @@ export interface StorageIterator { export type BroadcastTargets = Record string[] | undefined> -export interface SessionOperationContext { - ctx: MeasureContext - // A parts of derived data to deal with after operation will be complete +export interface SessionData { + broadcast: { + txes: Tx[] + targets: BroadcastTargets // A set of broadcast filters if required + } + contextCache: Map + removedMap: Map, Doc> + + userEmail: string + sessionId: string + admin?: boolean + + account: Account + + getAccount: (account: Ref) => Account | undefined + + workspace: WorkspaceIdWithUrl + branding: Branding | null +} + +export interface ContextData { derived: { txes: Tx[] targets: BroadcastTargets // A set of broadcast filters if required } - with: ( - name: string, - params: ParamsType, - op: (ctx: SessionOperationContext) => T | Promise, - fullParams?: FullParamsType - ) => Promise - contextCache: Map removedMap: Map, Doc> + + userEmail: string + sessionId: string + admin?: boolean + + account: Account + + getAccount: (account: Ref) => Account | undefined + + workspace: WorkspaceIdWithUrl + branding: Branding | null } /** diff --git a/packages/core/src/tx.ts b/packages/core/src/tx.ts index 8d5d24ff9c..61fda47304 100644 --- a/packages/core/src/tx.ts +++ b/packages/core/src/tx.ts @@ -122,13 +122,13 @@ export interface DocumentClassQuery { */ export interface TxApplyIf extends Tx { // only one operation per scope is allowed at one time. - scope: string + scope?: string // All matches should be true with at least one document. - match: DocumentClassQuery[] + match?: DocumentClassQuery[] // All matches should be false for all documents. - notMatch: DocumentClassQuery[] + notMatch?: DocumentClassQuery[] // If all matched execute following transactions. txes: TxCUD[] @@ -628,7 +628,7 @@ export class TxFactory { createTxApplyIf ( space: Ref, - scope: string, + scope: string | undefined, match: DocumentClassQuery[], notMatch: DocumentClassQuery[], txes: TxCUD[], diff --git a/packages/presentation/src/utils.ts b/packages/presentation/src/utils.ts index cfa4590862..5e199f223c 100644 --- a/packages/presentation/src/utils.ts +++ b/packages/presentation/src/utils.ts @@ -184,7 +184,7 @@ class UIClient extends TxOperations implements Client, OptimisticTxes { if (tx._class === core.class.TxApplyIf) { const applyTx = tx as TxApplyIf - if (applyTx.match.length !== 0 || applyTx.notMatch.length !== 0) { + if ((applyTx.match?.length ?? 0) !== 0 || (applyTx.notMatch?.length ?? 0) !== 0) { // Cannot early apply conditional transactions return } diff --git a/plugins/chunter-resources/src/components/ChannelScrollView.svelte b/plugins/chunter-resources/src/components/ChannelScrollView.svelte index c8c40bb2a4..5d5d8dbae8 100644 --- a/plugins/chunter-resources/src/components/ChannelScrollView.svelte +++ b/plugins/chunter-resources/src/components/ChannelScrollView.svelte @@ -26,16 +26,17 @@ messageInFocus, sortActivityMessages } from '@hcengineering/activity-resources' - import { Doc, generateId, getDay, Ref, Timestamp } from '@hcengineering/core' + import { Doc, getDay, Ref, Timestamp } from '@hcengineering/core' + import { DocNotifyContext } from '@hcengineering/notification' import { InboxNotificationsClientImpl } from '@hcengineering/notification-resources' import { getResource } from '@hcengineering/platform' import { getClient } from '@hcengineering/presentation' import { Loading, ModernButton, Scroller, ScrollParams } from '@hcengineering/ui' import { afterUpdate, beforeUpdate, onDestroy, onMount, tick } from 'svelte' import { get } from 'svelte/store' - import { DocNotifyContext } from '@hcengineering/notification' import { ChannelDataProvider, MessageMetadata } from '../channelDataProvider' + import chunter from '../plugin' import { chatReadMessagesStore, filterChatMessages, @@ -43,11 +44,10 @@ readChannelMessages, recheckNotifications } from '../utils' + import BlankView from './BlankView.svelte' import ActivityMessagesSeparator from './ChannelMessagesSeparator.svelte' import JumpToDateSelector from './JumpToDateSelector.svelte' import HistoryLoading from './LoadingHistory.svelte' - import BlankView from './BlankView.svelte' - import chunter from '../plugin' export let provider: ChannelDataProvider export let object: Doc @@ -672,7 +672,7 @@ scrollToBottom() } - const op = client.apply(generateId(), 'chunter.scrollDown') + const op = client.apply(undefined, 'chunter.scrollDown') await inboxClient.readDoc(op, doc._id) await op.commit() } @@ -691,7 +691,7 @@ if (unViewed.length === 0) { forceRead = true - const op = client.apply(generateId(), 'chunter.forceReadContext') + const op = client.apply(undefined, 'chunter.forceReadContext') await inboxClient.readDoc(op, object._id) await op.commit() } diff --git a/plugins/chunter-resources/src/components/chat-message/ChatMessageInput.svelte b/plugins/chunter-resources/src/components/chat-message/ChatMessageInput.svelte index 76ea0a5b70..934d1baa10 100644 --- a/plugins/chunter-resources/src/components/chat-message/ChatMessageInput.svelte +++ b/plugins/chunter-resources/src/components/chat-message/ChatMessageInput.svelte @@ -196,7 +196,7 @@ async function createMessage (event: CustomEvent, _id: Ref, msg: string): Promise { const { message, attachments } = event.detail - const operations = client.apply(_id, msg) + const operations = client.apply(undefined, msg) if (_class === chunter.class.ThreadMessage) { const parentMessage = object as ActivityMessage diff --git a/plugins/chunter-resources/src/components/chat/utils.ts b/plugins/chunter-resources/src/components/chat/utils.ts index 5f4802d3f7..41fffc19a5 100644 --- a/plugins/chunter-resources/src/components/chat/utils.ts +++ b/plugins/chunter-resources/src/components/chat/utils.ts @@ -18,7 +18,6 @@ import contact, { type PersonAccount } from '@hcengineering/contact' import core, { type Account, AccountRole, - generateId, getCurrentAccount, hasAccountRole, type IdMap, @@ -293,7 +292,7 @@ function getPinnedActions (contexts: DocNotifyContext[]): Action[] { } async function unpinAllChannels (contexts: DocNotifyContext[]): Promise { - const ops = getClient().apply(generateId(), 'unpinAllChannels') + const ops = getClient().apply(undefined, 'unpinAllChannels') try { for (const context of contexts) { @@ -387,7 +386,7 @@ export function loadSavedAttachments (): void { } export async function removeActivityChannels (contexts: DocNotifyContext[]): Promise { - const ops = getClient().apply(generateId(), 'removeActivityChannels') + const ops = getClient().apply(undefined, 'removeActivityChannels') try { for (const context of contexts) { @@ -408,7 +407,7 @@ export async function removeActivityChannels (contexts: DocNotifyContext[]): Pro export async function readActivityChannels (contexts: DocNotifyContext[]): Promise { const client = InboxNotificationsClientImpl.getClient() const notificationsByContext = get(client.inboxNotificationsByContext) - const ops = getClient().apply(generateId(), 'readActivityChannels') + const ops = getClient().apply(undefined, 'readActivityChannels') try { for (const context of contexts) { diff --git a/plugins/chunter-resources/src/utils.ts b/plugins/chunter-resources/src/utils.ts index 0888155898..43f252b31e 100644 --- a/plugins/chunter-resources/src/utils.ts +++ b/plugins/chunter-resources/src/utils.ts @@ -19,11 +19,11 @@ import activity, { type DisplayDocUpdateMessage, type DocUpdateMessage } from '@hcengineering/activity' +import { isReactionMessage } from '@hcengineering/activity-resources' import { type Channel, type ChatMessage, type DirectMessage, type ThreadMessage } from '@hcengineering/chunter' import contact, { getName, type Employee, type Person, type PersonAccount } from '@hcengineering/contact' import { PersonIcon, employeeByIdStore } from '@hcengineering/contact-resources' import core, { - generateId, getCurrentAccount, type Account, type Class, @@ -46,7 +46,6 @@ import { getClient } from '@hcengineering/presentation' import { type AnySvelteComponent } from '@hcengineering/ui' import { classIcon, getDocLinkTitle, getDocTitle } from '@hcengineering/view-resources' import { get, writable, type Unsubscriber } from 'svelte/store' -import { isReactionMessage } from '@hcengineering/activity-resources' import ChannelIcon from './components/ChannelIcon.svelte' import DirectIcon from './components/DirectIcon.svelte' @@ -417,7 +416,7 @@ export function recheckNotifications (context: DocNotifyContext): void { const toReadData = Array.from(toRead) toRead.clear() void (async () => { - const _client = client.apply(generateId(), 'recheckNotifications') + const _client = client.apply(undefined, 'recheckNotifications') await inboxClient.readNotifications(_client, toReadData) await _client.commit() })() @@ -434,7 +433,7 @@ export async function readChannelMessages ( const inboxClient = InboxNotificationsClientImpl.getClient() - const client = getClient().apply(generateId(), 'readViewportMessages') + const client = getClient().apply(undefined, 'readViewportMessages') try { const readMessages = get(chatReadMessagesStore) const allIds = getAllIds(messages).filter((id) => !readMessages.has(id)) diff --git a/plugins/controlled-documents/src/docutils.ts b/plugins/controlled-documents/src/docutils.ts index 532724476a..29e2815475 100644 --- a/plugins/controlled-documents/src/docutils.ts +++ b/plugins/controlled-documents/src/docutils.ts @@ -135,7 +135,7 @@ async function createControlledDoc ( const collaborativeDoc = getCollaborativeDocForDocument(`DOC-${prefix}`, seqNumber, 0, 1) - const ops = client.apply(documentId) + const ops = client.apply() ops.notMatch(documents.class.Document, { template: templateId, @@ -237,7 +237,7 @@ export async function createDocumentTemplate ( path = await getParentPath(client, parent) } - const ops = client.apply(templateId) + const ops = client.apply() ops.notMatch(documents.class.Document, { template: { $exists: false }, diff --git a/plugins/notification-resources/src/components/inbox/Inbox.svelte b/plugins/notification-resources/src/components/inbox/Inbox.svelte index 0ddef087c6..24791c2b5a 100644 --- a/plugins/notification-resources/src/components/inbox/Inbox.svelte +++ b/plugins/notification-resources/src/components/inbox/Inbox.svelte @@ -269,7 +269,7 @@ const contextNotifications = $notificationsByContextStore.get(selectedContext._id) ?? [] - const ops = getClient().apply(selectedContext._id, 'readNotifications') + const ops = getClient().apply(undefined, 'readNotifications') try { await inboxClient.readNotifications( ops, diff --git a/plugins/notification-resources/src/inboxNotificationsClient.ts b/plugins/notification-resources/src/inboxNotificationsClient.ts index e666ba7dff..19369b51d6 100644 --- a/plugins/notification-resources/src/inboxNotificationsClient.ts +++ b/plugins/notification-resources/src/inboxNotificationsClient.ts @@ -15,7 +15,6 @@ import activity from '@hcengineering/activity' import { SortingOrder, - generateId, getCurrentAccount, toIdMap, type Class, @@ -34,7 +33,6 @@ import notification, { } from '@hcengineering/notification' import { createQuery, getClient } from '@hcengineering/presentation' import { derived, get, writable } from 'svelte/store' - import { isActivityNotification } from './utils' /** @@ -237,7 +235,7 @@ export class InboxNotificationsClientImpl implements InboxNotificationsClient { } async archiveAllNotifications (): Promise { - const ops = getClient().apply(generateId(), 'archiveAllNotifications') + const ops = getClient().apply(undefined, 'archiveAllNotifications') try { const inboxNotifications = await ops.findAll( @@ -262,7 +260,7 @@ export class InboxNotificationsClientImpl implements InboxNotificationsClient { } async readAllNotifications (): Promise { - const ops = getClient().apply(generateId(), 'readAllNotifications') + const ops = getClient().apply(undefined, 'readAllNotifications') try { const inboxNotifications = await ops.findAll( @@ -287,7 +285,7 @@ export class InboxNotificationsClientImpl implements InboxNotificationsClient { } async unreadAllNotifications (): Promise { - const ops = getClient().apply(generateId(), 'unreadAllNotifications') + const ops = getClient().apply(undefined, 'unreadAllNotifications') try { const inboxNotifications = await ops.findAll( diff --git a/plugins/notification-resources/src/utils.ts b/plugins/notification-resources/src/utils.ts index 143383e8eb..8902af2918 100644 --- a/plugins/notification-resources/src/utils.ts +++ b/plugins/notification-resources/src/utils.ts @@ -128,7 +128,7 @@ export async function readNotifyContext (doc: DocNotifyContext): Promise { const inboxClient = InboxNotificationsClientImpl.getClient() const inboxNotifications = get(inboxClient.inboxNotificationsByContext).get(doc._id) ?? [] - const ops = getClient().apply(doc._id, 'readNotifyContext') + const ops = getClient().apply(undefined, 'readNotifyContext') try { await inboxClient.readNotifications( ops, @@ -152,7 +152,7 @@ export async function unReadNotifyContext (doc: DocNotifyContext): Promise return } - const ops = getClient().apply(doc._id, 'unReadNotifyContext') + const ops = getClient().apply(undefined, 'unReadNotifyContext') try { await inboxClient.unreadNotifications( @@ -183,7 +183,7 @@ export async function archiveContextNotifications (doc?: DocNotifyContext): Prom return } - const ops = getClient().apply(doc._id, 'archiveContextNotifications') + const ops = getClient().apply(undefined, 'archiveContextNotifications') try { const notifications = await ops.findAll( @@ -209,7 +209,7 @@ export async function unarchiveContextNotifications (doc?: DocNotifyContext): Pr return } - const ops = getClient().apply(doc._id, 'unarchiveContextNotifications') + const ops = getClient().apply(undefined, 'unarchiveContextNotifications') try { const notifications = await ops.findAll( diff --git a/plugins/products-resources/src/components/product-version/CreateProductVersion.svelte b/plugins/products-resources/src/components/product-version/CreateProductVersion.svelte index e4d64cb6f9..60fa5f2979 100644 --- a/plugins/products-resources/src/components/product-version/CreateProductVersion.svelte +++ b/plugins/products-resources/src/components/product-version/CreateProductVersion.svelte @@ -93,7 +93,7 @@ return } - const ops = client.apply(id) + const ops = client.apply() const version = { ...object, diff --git a/plugins/products-resources/src/components/product/CreateProduct.svelte b/plugins/products-resources/src/components/product/CreateProduct.svelte index 41804b1e7d..bb51aa1aa5 100644 --- a/plugins/products-resources/src/components/product/CreateProduct.svelte +++ b/plugins/products-resources/src/components/product/CreateProduct.svelte @@ -154,7 +154,7 @@ return } - const ops = client.apply(productId) + const ops = client.apply() await ops.createDoc( products.class.Product, diff --git a/plugins/questions-resources/src/actions/questionMoveDownAction.ts b/plugins/questions-resources/src/actions/questionMoveDownAction.ts index d1bce8659f..ad5320c818 100644 --- a/plugins/questions-resources/src/actions/questionMoveDownAction.ts +++ b/plugins/questions-resources/src/actions/questionMoveDownAction.ts @@ -2,7 +2,6 @@ // Copyright @ 2024 Hardcore Engineering Inc. // -import { generateId } from '@hcengineering/core' import { getClient } from '@hcengineering/presentation' import type { Question } from '@hcengineering/questions' import { canUpdateQuestion, findNextQuestion, updateQuestion } from '../utils' @@ -21,7 +20,7 @@ export const questionMoveDownAction = focusActionWithAvailability( diff --git a/plugins/recruit-resources/src/components/CreateCandidate.svelte b/plugins/recruit-resources/src/components/CreateCandidate.svelte index 9979348eea..df2b2808ba 100644 --- a/plugins/recruit-resources/src/components/CreateCandidate.svelte +++ b/plugins/recruit-resources/src/components/CreateCandidate.svelte @@ -222,7 +222,7 @@ } } - const applyOps = client.apply(_id, 'create-candidate') + const applyOps = client.apply(undefined, 'create-candidate') await applyOps.createDoc(contact.class.Person, contact.space.Contacts, candidate, _id) await applyOps.createMixin( diff --git a/plugins/recruit-resources/src/components/MoveApplication.svelte b/plugins/recruit-resources/src/components/MoveApplication.svelte index 6d174dd08d..2a64e4ef7a 100644 --- a/plugins/recruit-resources/src/components/MoveApplication.svelte +++ b/plugins/recruit-resources/src/components/MoveApplication.svelte @@ -19,6 +19,8 @@ import { OK, Severity, Status } from '@hcengineering/platform' import presentation, { Card, SpaceSelect, createQuery, getClient } from '@hcengineering/presentation' import type { Applicant, Vacancy } from '@hcengineering/recruit' + import { getStates } from '@hcengineering/task' + import { typeStore } from '@hcengineering/task-resources' import ui, { Button, ColorPopup, @@ -41,8 +43,6 @@ import ApplicationPresenter from './ApplicationPresenter.svelte' import VacancyCard from './VacancyCard.svelte' import VacancyOrgPresenter from './VacancyOrgPresenter.svelte' - import { getStates } from '@hcengineering/task' - import { typeStore } from '@hcengineering/task-resources' export let selected: Applicant[] @@ -65,7 +65,7 @@ throw new Error(`create application: state not found space:${_space}`) } - const op = client.apply(_space + 'application.states') + const op = client.apply(undefined, 'application.states') for (const a of selected) { await moveToSpace(op, a, _space, { status: selectedState._id }) diff --git a/plugins/recruit-resources/src/components/OptimizeSkills.svelte b/plugins/recruit-resources/src/components/OptimizeSkills.svelte index b2a2290e10..14ad404157 100644 --- a/plugins/recruit-resources/src/components/OptimizeSkills.svelte +++ b/plugins/recruit-resources/src/components/OptimizeSkills.svelte @@ -17,7 +17,7 @@ import { getEmbeddedLabel } from '@hcengineering/platform' import { Card, getClient } from '@hcengineering/presentation' import tags, { TagCategory, TagElement, TagReference } from '@hcengineering/tags' - import { Button, CheckBox, EditBox, Lazy, ListView, Loading, Expandable } from '@hcengineering/ui' + import { Button, CheckBox, EditBox, Expandable, Lazy, ListView, Loading } from '@hcengineering/ui' import { FILTER_DEBOUNCE_MS } from '@hcengineering/view-resources' import { createEventDispatcher } from 'svelte' import recruit from '../plugin' @@ -460,7 +460,7 @@ for (const item of searchPlanElements) { console.log('Apply', item.original.title) const st = Date.now() - const ops = client.apply('optimize:' + item.original._id) + const ops = client.apply(undefined, 'optimize-skill') let allRefs: TagReference[] = await client.findAll(tags.class.TagReference, { tag: item.original._id }) allRefs.sort((a, b) => (b.weight ?? 0) - (a.weight ?? 0)) diff --git a/plugins/setting-resources/src/components/spaceTypes/editor/SpaceTypeGeneralSectionEditor.svelte b/plugins/setting-resources/src/components/spaceTypes/editor/SpaceTypeGeneralSectionEditor.svelte index 35a9a50782..8a6758fc1d 100644 --- a/plugins/setting-resources/src/components/spaceTypes/editor/SpaceTypeGeneralSectionEditor.svelte +++ b/plugins/setting-resources/src/components/spaceTypes/editor/SpaceTypeGeneralSectionEditor.svelte @@ -70,7 +70,7 @@ if (push.size === 0 && pull.size === 0) { return } - const ops = client.apply(`typeMembers_${type._id}`) + const ops = client.apply(undefined, 'change-members') for (const pushMem of push) { ops.update(type, { $push: { members: pushMem } }) } diff --git a/plugins/setting/src/utils.ts b/plugins/setting/src/utils.ts index 97f9d46ee1..77fd611d12 100644 --- a/plugins/setting/src/utils.ts +++ b/plugins/setting/src/utils.ts @@ -134,7 +134,7 @@ export async function deleteSpaceTypeRole ( targetClass: Ref> ): Promise { const attribute = await client.findOne(core.class.Attribute, { name: role._id, attributeOf: targetClass }) - const ops = client.apply(role._id) + const ops = client.apply() await ops.removeCollection( core.class.Role, diff --git a/plugins/task-resources/src/components/StatusSelector.svelte b/plugins/task-resources/src/components/StatusSelector.svelte index a2cc2ab626..422d5c2831 100644 --- a/plugins/task-resources/src/components/StatusSelector.svelte +++ b/plugins/task-resources/src/components/StatusSelector.svelte @@ -1,11 +1,11 @@