UBERF-7690: Performance fixes (#6336)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-08-15 17:30:25 +07:00 committed by GitHub
parent d502ba86d9
commit 87ded4d797
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 200 additions and 103 deletions

View File

@ -67,7 +67,7 @@ async function hydrateNotificationAsYouCan (lastNotification: InboxNotification)
body: ''
}
const account = await client.findOne(contact.class.PersonAccount, { _id: lastNotification.modifiedBy as Ref<PersonAccount> })
const account = await client.getModel().findOne(contact.class.PersonAccount, { _id: lastNotification.modifiedBy as Ref<PersonAccount> })
if (account == null) {
return noPersonData

View File

@ -362,7 +362,6 @@ export function createModel (builder: Builder): void {
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_ACTIVITY,
indexes: [{ keys: { attachedTo: 1, createdOn: 1 } }, { keys: { attachedTo: 1, createdOn: -1 } }],
disabled: [
{ modifiedOn: 1 },
{ createdOn: -1 },

View File

@ -199,7 +199,8 @@ export function createModel (builder: Builder): void {
{ modifiedBy: 1 },
{ createdBy: 1 },
{ createdOn: -1 },
{ state: 1 }
{ state: 1 },
{ _class: 1 }
]
})
}

View File

@ -135,6 +135,14 @@ export function createModel (builder: Builder): void {
)
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_BITRIX,
disabled: [{ _id: 1 }, { _class: 1 }, { space: 1 }, { modifiedBy: 1 }, { createdBy: 1 }, { createdOn: -1 }]
disabled: [
{ _id: 1 },
{ _class: 1 },
{ space: 1 },
{ modifiedBy: 1 },
{ createdBy: 1 },
{ createdOn: -1 },
{ modifiedOn: 1 }
]
})
}

View File

@ -223,6 +223,7 @@ export class TContactsTab extends TDoc implements ContactsTab {
@Model(contact.class.PersonSpace, core.class.Space)
export class TPersonSpace extends TSpace implements PersonSpace {
@Prop(TypeRef(contact.class.Person), contact.string.Person)
@Index(IndexKind.Indexed)
person!: Ref<Person>
}
@ -1170,6 +1171,14 @@ export function createModel (builder: Builder): void {
})
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_CONTACT,
indexes: [
{
keys: {
_class: 1,
[contact.mixin.Employee + '.active']: 1
}
}
],
disabled: [{ attachedToClass: 1 }, { modifiedBy: 1 }, { createdBy: 1 }, { createdOn: -1 }, { attachedTo: 1 }]
})

View File

