UBERF-10413: Fix update of %hash% and update migration (#8771)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2025-04-29 22:58:39 +07:00 committed by GitHub
parent 5c0ea43eda
commit 1c9127b0a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 55 additions and 11 deletions

View File

@ -16,40 +16,43 @@
import { saveCollabJson } from '@hcengineering/collaboration' import { saveCollabJson } from '@hcengineering/collaboration'
import core, { import core, {
buildSocialIdString, buildSocialIdString,
configUserAccountUuid,
coreId, coreId,
DOMAIN_MODEL_TX, DOMAIN_MODEL_TX,
DOMAIN_SPACE, DOMAIN_SPACE,
DOMAIN_STATUS, DOMAIN_STATUS,
DOMAIN_TX, DOMAIN_TX,
generateId, generateId,
groupByArray,
makeCollabJsonId, makeCollabJsonId,
makeCollabYdocId, makeCollabYdocId,
makeDocCollabId, makeDocCollabId,
MeasureMetricsContext, MeasureMetricsContext,
RateLimiter, RateLimiter,
SocialIdType, SocialIdType,
type PersonId, systemAccountUuid,
toIdMap,
TxProcessor,
type AccountUuid,
type AnyAttribute, type AnyAttribute,
type AttachedDoc,
type Blob, type Blob,
type Class, type Class,
type Doc, type Doc,
type Domain, type Domain,
type MeasureContext, type MeasureContext,
type PersonId,
type Ref, type Ref,
type Role,
type SocialKey,
type Space, type Space,
type SpaceType,
type Status, type Status,
type TxCreateDoc, type TxCreateDoc,
type TxCUD, type TxCUD,
type SpaceType, type TxMixin,
type TxUpdateDoc, type TxUpdateDoc,
type Role, type TypedSpace
toIdMap,
type TypedSpace,
TxProcessor,
type SocialKey,
type AccountUuid,
systemAccountUuid,
configUserAccountUuid
} from '@hcengineering/core' } from '@hcengineering/core'
import { import {
createDefaultSpace, createDefaultSpace,
@ -264,6 +267,41 @@ async function processMigrateContentFor (
} }
} }
async function migrateBackupMixins (client: MigrationClient): Promise<void> {
// Go via classes with domain and check if mixin exists and need to flush %hash%
const hierarchy = client.hierarchy
const curHash = Date.now().toString(16) // Current hash value
const txIterator = await client.traverse<TxMixin<Doc, AttachedDoc>>(DOMAIN_TX, { _class: core.class.TxMixin })
while (true) {
const mixinOps = await txIterator.next(500)
if (mixinOps === null || mixinOps.length === 0) break
const _classes = groupByArray(mixinOps, (it) => it.objectClass)
for (const [_class, ops] of _classes.entries()) {
const domain = hierarchy.findDomain(_class)
if (domain === undefined) continue
let docs = await client.find(domain, { _id: { $in: ops.map((it) => it.objectId) } })
docs = docs.filter((it) => {
// Check if mixin is last operation by modifiedOn
const mops = ops.filter((mi) => mi.objectId === it._id)
if (mops.length === 0) return false
return mops.some((mi) => mi.modifiedOn === it.modifiedOn && mi.modifiedBy === it.modifiedBy)
})
if (docs.length > 0) {
// Check if docs has mixins from list
const toUpdate = docs.filter((it) => hierarchy.findAllMixins(it).length > 0)
if (toUpdate.length > 0) {
await client.update(domain, { _id: { $in: toUpdate.map((it) => it._id) } }, { '%hash%': curHash })
}
}
}
}
}
async function migrateCollaborativeDocsToJson (client: MigrationClient): Promise<void> { async function migrateCollaborativeDocsToJson (client: MigrationClient): Promise<void> {
const ctx = new MeasureMetricsContext('migrateCollaborativeDocsToJson', {}) const ctx = new MeasureMetricsContext('migrateCollaborativeDocsToJson', {})
const storageAdapter = client.storageAdapter const storageAdapter = client.storageAdapter
@ -921,6 +959,11 @@ export const coreOperation: MigrateOperation = {
state: 'accounts-to-social-ids', state: 'accounts-to-social-ids',
mode: 'upgrade', mode: 'upgrade',
func: migrateAccounts func: migrateAccounts
},
{
state: 'migrate-backup-mixins',
mode: 'upgrade',
func: migrateBackupMixins
} }
]) ])
}, },

View File

@ -1401,7 +1401,8 @@ class MongoAdapter extends MongoAdapterBase {
const filter = { _id: tx.objectId } const filter = { _id: tx.objectId }
const modifyOp = { const modifyOp = {
modifiedBy: tx.modifiedBy, modifiedBy: tx.modifiedBy,
modifiedOn: tx.modifiedOn modifiedOn: tx.modifiedOn,
'%hash%': this.curHash()
} }
if (isOperator(tx.attributes)) { if (isOperator(tx.attributes)) {
const update = { ...this.translateMixinAttrs(tx.mixin, tx.attributes), $set: { ...modifyOp } } const update = { ...this.translateMixinAttrs(tx.mixin, tx.attributes), $set: { ...modifyOp } }