diff --git a/.vscode/launch.json b/.vscode/launch.json index 090cdf176a..7c1bf86405 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -100,6 +100,7 @@ "ACCOUNTS_URL": "http://localhost:3000", "UPLOAD_URL": "/files", "SERVER_PORT": "8087", + "VERSION": null, "COLLABORATOR_URL": "ws://localhost:3078", "COLLABORATOR_API_URL": "http://localhost:3078", "CALENDAR_URL": "http://localhost:8095", diff --git a/common/scripts/version.txt b/common/scripts/version.txt index 0fa1e44bad..2974978539 100644 --- a/common/scripts/version.txt +++ b/common/scripts/version.txt @@ -1 +1 @@ -"0.6.270" \ No newline at end of file +"0.6.271" \ No newline at end of file diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index d8fb0b1c6d..23377590e8 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -77,6 +77,7 @@ services: - ACCOUNTS_URL=http://account:3000 - UPLOAD_URL=/files - MONGO_URL=mongodb://mongodb:27017?compressors=snappy + - 'MONGO_OPTIONS={"appName":"collaborator","maxPoolSize":2}' - STORAGE_CONFIG=${STORAGE_CONFIG} restart: unless-stopped front: @@ -95,6 +96,7 @@ services: - SERVER_PORT=8080 - SERVER_SECRET=secret - MONGO_URL=mongodb://mongodb:27017?compressors=snappy + - 'MONGO_OPTIONS={"appName":"front","maxPoolSize":1}' - ACCOUNTS_URL=http://localhost:3000 - UPLOAD_URL=/files - ELASTIC_URL=http://elastic:9200 @@ -135,6 +137,7 @@ services: - ENABLE_COMPRESSION=true - ELASTIC_URL=http://elastic:9200 - MONGO_URL=mongodb://mongodb:27017?compressors=snappy + - 'MONGO_OPTIONS={"appName": "transactor", "maxPoolSize": 1}' - METRICS_CONSOLE=false - METRICS_FILE=metrics.txt - STORAGE_CONFIG=${STORAGE_CONFIG} @@ -165,6 +168,7 @@ services: environment: - SECRET=secret - MONGO_URL=mongodb://mongodb:27017?compressors=snappy + - 'MONGO_OPTIONS={"appName":"print","maxPoolSize":1}' - STORAGE_CONFIG=${STORAGE_CONFIG} deploy: resources: @@ -181,6 +185,7 @@ services: environment: - SECRET=secret - MONGO_URL=mongodb://mongodb:27017 + - 'MONGO_OPTIONS={"appName":"sign","maxPoolSize":1}' - MINIO_ENDPOINT=minio - MINIO_ACCESS_KEY=minioadmin - ACCOUNTS_URL=http://account:3000 @@ -201,6 +206,7 @@ services: - SECRET=secret - PORT=4007 - MONGO_URL=mongodb://mongodb:27017 + - 'MONGO_OPTIONS={"appName":"analytics","maxPoolSize":1}' - SERVICE_ID=analytics-collector-service - ACCOUNTS_URL=http://account:3000 - SUPPORT_WORKSPACE=support diff --git a/models/core/src/security.ts b/models/core/src/security.ts index c4934e58c0..fa694867e3 100644 --- a/models/core/src/security.ts +++ b/models/core/src/security.ts @@ -70,6 +70,7 @@ export class TSpace extends TDoc implements Space { archived!: boolean @Prop(ArrOf(TypeRef(core.class.Account)), core.string.Members) + @Index(IndexKind.Indexed) members!: Arr> @Prop(ArrOf(TypeRef(core.class.Account)), core.string.Owners) diff --git a/models/preference/src/index.ts b/models/preference/src/index.ts index c6cfc8477b..0e2ae21cae 100644 --- a/models/preference/src/index.ts +++ b/models/preference/src/index.ts @@ -39,6 +39,6 @@ export function createModel (builder: Builder): void { builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, { domain: DOMAIN_PREFERENCE, - disabled: [{ modifiedOn: 1 }, { createdOn: 1 }] + disabled: [{ modifiedOn: 1 }, { createdOn: 1 }, { attachedTo: 1 }, { createdOn: -1 }, { modifiedBy: 1 }] }) } diff --git a/models/tags/src/index.ts b/models/tags/src/index.ts index 64a2531fc2..ffc707da9b 100644 --- a/models/tags/src/index.ts +++ b/models/tags/src/index.ts @@ -148,6 +148,7 @@ export function createModel (builder: Builder): void { builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, { domain: DOMAIN_TAGS, disabled: [ + { _class: 1 }, { modifiedOn: 1 }, { modifiedBy: 1 }, { createdBy: 1 }, diff --git a/packages/core/src/measurements/metrics.ts b/packages/core/src/measurements/metrics.ts index fbef8f77f9..d3a9ae014d 100644 --- a/packages/core/src/measurements/metrics.ts +++ b/packages/core/src/measurements/metrics.ts @@ -1,7 +1,6 @@ // Basic performance metrics suite. import { MetricsData } from '.' -import { cutObjectArray } from '../utils' import { FullParamsType, Metrics, ParamsType } from './types' /** @@ -35,7 +34,7 @@ function getUpdatedTopResult ( const newValue = { value: time, - params: cutObjectArray(params) + params } if (result.length > 6) { diff --git a/packages/core/src/operations.ts b/packages/core/src/operations.ts index 94e45c3ec9..4c70d569a7 100644 --- a/packages/core/src/operations.ts +++ b/packages/core/src/operations.ts @@ -487,9 +487,13 @@ export class ApplyOperations extends TxOperations { extraNotify ) )) as Promise) + const dnow = Date.now() + if (typeof window === 'object' && window !== null) { + console.log(`measure ${this.measureName}`, dnow - st, 'server time', result.serverTime) + } return { result: result.success, - time: Date.now() - st, + time: dnow - st, serverTime: result.serverTime } } diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index 2fe36d2e10..075f0f535e 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -13,8 +13,9 @@ // limitations under the License. // -import { getEmbeddedLabel, IntlString } from '@hcengineering/platform' +import { getEmbeddedLabel, IntlString, PlatformError, unknownError } from '@hcengineering/platform' import { deepEqual } from 'fast-equals' +import { DOMAIN_BENCHMARK } from './benchmark' import { Account, AccountRole, @@ -46,7 +47,6 @@ import { TxOperations } from './operations' import { isPredicate } from './predicate' import { DocumentQuery, FindResult } from './storage' import { DOMAIN_TX } from './tx' -import { DOMAIN_BENCHMARK } from './benchmark' function toHex (value: number, chars: number): string { const result = value.toString(16) @@ -355,7 +355,6 @@ export class DocManager implements IDocManager { export class RateLimiter { idCounter: number = 0 - processingQueue = new Map>() last: number = 0 rate: number @@ -366,21 +365,21 @@ export class RateLimiter { } notify: (() => void)[] = [] + finished: boolean = false async exec = any>(op: (args?: B) => Promise, args?: B): Promise { - const processingId = this.idCounter++ - - while (this.processingQueue.size >= this.rate) { + if (this.finished) { + throw new PlatformError(unknownError('No Possible to add/exec on finished queue')) + } + while (this.notify.length >= this.rate) { await new Promise((resolve) => { this.notify.push(resolve) }) } try { const p = op(args) - this.processingQueue.set(processingId, p as Promise) return await p } finally { - this.processingQueue.delete(processingId) const n = this.notify.shift() if (n !== undefined) { n() @@ -389,7 +388,7 @@ export class RateLimiter { } async add = any>(op: (args?: B) => Promise, args?: B): Promise { - if (this.processingQueue.size < this.rate) { + if (this.notify.length < this.rate) { void this.exec(op, args) } else { await this.exec(op, args) @@ -397,7 +396,12 @@ export class RateLimiter { } async waitProcessing (): Promise { - await Promise.all(this.processingQueue.values()) + this.finished = true + while (this.notify.length > 0) { + await new Promise((resolve) => { + this.notify.push(resolve) + }) + } } } diff --git a/packages/presentation/src/pipeline.ts b/packages/presentation/src/pipeline.ts index 79f3fe6663..cd75ef2672 100644 --- a/packages/presentation/src/pipeline.ts +++ b/packages/presentation/src/pipeline.ts @@ -9,6 +9,7 @@ import { type FindResult, type Hierarchy, type ModelDb, + type QuerySelector, type Ref, type SearchOptions, type SearchQuery, @@ -330,6 +331,22 @@ export class OptimizeQueryMiddleware extends BasePresentationMiddleware implemen const fQuery = { ...query } const fOptions = { ...options } this.optimizeQuery(fQuery, fOptions) + + // Immidiate response queries, if have some $in with empty list. + + for (const [k, v] of Object.entries(fQuery)) { + if (typeof v === 'object' && v != null) { + const vobj = v as QuerySelector + if (vobj.$in != null && vobj.$in.length === 0) { + // Emopty in, will always return [] + return toFindResult([], 0) + } else if (vobj.$in != null && vobj.$in.length === 1 && Object.keys(vobj).length === 1) { + ;(fQuery as any)[k] = vobj.$in[0] + } else if (vobj.$nin != null && vobj.$nin.length === 1 && Object.keys(vobj).length === 1) { + ;(fQuery as any)[k] = { $ne: vobj.$nin[0] } + } + } + } return await this.provideFindAll(_class, fQuery, fOptions) } diff --git a/packages/ui/src/tooltips.ts b/packages/ui/src/tooltips.ts index 14a043c543..0a3e478599 100644 --- a/packages/ui/src/tooltips.ts +++ b/packages/ui/src/tooltips.ts @@ -28,6 +28,10 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any { if (options === undefined) { return {} } + if (options.label === undefined && options.component === undefined) { + // No tooltip + return {} + } let opt = options const show = (): void => { const shown = !!(storedValue.label !== undefined || storedValue.component !== undefined) @@ -113,7 +117,7 @@ export function showTooltip ( props, anchor, onUpdate, - kind, + kind: kind ?? 'tooltip', keys, type: 'tooltip' } diff --git a/plugins/attachment-resources/src/components/AttachmentStyledBox.svelte b/plugins/attachment-resources/src/components/AttachmentStyledBox.svelte index 29a3581897..c87a8ad08e 100644 --- a/plugins/attachment-resources/src/components/AttachmentStyledBox.svelte +++ b/plugins/attachment-resources/src/components/AttachmentStyledBox.svelte @@ -13,23 +13,23 @@ // limitations under the License. --> + + + + + +
{ + dispatch('changeContent') + }} + on:keydown={onKeydown} +> + {#if searchable} +
+ +
+ {:else} +