@ -197,6 +197,7 @@ export function createModel (builder: Builder): void {
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_TX,
disabled: [
{ _class: 1 },
{ space: 1 },
{ objectClass: 1 },
{ createdBy: 1 },
@ -267,7 +268,14 @@ export function createModel (builder: Builder): void {
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_STATUS,
disabled: [{ modifiedOn: 1 }, { modifiedBy: 1 }, { createdBy: 1 }, { createdBy: -1 }, { createdOn: -1 }]
disabled: [
{ modifiedOn: 1 },
{ modifiedBy: 1 },
{ createdBy: 1 },
{ createdBy: -1 },
{ createdOn: -1 },
{ space: 1 }
]
})
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_SPACE,
@ -276,7 +284,15 @@ export function createModel (builder: Builder): void {
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_BLOB,
disabled: [{ _class: 1 }, { space: 1 }, { modifiedBy: 1 }, { createdBy: 1 }, { createdBy: -1 }, { createdOn: -1 }]
disabled: [
{ _class: 1 },
{ space: 1 },
{ modifiedBy: 1 },
{ createdBy: 1 },
{ createdBy: -1 },
{ createdOn: -1 },
{ modifiedOn: 1 }
]
})
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {

View File

@ -14,22 +14,22 @@
//
import {
DOMAIN_MODEL,
IndexKind,
type Account,
type AccountRole,
type Arr,
type Class,
type CollectionSize,
type Domain,
DOMAIN_MODEL,
IndexKind,
type Permission,
type Ref,
type Role,
type RolesAssignment,
type Space,
type TypedSpace,
type SpaceType,
type SpaceTypeDescriptor,
type Role,
type Class,
type Permission,
type CollectionSize,
type RolesAssignment
type TypedSpace
} from '@hcengineering/core'
import {
ArrOf,
@ -46,7 +46,7 @@ import {
} from '@hcengineering/model'
import { getEmbeddedLabel, type Asset, type IntlString } from '@hcengineering/platform'
import core from './component'
import { TDoc, TAttachedDoc } from './core'
import { TAttachedDoc, TDoc } from './core'
export const DOMAIN_SPACE = 'space' as Domain
@ -67,6 +67,7 @@ export class TSpace extends TDoc implements Space {
private!: boolean
@Prop(TypeBoolean(), core.string.Archived)
@Index(IndexKind.Indexed)
archived!: boolean
@Prop(ArrOf(TypeRef(core.class.Account)), core.string.Members)

View File

@ -254,7 +254,8 @@ export function createModel (builder: Builder): void {
{ modifiedBy: 1 },
{ createdBy: 1 },
{ attachedToClass: 1 },
{ createdOn: -1 }
{ createdOn: -1 },
{ modifiedOn: 1 }
]
})

View File

@ -16,6 +16,7 @@
import activity, { type ActivityMessage } from '@hcengineering/activity'
import chunter from '@hcengineering/chunter'
import { type PersonSpace } from '@hcengineering/contact'
import {
AccountRole,
DOMAIN_MODEL,
@ -49,7 +50,6 @@ import {
UX,
type Builder
} from '@hcengineering/model'
import { type PersonSpace } from '@hcengineering/contact'
import core, { TClass, TDoc } from '@hcengineering/model-core'
import preference, { TPreference } from '@hcengineering/model-preference'
import view, { createAction, template } from '@hcengineering/model-view'
@ -201,7 +201,6 @@ export class TDocNotifyContext extends TDoc implements DocNotifyContext {
objectId!: Ref<Doc>
@Prop(TypeRef(core.class.Class), core.string.Class)
@Index(IndexKind.Indexed)
objectClass!: Ref<Class<Doc>>
@Prop(TypeRef(core.class.Space), core.string.Space)
@ -632,7 +631,7 @@ export function createModel (builder: Builder): void {
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {
domain: DOMAIN_NOTIFICATION,
indexes: [{ keys: { user: 1, archived: 1 } }],
indexes: [{ keys: { user: 1, archived: 1, space: 1 } }],
disabled: [{ modifiedOn: 1 }, { modifiedBy: 1 }, { createdBy: 1 }, { isViewed: 1 }, { hidden: 1 }]
})
@ -647,7 +646,8 @@ export function createModel (builder: Builder): void {
{ isViewed: 1 },
{ hidden: 1 },
{ createdOn: -1 },
{ attachedTo: 1 }
{ attachedTo: 1 },
{ space: 1 }
]
})
builder.createDoc(core.class.DomainIndexConfiguration, core.space.Model, {

View File

@ -480,7 +480,7 @@ export function createModel (builder: Builder): void {
sortable: true
},
baseQuery: {
isDone: { $ne: true },
isDone: false,
'$lookup.space.archived': false
}
},
@ -500,7 +500,7 @@ export function createModel (builder: Builder): void {
}
},
baseQuery: {
isDone: { $ne: true },
isDone: false,
'$lookup.space.archived': false
}
},
@ -796,7 +796,7 @@ export function createModel (builder: Builder): void {
descriptor: task.viewlet.Kanban,
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
baseQuery: {
isDone: { $ne: true },
isDone: false,
'$lookup.space.archived': false
},
viewOptions: {

View File

@ -60,6 +60,16 @@ export const recruitOperation: MigrateOperation = {
func: async (client: MigrationClient) => {
await migrateSpace(client, 'recruit:space:Reviews' as Ref<Space>, core.space.Workspace, [DOMAIN_CALENDAR])
}
},
{
state: 'migrate-applicants',
func: async (client: MigrationClient) => {
await client.update(
DOMAIN_TASK,
{ _class: recruit.class.Applicant, isDone: { $nin: [false, true] } },
{ isDone: false }
)
}
}
])
},

View File

