mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-23 00:37:47 +00:00
UBERF-7690: Performance fixes (#6336)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
d502ba86d9
commit
87ded4d797
@ -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
|
||||
|
@ -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 },
|
||||
|
@ -199,7 +199,8 @@ export function createModel (builder: Builder): void {
|
||||
{ modifiedBy: 1 },
|
||||
{ createdBy: 1 },
|
||||
{ createdOn: -1 },
|
||||
{ state: 1 }
|
||||
{ state: 1 },
|
||||
{ _class: 1 }
|
||||
]
|
||||
})
|
||||
}
|
||||
|
@ -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 }
|
||||
]
|
||||
})
|
||||
}
|
||||
|
@ -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 }]
|
||||
})
|
||||
|
||||
|
@ -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, {
|
||||
|
@ -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)
|
||||
|
@ -254,7 +254,8 @@ export function createModel (builder: Builder): void {
|
||||
{ modifiedBy: 1 },
|
||||
{ createdBy: 1 },
|
||||
{ attachedToClass: 1 },
|
||||
{ createdOn: -1 }
|
||||
{ createdOn: -1 },
|
||||
{ modifiedOn: 1 }
|
||||
]
|
||||
})
|
||||
|
||||
|
@ -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, {
|
||||
|
@ -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: {
|
||||
|
@ -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 }
|
||||
)
|
||||
}
|
||||
}
|
||||
])
|
||||
},
|
||||
|
@ -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 } } })
|
||||
|
@ -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'
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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) => {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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, {
|
||||
|
@ -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 })
|
||||
|
@ -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: {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -385,7 +385,7 @@ export async function upgradeModel (
|
||||
|
||||
await tryMigrate(migrateClient, coreId, [
|
||||
{
|
||||
state: 'indexes-v3',
|
||||
state: 'indexes-v4',
|
||||
func: upgradeIndexes
|
||||
}
|
||||
])
|
||||
|
@ -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
|
||||
|
2
server/ws/.gitignore
vendored
2
server/ws/.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
v20.43.0.zip
|
||||
v*.zip
|
||||
src/uws
|
@ -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)
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user