mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 21:50:34 +03:00
TSK-803: Fix load speed (#2728)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
parent
b6980f307e
commit
9eddd84ada
@ -34,8 +34,10 @@ import {
|
||||
DOMAIN_MODEL,
|
||||
Enum,
|
||||
EnumOf,
|
||||
FieldIndex,
|
||||
FullTextData,
|
||||
FullTextSearchContext,
|
||||
IndexingConfiguration,
|
||||
IndexKind,
|
||||
IndexStageState,
|
||||
Interface,
|
||||
@ -249,15 +251,22 @@ export class TFulltextData extends TDoc implements FullTextData {
|
||||
export class TDocIndexState extends TDoc implements DocIndexState {
|
||||
objectClass!: Ref<Class<Doc>>
|
||||
|
||||
attachedTo?: Ref<Doc>
|
||||
attachedToClass?: Ref<Class<Doc>>
|
||||
@Prop(TypeRef(core.class.Doc), core.string.AttachedTo)
|
||||
@Index(IndexKind.Indexed)
|
||||
@Hidden()
|
||||
attachedTo?: Ref<Doc>
|
||||
|
||||
@Prop(TypeRef(core.class.Doc), core.string.AttachedToClass)
|
||||
@Index(IndexKind.Indexed)
|
||||
@Hidden()
|
||||
attachedToClass?: Ref<Class<Doc>>
|
||||
|
||||
// Indexable attributes of document.
|
||||
attributes!: Record<string, any>
|
||||
|
||||
removed!: boolean
|
||||
|
||||
// States for diffetent stages
|
||||
// States for different stages
|
||||
stages!: Record<string, boolean | string>
|
||||
}
|
||||
|
||||
@ -284,3 +293,8 @@ export class TConfiguration extends TDoc implements Configuration {
|
||||
@Prop(TypeBoolean(), core.string.Private)
|
||||
enabled!: boolean
|
||||
}
|
||||
|
||||
@MMixin(core.mixin.IndexConfiguration, core.class.Class)
|
||||
export class TIndexConfiguration<T extends Doc = Doc> extends TClass implements IndexingConfiguration<T> {
|
||||
indexes!: FieldIndex<T>[]
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { AccountRole } from '@hcengineering/core'
|
||||
import { AccountRole, TxCollectionCUD, Doc, AttachedDoc, IndexingConfiguration, Class } from '@hcengineering/core'
|
||||
import { Builder } from '@hcengineering/model'
|
||||
import core from './component'
|
||||
import {
|
||||
@ -31,6 +31,7 @@ import {
|
||||
TEnumOf,
|
||||
TFulltextData,
|
||||
TFullTextSearchContext,
|
||||
TIndexConfiguration,
|
||||
TIndexStageState,
|
||||
TInterface,
|
||||
TMixin,
|
||||
@ -104,7 +105,8 @@ export function createModel (builder: Builder): void {
|
||||
TIndexStageState,
|
||||
TFullTextSearchContext,
|
||||
TConfiguration,
|
||||
TConfigurationElement
|
||||
TConfigurationElement,
|
||||
TIndexConfiguration
|
||||
)
|
||||
|
||||
builder.createDoc(
|
||||
@ -116,4 +118,23 @@ export function createModel (builder: Builder): void {
|
||||
},
|
||||
core.account.System
|
||||
)
|
||||
|
||||
builder.mixin<Class<TxCollectionCUD<Doc, AttachedDoc>>, IndexingConfiguration<TxCollectionCUD<Doc, AttachedDoc>>>(
|
||||
core.class.TxCollectionCUD,
|
||||
core.class.Class,
|
||||
core.mixin.IndexConfiguration,
|
||||
{
|
||||
indexes: [
|
||||
'tx.objectId',
|
||||
'tx._class',
|
||||
'tx.objectClass',
|
||||
'tx.operations.attachedTo',
|
||||
'objectSpace',
|
||||
{
|
||||
objectSpace: 1,
|
||||
_id: 1
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import {
|
||||
TxRemoveDoc,
|
||||
TxUpdateDoc
|
||||
} from '@hcengineering/core'
|
||||
import { Index, Model } from '@hcengineering/model'
|
||||
import { Hidden, Index, Model, Prop, TypeRef } from '@hcengineering/model'
|
||||
import core from './component'
|
||||
import { TDoc } from './core'
|
||||
|
||||
@ -43,7 +43,10 @@ import { TDoc } from './core'
|
||||
|
||||
@Model(core.class.Tx, core.class.Doc, DOMAIN_TX)
|
||||
export class TTx extends TDoc implements Tx {
|
||||
objectSpace!: Ref<Space>
|
||||
@Prop(TypeRef(core.class.Space), core.string.Space)
|
||||
@Index(IndexKind.Indexed)
|
||||
@Hidden()
|
||||
objectSpace!: Ref<Space>
|
||||
}
|
||||
|
||||
@Model(core.class.TxModelUpgrade, core.class.Tx, DOMAIN_TX)
|
||||
@ -51,10 +54,15 @@ export class TTxModelUpgrade extends TTx {}
|
||||
|
||||
@Model(core.class.TxCUD, core.class.Tx)
|
||||
export class TTxCUD<T extends Doc> extends TTx implements TxCUD<T> {
|
||||
@Prop(TypeRef(core.class.Doc), core.string.Object)
|
||||
@Index(IndexKind.Indexed)
|
||||
@Hidden()
|
||||
objectId!: Ref<T>
|
||||
|
||||
objectClass!: Ref<Class<T>>
|
||||
@Prop(TypeRef(core.class.Class), core.string.ClassLabel)
|
||||
@Index(IndexKind.Indexed)
|
||||
@Hidden()
|
||||
objectClass!: Ref<Class<T>>
|
||||
}
|
||||
|
||||
@Model(core.class.TxCreateDoc, core.class.TxCUD)
|
||||
|
@ -211,9 +211,11 @@ export class TIssue extends TAttachedDoc implements Issue {
|
||||
description!: Markup
|
||||
|
||||
@Prop(TypeRef(tracker.class.IssueStatus), tracker.string.Status)
|
||||
@Index(IndexKind.Indexed)
|
||||
status!: Ref<IssueStatus>
|
||||
|
||||
@Prop(TypeIssuePriority(), tracker.string.Priority)
|
||||
@Index(IndexKind.Indexed)
|
||||
priority!: IssuePriority
|
||||
|
||||
@Prop(TypeNumber(), tracker.string.Number)
|
||||
@ -221,9 +223,11 @@ export class TIssue extends TAttachedDoc implements Issue {
|
||||
number!: number
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.Assignee)
|
||||
@Index(IndexKind.Indexed)
|
||||
assignee!: Ref<Employee> | null
|
||||
|
||||
@Prop(TypeRef(tracker.class.Project), tracker.string.Project)
|
||||
@Index(IndexKind.Indexed)
|
||||
project!: Ref<Project> | null
|
||||
|
||||
@Prop(Collection(tracker.class.Issue), tracker.string.SubIssues)
|
||||
@ -256,6 +260,7 @@ export class TIssue extends TAttachedDoc implements Issue {
|
||||
rank!: string
|
||||
|
||||
@Prop(TypeRef(tracker.class.Sprint), tracker.string.Sprint)
|
||||
@Index(IndexKind.Indexed)
|
||||
sprint!: Ref<Sprint> | null
|
||||
|
||||
@Prop(TypeNumber(), tracker.string.Estimation)
|
||||
@ -397,6 +402,7 @@ export class TSprint extends TDoc implements Sprint {
|
||||
description?: Markup
|
||||
|
||||
@Prop(TypeSprintStatus(), tracker.string.Status)
|
||||
@Index(IndexKind.Indexed)
|
||||
status!: SprintStatus
|
||||
|
||||
@Prop(TypeRef(contact.class.Employee), tracker.string.ProjectLead)
|
||||
@ -423,6 +429,7 @@ export class TSprint extends TDoc implements Sprint {
|
||||
capacity!: number
|
||||
|
||||
@Prop(TypeRef(tracker.class.Project), tracker.string.Project)
|
||||
@Index(IndexKind.Indexed)
|
||||
project!: Ref<Project>
|
||||
}
|
||||
|
||||
|
@ -391,7 +391,7 @@ export interface FullTextSearchContext extends Class<Doc> {
|
||||
fullTextSummary?: boolean
|
||||
forceIndex?: boolean
|
||||
|
||||
// If defined, will propogate changes to childs with defined set of classes
|
||||
// If defined, will propagate changes to child's with defined set of classes
|
||||
propogate?: Ref<Class<Doc>>[]
|
||||
}
|
||||
|
||||
@ -401,7 +401,7 @@ export interface FullTextSearchContext extends Class<Doc> {
|
||||
export interface ConfigurationElement extends Class<Doc> {
|
||||
// Title will be presented to owner.
|
||||
title: IntlString
|
||||
// Group for groupping.
|
||||
// Group for grouping.
|
||||
group: IntlString
|
||||
}
|
||||
|
||||
@ -410,7 +410,7 @@ export interface ConfigurationElement extends Class<Doc> {
|
||||
*
|
||||
* Define configuration value configuration for workspace.
|
||||
*
|
||||
* Configuration is accessble only for owners of workspace and underhood services.
|
||||
* Configuration is accessible only for owners of workspace and under hood services.
|
||||
*/
|
||||
export interface Configuration extends Doc {
|
||||
enabled: boolean
|
||||
@ -420,3 +420,30 @@ export interface Configuration extends Doc {
|
||||
* @public
|
||||
*/
|
||||
export type RelatedDocument = Pick<Doc, '_id' | '_class'>
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export enum IndexOrder {
|
||||
Ascending = 1,
|
||||
Descending = -1
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export type FieldIndex<T extends Doc> = {
|
||||
[P in keyof T]?: IndexOrder
|
||||
} & {
|
||||
[key: string]: IndexOrder
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
* Mixin for extra indexing fields.
|
||||
*/
|
||||
export interface IndexingConfiguration<T extends Doc> extends Class<Doc> {
|
||||
// Define a list of extra index definitions.
|
||||
indexes: (FieldIndex<T> | string)[]
|
||||
}
|
||||
|
@ -166,12 +166,13 @@ export async function createClient (
|
||||
}
|
||||
|
||||
const conn = await connect(txHandler)
|
||||
const t = Date.now()
|
||||
const atxes = await conn.findAll(
|
||||
core.class.Tx,
|
||||
{ objectSpace: core.space.Model },
|
||||
{ sort: { _id: SortingOrder.Ascending } }
|
||||
)
|
||||
console.log('find model', atxes.length)
|
||||
console.log('find model', atxes.length, Date.now() - t)
|
||||
|
||||
let systemTx: Tx[] = []
|
||||
const userTx: Tx[] = []
|
||||
|
@ -42,7 +42,8 @@ import type {
|
||||
UserStatus,
|
||||
Configuration,
|
||||
ConfigurationElement,
|
||||
IndexStageState
|
||||
IndexStageState,
|
||||
IndexingConfiguration
|
||||
} from './classes'
|
||||
import type {
|
||||
Tx,
|
||||
@ -109,7 +110,8 @@ export default plugin(coreId, {
|
||||
},
|
||||
mixin: {
|
||||
FullTextSearchContext: '' as Ref<Mixin<FullTextSearchContext>>,
|
||||
ConfigurationElement: '' as Ref<Mixin<ConfigurationElement>>
|
||||
ConfigurationElement: '' as Ref<Mixin<ConfigurationElement>>,
|
||||
IndexConfiguration: '' as Ref<Mixin<IndexingConfiguration<Doc>>>
|
||||
},
|
||||
space: {
|
||||
Tx: '' as Ref<Space>,
|
||||
|
@ -47,7 +47,7 @@
|
||||
"AddIssue": "Add Issue",
|
||||
"NewIssue": "New issue",
|
||||
"ResumeDraft": "Resume draft",
|
||||
"SaveIssue": "Save issue",
|
||||
"SaveIssue": "Create issue",
|
||||
"SetPriority": "Set priority\u2026",
|
||||
"SetStatus": "Set status\u2026",
|
||||
"SelectIssue": "Select issue",
|
||||
|
@ -17,9 +17,11 @@ import contact from '@hcengineering/contact'
|
||||
import core, {
|
||||
BackupClient,
|
||||
Client as CoreClient,
|
||||
Doc,
|
||||
Domain,
|
||||
DOMAIN_MODEL,
|
||||
DOMAIN_TX,
|
||||
FieldIndex,
|
||||
IndexKind,
|
||||
Tx,
|
||||
WorkspaceId
|
||||
@ -198,7 +200,7 @@ async function createUpdateIndexes (connection: CoreClient, db: Db): Promise<voi
|
||||
const classes = await connection.findAll(core.class.Class, {})
|
||||
|
||||
const hierarchy = connection.getHierarchy()
|
||||
const domains = new Map<Domain, Set<string>>()
|
||||
const domains = new Map<Domain, Set<string | FieldIndex<Doc>>>()
|
||||
// Find all domains and indexed fields inside
|
||||
for (const c of classes) {
|
||||
try {
|
||||
@ -207,22 +209,30 @@ async function createUpdateIndexes (connection: CoreClient, db: Db): Promise<voi
|
||||
continue
|
||||
}
|
||||
const attrs = hierarchy.getAllAttributes(c._id)
|
||||
const domainAttrs = domains.get(domain) ?? new Set<string>()
|
||||
const domainAttrs = domains.get(domain) ?? new Set<string | FieldIndex<Doc>>()
|
||||
for (const a of attrs.values()) {
|
||||
if (a.index !== undefined && a.index === IndexKind.Indexed) {
|
||||
domainAttrs.add(a.name)
|
||||
}
|
||||
}
|
||||
|
||||
// Handle extra configurations
|
||||
if (hierarchy.hasMixin(c, core.mixin.IndexConfiguration)) {
|
||||
const config = hierarchy.as(c, core.mixin.IndexConfiguration)
|
||||
for (const attr of config.indexes) {
|
||||
domainAttrs.add(attr)
|
||||
}
|
||||
}
|
||||
|
||||
domains.set(domain, domainAttrs)
|
||||
} catch (err: any) {
|
||||
// Ignore, since we have clases without domain.
|
||||
// Ignore, since we have classes without domain.
|
||||
}
|
||||
}
|
||||
|
||||
for (const [d, v] of domains.entries()) {
|
||||
const collection = db.collection(d)
|
||||
const bb: string[] = []
|
||||
const bb: (string | FieldIndex<Doc>)[] = []
|
||||
for (const vv of v.values()) {
|
||||
await collection.createIndex(vv)
|
||||
bb.push(vv)
|
||||
|
@ -30,7 +30,7 @@ test.describe('project tests', () => {
|
||||
await page.fill('[placeholder="Issue\\ title"]', 'issue')
|
||||
await page.click('form button:has-text("Project")')
|
||||
await page.click(`.selectPopup button:has-text("${prjId}")`)
|
||||
await page.click('form button:has-text("Save issue")')
|
||||
await page.click('form button:has-text("Create issue")')
|
||||
await page.waitForSelector('form.antiCard', { state: 'detached' })
|
||||
|
||||
await page.click('.listGrid :has-text("issue")')
|
||||
|
@ -84,7 +84,7 @@ export async function createIssue (page: Page, props: IssueProps): Promise<void>
|
||||
await page.waitForSelector('span:has-text("Default")')
|
||||
await page.click('button:has-text("New issue")')
|
||||
await fillIssueForm(page, props)
|
||||
await page.click('button:has-text("Save issue")')
|
||||
await page.click('button:has-text("Create issue")')
|
||||
await page.waitForSelector('form.antiCard', { state: 'detached' })
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user