From 377fb908babc51707871f59baf1e5607378601bb Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Mon, 16 Dec 2024 18:02:50 +0700 Subject: [PATCH] UBERF-8897 Use proper state when update collab doc activity (#7475) Signed-off-by: Alexander Onnikov --- server/collaborator/src/storage/platform.ts | 6 +- workers/collaborator/src/metrics.ts | 95 +++++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 workers/collaborator/src/metrics.ts diff --git a/server/collaborator/src/storage/platform.ts b/server/collaborator/src/storage/platform.ts index 3edccdd1ee..9855f62f31 100644 --- a/server/collaborator/src/storage/platform.ts +++ b/server/collaborator/src/storage/platform.ts @@ -16,7 +16,7 @@ import activity, { DocUpdateMessage } from '@hcengineering/activity' import { loadCollabJson, loadCollabYdoc, saveCollabJson, saveCollabYdoc } from '@hcengineering/collaboration' import { decodeDocumentId } from '@hcengineering/collaborator-client' -import core, { AttachedData, MeasureContext, TxOperations } from '@hcengineering/core' +import core, { AttachedData, MeasureContext, Ref, Space, TxOperations } from '@hcengineering/core' import { StorageAdapter } from '@hcengineering/server-core' import { markupToYDocNoSchema, areEqualMarkups } from '@hcengineering/text' import { Doc as YDoc } from 'yjs' @@ -173,6 +173,8 @@ export class PlatformStorageAdapter implements CollabStorageAdapter { await ctx.with('update', {}, () => client.diffUpdate(current, { [objectAttr]: blobId })) await ctx.with('activity', {}, () => { + const space = hierarchy.isDerived(current._class, core.class.Space) ? (current._id as Ref) : current.space + const data: AttachedData = { objectId, objectClass, @@ -189,7 +191,7 @@ export class PlatformStorageAdapter implements CollabStorageAdapter { } return client.addCollection( activity.class.DocUpdateMessage, - current.space, + space, current._id, current._class, 'docUpdateMessages', diff --git a/workers/collaborator/src/metrics.ts b/workers/collaborator/src/metrics.ts new file mode 100644 index 0000000000..5c800b879b --- /dev/null +++ b/workers/collaborator/src/metrics.ts @@ -0,0 +1,95 @@ +// +// Copyright © 2024 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the 'License'); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an 'AS IS' BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import { type Env } from './env' + +export async function withMetrics (name: string, fn: (ctx: MetricsContext) => Promise): Promise { + const ctx = new MetricsContext() + + const start = performance.now() + + try { + return await fn(ctx) + } finally { + const total = performance.now() - start + const ops = ctx.metrics + const message = `${name} total=${total} ` + ctx.toString() + console.log({ message, total, ops }) + } +} + +export interface MetricsData { + op: string + time: number +} + +export class MetricsContext { + metrics: Array = [] + + debug (...data: any[]): void { + console.debug(...data) + } + + log (...data: any[]): void { + console.log(...data) + } + + error (...data: any[]): void { + console.error(...data) + } + + async with(op: string, fn: () => Promise): Promise { + const start = performance.now() + try { + return await fn() + } finally { + const time = performance.now() - start + this.metrics.push({ op, time }) + } + } + + withSync(op: string, fn: () => T): T { + const start = performance.now() + try { + return fn() + } finally { + const time = performance.now() - start + this.metrics.push({ op, time }) + } + } + + toString (): string { + return this.metrics.map((p) => `${p.op}=${p.time}`).join(' ') + } +} + +export class LoggedDatalake { + constructor ( + private readonly datalake: Env['DATALAKE'], + private readonly ctx: MetricsContext + ) {} + + async getBlob (workspace: string, name: string): Promise { + return await this.ctx.with('datalake.getBlob', () => { + return this.datalake.getBlob(workspace, name) + }) + } + + async putBlob (workspace: string, name: string, data: ArrayBuffer | Blob | string, type: string): Promise { + await this.ctx.with('datalake.putBlob', () => { + return this.datalake.putBlob(workspace, name, data, type) + }) + } +}