mirror of
https://github.com/hcengineering/platform.git
synced 2025-06-05 15:24:22 +00:00
UBERF-5061 Rewrite queries in index consistency check (#4430)
Signed-off-by: Alexander Onnikov <alexander.onnikov@xored.com>
This commit is contained in:
parent
136134de60
commit
3ee98b67ff
@ -318,6 +318,11 @@ export class TDocIndexState extends TDoc implements DocIndexState {
|
|||||||
@Index(IndexKind.Indexed)
|
@Index(IndexKind.Indexed)
|
||||||
@Hidden()
|
@Hidden()
|
||||||
stages!: Record<string, boolean | string>
|
stages!: Record<string, boolean | string>
|
||||||
|
|
||||||
|
@Prop(TypeString(), getEmbeddedLabel('Generation'))
|
||||||
|
@Index(IndexKind.Indexed)
|
||||||
|
@Hidden()
|
||||||
|
generationId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
@Model(core.class.IndexStageState, core.class.Doc, DOMAIN_DOC_INDEX_STATE)
|
@Model(core.class.IndexStageState, core.class.Doc, DOMAIN_DOC_INDEX_STATE)
|
||||||
|
@ -432,6 +432,8 @@ export interface DocIndexState extends Doc {
|
|||||||
attachedTo?: Ref<Doc>
|
attachedTo?: Ref<Doc>
|
||||||
attachedToClass?: Ref<Class<Doc>>
|
attachedToClass?: Ref<Class<Doc>>
|
||||||
|
|
||||||
|
generationId?: string
|
||||||
|
|
||||||
// States for stages
|
// States for stages
|
||||||
stages: Record<string, boolean | string>
|
stages: Record<string, boolean | string>
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import core, {
|
|||||||
AttachedDoc,
|
AttachedDoc,
|
||||||
Class,
|
Class,
|
||||||
DOMAIN_DOC_INDEX_STATE,
|
DOMAIN_DOC_INDEX_STATE,
|
||||||
|
DOMAIN_FULLTEXT_BLOB,
|
||||||
Doc,
|
Doc,
|
||||||
DocIndexState,
|
DocIndexState,
|
||||||
DocumentQuery,
|
DocumentQuery,
|
||||||
@ -32,7 +33,8 @@ import core, {
|
|||||||
setObjectValue,
|
setObjectValue,
|
||||||
toFindResult,
|
toFindResult,
|
||||||
versionToString,
|
versionToString,
|
||||||
docKey
|
docKey,
|
||||||
|
generateId
|
||||||
} from '@hcengineering/core'
|
} from '@hcengineering/core'
|
||||||
import { DbAdapter } from '../adapter'
|
import { DbAdapter } from '../adapter'
|
||||||
import { RateLimitter } from '../limitter'
|
import { RateLimitter } from '../limitter'
|
||||||
@ -600,44 +602,83 @@ export class FullTextIndexPipeline implements FullTextPipeline {
|
|||||||
|
|
||||||
console.log(this.workspace.name, 'checking index', c)
|
console.log(this.workspace.name, 'checking index', c)
|
||||||
|
|
||||||
// All saved state documents
|
const generationId = generateId()
|
||||||
const states = (
|
|
||||||
await this.storage.findAll(core.class.DocIndexState, { objectClass: c }, { projection: { _id: 1 } })
|
let lastId = ''
|
||||||
).map((it) => it._id)
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (this.cancelling) {
|
if (this.cancelling) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let newDocs: DocIndexState[] = []
|
let newDocs: DocIndexState[] = []
|
||||||
|
let updates = new Map<Ref<DocIndexState>, DocumentUpdate<DocIndexState>>()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
newDocs = (
|
const docs = await dbStorage.findAll<Doc>(
|
||||||
await dbStorage.findAll<Doc>(
|
this.metrics,
|
||||||
this.metrics,
|
c,
|
||||||
c,
|
{ _class: c, _id: { $gt: lastId as any } },
|
||||||
{ _class: c, _id: { $nin: states } },
|
{
|
||||||
{ limit: 500, projection: { _id: 1, attachedTo: 1, attachedToClass: 1 } as any }
|
limit: 10000,
|
||||||
|
sort: { _id: 1 },
|
||||||
|
projection: { _id: 1, attachedTo: 1, attachedToClass: 1 } as any
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
if (docs.length === 0) {
|
||||||
|
// All updated for this class
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
lastId = docs[docs.length - 1]._id
|
||||||
|
|
||||||
|
const states = (
|
||||||
|
await this.storage.findAll(
|
||||||
|
core.class.DocIndexState,
|
||||||
|
{
|
||||||
|
objectClass: c,
|
||||||
|
_id: {
|
||||||
|
$gte: docs[0]._id as any,
|
||||||
|
$lte: docs[docs.length - 1]._id as any
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ projection: { _id: 1 } }
|
||||||
)
|
)
|
||||||
).map((it) => {
|
).map((it) => it._id)
|
||||||
return createStateDoc(it._id, c, {
|
const statesSet = new Set(states)
|
||||||
stages: {},
|
|
||||||
attributes: {},
|
// create missing index states
|
||||||
removed: false,
|
newDocs = docs
|
||||||
space: it.space,
|
.filter((it) => !statesSet.has(it._id as Ref<DocIndexState>))
|
||||||
attachedTo: (it as AttachedDoc)?.attachedTo ?? undefined,
|
.map((it) => {
|
||||||
attachedToClass: (it as AttachedDoc)?.attachedToClass ?? undefined
|
return createStateDoc(it._id, c, {
|
||||||
|
generationId,
|
||||||
|
stages: {},
|
||||||
|
attributes: {},
|
||||||
|
removed: false,
|
||||||
|
space: it.space,
|
||||||
|
attachedTo: (it as AttachedDoc)?.attachedTo ?? undefined,
|
||||||
|
attachedToClass: (it as AttachedDoc)?.attachedToClass ?? undefined
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
// update generationId for existing index states
|
||||||
|
updates = new Map()
|
||||||
|
docs
|
||||||
|
.filter((it) => statesSet.has(it._id as Ref<DocIndexState>))
|
||||||
|
.forEach((it) => {
|
||||||
|
updates.set(it._id as Ref<DocIndexState>, { generationId })
|
||||||
})
|
})
|
||||||
})
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
states.push(...newDocs.map((it) => it._id))
|
try {
|
||||||
|
await this.storage.update(DOMAIN_DOC_INDEX_STATE, updates)
|
||||||
if (newDocs.length === 0) {
|
} catch (err: any) {
|
||||||
// All updated for this class
|
console.error(err)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -646,11 +687,20 @@ export class FullTextIndexPipeline implements FullTextPipeline {
|
|||||||
console.error(err)
|
console.error(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const statesSet = new Set(states)
|
|
||||||
const docIds = (await dbStorage.findAll<Doc>(this.metrics, c, { _class: c }, { projection: { _id: 1 } }))
|
// remove index states for documents that do not exist
|
||||||
.filter((it) => !statesSet.has(it._id as Ref<DocIndexState>))
|
const toRemove = (
|
||||||
.map((it) => it._id)
|
await this.storage.findAll(
|
||||||
await this.storage.clean(DOMAIN_DOC_INDEX_STATE, docIds)
|
core.class.DocIndexState,
|
||||||
|
{ objectClass: c, generationId: { $ne: generationId } },
|
||||||
|
{ projection: { _id: 1 } }
|
||||||
|
)
|
||||||
|
).map((it) => it._id)
|
||||||
|
|
||||||
|
if (toRemove.length > 0) {
|
||||||
|
await this.storage.clean(DOMAIN_DOC_INDEX_STATE, toRemove)
|
||||||
|
await this.storage.clean(DOMAIN_FULLTEXT_BLOB, toRemove)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean for non existing classes
|
// Clean for non existing classes
|
||||||
|
Loading…
Reference in New Issue
Block a user