@ -15,6 +15,7 @@
import { getEmbeddedLabel, IntlString } 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)
@ -604,9 +604,10 @@ export const isEnum =
export async function checkPermission (
client: TxOperations,
_id: Ref<Permission>,
_space: Ref<TypedSpace>
_space: Ref<TypedSpace>,
space?: TypedSpace
): Promise<boolean> {
const space = await client.findOne(core.class.TypedSpace, { _id: _space })
space = space ?? (await client.findOne(core.class.TypedSpace, { _id: _space }))
const type = await client
.getModel()
.findOne(core.class.SpaceType, { _id: space?.type }, { lookup: { _id: { roles: core.class.Role } } })

View File

@ -16,7 +16,7 @@ import type { AttachedDoc, Class, Doc, Markup, Mixin, Ref, SystemSpace, Timestam
import { NotificationType } from '@hcengineering/notification'
import type { Asset, IntlString, Metadata, Plugin } from '@hcengineering/platform'
import { plugin } from '@hcengineering/platform'
import type { Handler, IntegrationType } from '@hcengineering/setting'
import { Handler, IntegrationType } from '@hcengineering/setting'
import { AnyComponent, ComponentExtensionId } from '@hcengineering/ui'
/**

View File

@ -320,7 +320,7 @@ function fillStores (): void {
const accountPersonQuery = createQuery(true)
const query = createQuery(true)
query.query(contact.mixin.Employee, {}, (res) => {
query.query(contact.mixin.Employee, { [contact.mixin.Employee + '.active']: { $in: [true, false] } }, (res) => {
employeesStore.set(res)
employeeByIdStore.set(toIdMap(res))
})
@ -331,13 +331,10 @@ function fillStores (): void {
const persons = res.map((it) => it.person)
accountPersonQuery.query<Person>(
contact.class.Person,
{ _id: { $in: persons }, [contact.mixin.Employee]: { $exists: false } },
(res) => {
personAccountPersonByIdStore.set(toIdMap(res))
}
)
accountPersonQuery.query<Person>(contact.class.Person, { _id: { $in: persons } }, (res) => {
const personIn = toIdMap(res)
personAccountPersonByIdStore.set(personIn)
})
})
const providerQuery = createQuery(true)

View File

@ -112,12 +112,8 @@ export class InboxNotificationsClientImpl implements InboxNotificationsClient {
user: getCurrentAccount()._id
},
(result: InboxNotification[]) => {
result.sort((a, b) => (b.createdOn ?? b.modifiedOn) - (a.createdOn ?? a.modifiedOn))
this.otherInboxNotifications.set(result)
},
{
sort: {
createdOn: SortingOrder.Descending
}
}
)

View File

@ -14,7 +14,7 @@
-->
<script lang="ts">
import { DocumentQuery, Ref } from '@hcengineering/core'
import type { IntlString, Asset } from '@hcengineering/platform'
import type { Asset, IntlString } from '@hcengineering/platform'
import { createQuery } from '@hcengineering/presentation'
import { Issue, IssueStatus, Project } from '@hcengineering/tracker'
import { IModeSelector, resolvedLocationStore } from '@hcengineering/ui'
@ -41,18 +41,20 @@
let query: DocumentQuery<Issue> | undefined = undefined
let modeSelectorProps: IModeSelector | undefined = undefined
const archivedProjectQuery = createQuery()
let archived: Ref<Project>[] = []
const allProjectQuery = createQuery()
let allProjects: Pick<Project, '_id' | '_class' | 'archived'>[] = []
archivedProjectQuery.query(
allProjectQuery.query(
tracker.class.Project,
{ archived: true },
{},
(res) => {
archived = res.map((it) => it._id)
allProjects = res
},
{ projection: { _id: 1 } }
{ projection: { _id: 1, archived: 1 } }
)
$: spaceQuery = currentSpace ? { space: currentSpace } : { space: { $nin: archived } }
$: spaceQuery = currentSpace
? { space: currentSpace }
: { space: { $in: allProjects.filter((it) => !it.archived).map((it) => it._id) } }
$: all = { ...baseQuery, ...spaceQuery }

View File

@ -75,16 +75,16 @@
{ sort: { _id: 1 }, projection: { _id: 1 } }
)
const archivedProjectQuery = createQuery()
let archived: Ref<Project>[] = []
const allProjectQuery = createQuery()
let allProjects: Pick<Project, '_class' | '_id' | 'archived'>[] = []
archivedProjectQuery.query(
allProjectQuery.query(
tracker.class.Project,
{ archived: true },
{},
(res) => {
archived = res.map((it) => it._id)
allProjects = res
},
{ projection: { _id: 1 } }
{ projection: { _id: 1, archived: 1 } }
)
$: queries = { assigned, active, backlog, created, subscribed }
@ -95,7 +95,7 @@
$: if (mode !== undefined) {
query = { ...(queries as any)[mode] }
if (query?.space === undefined) {
query = { ...query, space: { $nin: archived } }
query = { ...query, space: { $in: allProjects.filter((it) => !it.archived).map((it) => it._id) } }
}
modeSelectorProps = {
config,

View File

@ -1496,6 +1496,14 @@ export const permissionsStore = writable<PermissionsStore>({
whitelist: new Set()
})
const spaceSpaceQuery = createQuery(true)
export const spaceSpace = writable<TypedSpace | undefined>(undefined)
spaceSpaceQuery.query(core.class.TypedSpace, { _id: core.space.Space }, (res) => {
spaceSpace.set(res[0])
})
const spaceTypesQuery = createQuery(true)
const permissionsQuery = createQuery(true)
type TargetClassesProjection = Record<Ref<Class<Space>>, number>

View File

@ -13,8 +13,17 @@
// limitations under the License.
//
import core, { checkPermission, type Space, type Doc, type TypedSpace, getCurrentAccount } from '@hcengineering/core'
import core, {
checkPermission,
getCurrentAccount,
toIdMap,
type Doc,
type Space,
type TypedSpace
} from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { get } from 'svelte/store'
import { spaceSpace } from './utils'
function isTypedSpace (space: Space): space is TypedSpace {
return getClient().getHierarchy().isDerived(space._class, core.class.TypedSpace)
@ -28,14 +37,14 @@ export async function canDeleteObject (doc?: Doc | Doc[]): Promise<boolean> {
const client = getClient()
const targets = Array.isArray(doc) ? doc : [doc]
// Note: allow deleting objects in NOT typed spaces for now
const targetSpaces = (await client.findAll(core.class.Space, { _id: { $in: targets.map((t) => t.space) } })).filter(
isTypedSpace
const targetSpaces = toIdMap(
(await client.findAll(core.class.Space, { _id: { $in: targets.map((t) => t.space) } })).filter(isTypedSpace)
)
return !(
await Promise.all(
Array.from(new Set(targetSpaces.map((t) => t._id))).map(
async (s) => await checkPermission(client, core.permission.ForbidDeleteObject, s)
Array.from(targetSpaces.entries()).map(
async (s) => await checkPermission(client, core.permission.ForbidDeleteObject, s[0], s[1])
)
)
).some((r) => r)
@ -54,11 +63,13 @@ export async function canEditSpace (doc?: Doc | Doc[]): Promise<boolean> {
const client = getClient()
if (await checkPermission(client, core.permission.UpdateObject, core.space.Space)) {
const _spaceSpace = get(spaceSpace) ?? (await client.findOne(core.class.TypedSpace, { _id: core.space.Space }))
if (await checkPermission(client, core.permission.UpdateObject, core.space.Space, _spaceSpace)) {
return true
}
if (isTypedSpace(space) && (await checkPermission(client, core.permission.UpdateSpace, space._id))) {
if (isTypedSpace(space) && (await checkPermission(client, core.permission.UpdateSpace, space._id, space))) {
return true
}
@ -78,11 +89,13 @@ export async function canArchiveSpace (doc?: Doc | Doc[]): Promise<boolean> {
const client = getClient()
if (await checkPermission(client, core.permission.DeleteObject, core.space.Space)) {
const _spaceSpace = get(spaceSpace) ?? (await client.findOne(core.class.TypedSpace, { _id: core.space.Space }))
if (await checkPermission(client, core.permission.DeleteObject, core.space.Space, _spaceSpace)) {
return true
}
if (isTypedSpace(space) && (await checkPermission(client, core.permission.ArchiveSpace, space._id))) {
if (isTypedSpace(space) && (await checkPermission(client, core.permission.ArchiveSpace, space._id, space))) {
return true
}
@ -102,7 +115,9 @@ export async function canDeleteSpace (doc?: Doc | Doc[]): Promise<boolean> {
const client = getClient()
if (await checkPermission(client, core.permission.DeleteObject, core.space.Space)) {
const _spaceSpace = get(spaceSpace) ?? (await client.findOne(core.class.TypedSpace, { _id: core.space.Space }))
if (await checkPermission(client, core.permission.DeleteObject, core.space.Space, _spaceSpace)) {
return true
}

View File

@ -41,12 +41,14 @@
let shownSpaces: Space[] = []
$: if (model) {
const classes = getSpecialSpaceClass(model).flatMap((c) => hierarchy.getDescendants(c))
const classes = Array.from(new Set(getSpecialSpaceClass(model).flatMap((c) => hierarchy.getDescendants(c)))).filter(
(it) => !hierarchy.isMixin(it)
)
if (classes.length > 0) {
query.query(
core.class.Space,
classes.length === 1 ? classes[0] : core.class.Space,
{
_class: classes.length === 1 ? classes[0] : { $in: classes },
...(classes.length === 1 ? {} : { _class: { $in: classes } }),
members: getCurrentAccount()._id
},
(result) => {

View File

@ -2,7 +2,7 @@ FROM node:20
WORKDIR /usr/src/app
RUN npm install --ignore-scripts=false --verbose bufferutil utf-8-validate @mongodb-js/zstd snappy --unsafe-perm
RUN npm install --ignore-scripts=false --verbose uNetworking/uWebSockets.js#v20.43.0
RUN npm install --ignore-scripts=false --verbose uNetworking/uWebSockets.js#v20.47.0
RUN apt-get update
RUN apt-get install libjemalloc2

View File

@ -122,10 +122,11 @@ async function handleVacancyUpdate (control: TriggerControl, cud: TxCUD<Doc>, re
const updateTx = cud as TxUpdateDoc<Vacancy>
if (updateTx.operations.company !== undefined) {
// It could be null or new value
const txes = await control.findAll(core.class.TxCUD, {
objectId: updateTx.objectId,
_id: { $nin: [updateTx._id] }
})
const txes = (
await control.findAll(core.class.TxCUD, {
objectId: updateTx.objectId
})
).filter((it) => it._id !== updateTx._id)
const vacancy = TxProcessor.buildDoc2Doc(txes) as Vacancy
if (vacancy.company != null) {
// We have old value
@ -162,10 +163,11 @@ async function handleVacancyRemove (control: TriggerControl, cud: TxCUD<Doc>, ac
if (control.hierarchy.isDerived(cud.objectClass, recruit.class.Vacancy)) {
const removeTx = actualTx as TxRemoveDoc<Vacancy>
// It could be null or new value
const txes = await control.findAll(core.class.TxCUD, {
objectId: removeTx.objectId,
_id: { $nin: [removeTx._id] }
})
const txes = (
await control.findAll(core.class.TxCUD, {
objectId: removeTx.objectId
})
).filter((it) => it._id !== removeTx._id)
const vacancy = TxProcessor.buildDoc2Doc(txes) as Vacancy
const res: Tx[] = []
if (vacancy.company != null) {

View File

@ -44,11 +44,9 @@ export async function getValue (control: TriggerControl, context: Record<string,
}
async function getEmployee (control: TriggerControl, _id: Ref<Account>): Promise<Person | undefined> {
const employeeAccount = (
await control.modelDb.findAll(contact.class.PersonAccount, {
_id: _id as Ref<PersonAccount>
})
)[0]
const employeeAccount = control.modelDb.findAllSync(contact.class.PersonAccount, {
_id: _id as Ref<PersonAccount>
})[0]
if (employeeAccount !== undefined) {
const employee = (
await control.findAll(contact.class.Person, {

View File

@ -321,11 +321,12 @@ async function doTimeReportUpdate (cud: TxCUD<TimeSpendReport>, tx: Tx, control:
if (upd.operations.value !== undefined) {
const logTxes = Array.from(
await control.findAll(core.class.TxCollectionCUD, {
'tx.objectId': cud.objectId,
_id: { $nin: [parentTx._id] }
'tx.objectId': cud.objectId
})
)
.filter((it) => it._id !== parentTx._id)
// eslint-disable-next-line @typescript-eslint/unbound-method
).map(TxProcessor.extractTx)
.map(TxProcessor.extractTx)
const doc: TimeSpendReport | undefined = TxProcessor.buildDoc2Doc(logTxes)
const res: Tx[] = []
@ -357,11 +358,12 @@ async function doTimeReportUpdate (cud: TxCUD<TimeSpendReport>, tx: Tx, control:
if (!control.removedMap.has(parentTx.objectId)) {
const logTxes = Array.from(
await control.findAll(core.class.TxCollectionCUD, {
'tx.objectId': cud.objectId,
_id: { $nin: [parentTx._id] }
'tx.objectId': cud.objectId
})
)
.filter((it) => it._id !== parentTx._id)
// eslint-disable-next-line @typescript-eslint/unbound-method
).map(TxProcessor.extractTx)
.map(TxProcessor.extractTx)
const doc: TimeSpendReport | undefined = TxProcessor.buildDoc2Doc(logTxes)
if (doc !== undefined) {
const [currentIssue] = await control.findAll(tracker.class.Issue, { _id: parentTx.objectId }, { limit: 1 })

View File

@ -44,6 +44,10 @@ export class DomainIndexHelperImpl implements DomainHelper {
const attrs = hierarchy.getAllAttributes(c._id)
const domainAttrs = this.domains.get(domain) ?? new Set<FieldIndexConfig<Doc>>()
for (const a of attrs.values()) {
if (a.isCustom === true) {
// Skip custom attribute indexes
continue
}
if (a.index !== undefined && a.index !== IndexKind.FullText) {
domainAttrs.add({
keys: {

View File

@ -115,7 +115,19 @@ interface LookupStep {
}
export async function toArray<T> (cursor: AbstractCursor<T>): Promise<T[]> {
const data = await cursor.toArray()
const data: T[] = []
while (true) {
const d = await cursor.next()
if (d === null) {
break
}
data.push(d)
const batch = cursor.readBufferedDocuments()
if (batch.length > 0) {
data.push(...batch)
}
}
await cursor.close()
return data
}

View File

@ -125,14 +125,26 @@ export function getMongoClient (uri: string, options?: MongoClientOptions): Mong
const key = `${uri}${process.env.MONGO_OPTIONS ?? '{}'}_${JSON.stringify(options ?? {})}`
let existing = connections.get(key)
const allOptions: MongoClientOptions = {
...options,
...extraOptions
}
// Make poll size stable
if (allOptions.maxPoolSize !== undefined) {
allOptions.minPoolSize = allOptions.maxPoolSize
}
allOptions.monitorCommands = false
allOptions.noDelay = true
// If not created or closed
if (existing === undefined) {
existing = new MongoClientReferenceImpl(
MongoClient.connect(uri, {
appName: 'transactor',
...options,
...extraOptions,
enableUtf8Validation: false
enableUtf8Validation: false,
...allOptions
}),
() => {
connections.delete(key)

View File

@ -385,7 +385,7 @@ export async function upgradeModel (
await tryMigrate(migrateClient, coreId, [
{
state: 'indexes-v3',
state: 'indexes-v4',
func: upgradeIndexes
}
])

View File

@ -2,9 +2,9 @@
mkdir -p ./.build
cd ./.build
if ! test -f ./v20.43.0.zip; then
wget --quiet https://github.com/uNetworking/uWebSockets.js/archive/refs/tags/v20.43.0.zip
if ! test -f ./v20.47.0.zip; then
wget --quiet https://github.com/uNetworking/uWebSockets.js/archive/refs/tags/v20.47.0.zip
fi
if ! test -f ../lib/uws.js; then
unzip -qq -j -o ./v20.43.0.zip -d ../lib
unzip -qq -j -o ./v20.47.0.zip -d ../lib
fi

View File

@ -1,2 +1,2 @@
v20.43.0.zip
v*.zip
src/uws

View File

@ -80,12 +80,13 @@ export function startHttpServer (
const token = req.query.token as string
const payload = decodeToken(token)
const admin = payload.extra?.admin === 'true'
res.writeHead(200, { 'Content-Type': 'application/json' })
const json = JSON.stringify({
const jsonData = {
...getStatistics(ctx, sessions, admin),
users: getUsers,
users: getUsers(),
admin
})
}
const json = JSON.stringify(jsonData)
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(json)
} catch (err: any) {
Analytics.handleError(err)

View File

@ -21,10 +21,10 @@ import core, {
type Class,
type TxMixin
} from '@hcengineering/core'
import github, { DocSyncInfo, GithubProject } from '@hcengineering/github'
import { TriggerControl } from '@hcengineering/server-core'
import time, { ToDo } from '@hcengineering/time'
import tracker from '@hcengineering/tracker'
import github, { DocSyncInfo, GithubProject } from '@hcengineering/github'
/**
* @public
@ -124,7 +124,7 @@ async function updateDocSyncInfo (
}
}
const [account] = await control.modelDb.findAll(contact.class.PersonAccount, {
const [account] = control.modelDb.findAllSync(contact.class.PersonAccount, {
_id: tx.modifiedBy as Ref<PersonAccount>
})
// Do not modify state if is modified by github service.