UBER-810 Split mixin update to doc and mixin (#3643)

Signed-off-by: Alexander Onnikov <alexander.onnikov@xored.com>
This commit is contained in:
Alexander Onnikov 2023-08-30 23:44:00 +07:00 committed by GitHub
parent c3197951c8
commit e80844e18e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 6 deletions

View File

@ -219,7 +219,7 @@ export class TxOperations implements Omit<Client, 'notify'> {
return this.client.tx(tx)
}
update<T extends Doc>(
async update<T extends Doc>(
doc: T,
update: DocumentUpdate<T>,
retrieve?: boolean,
@ -229,13 +229,22 @@ export class TxOperations implements Omit<Client, 'notify'> {
const hierarchy = this.client.getHierarchy()
const mixClass = Hierarchy.mixinOrClass(doc)
if (hierarchy.isMixin(mixClass)) {
// TODO: Rework it is wrong, we need to split values to mixin update and original document update if mixed.
const baseClass = hierarchy.getBaseClass(doc._class)
return this.updateMixin(doc._id, baseClass, doc.space, mixClass, update, modifiedOn, modifiedBy)
const byClass = this.splitMixinUpdate(update, mixClass, baseClass)
const ops = this.apply(doc._id)
for (const it of byClass) {
if (hierarchy.isMixin(it[0])) {
await ops.updateMixin(doc._id, baseClass, doc.space, it[0], it[1], modifiedOn, modifiedBy)
} else {
await ops.updateDoc(it[0], doc.space, doc._id, it[1], retrieve, modifiedOn, modifiedBy)
}
}
return await ops.commit()
}
if (hierarchy.isDerived(doc._class, core.class.AttachedDoc)) {
const adoc = doc as unknown as AttachedDoc
return this.updateCollection(
return await this.updateCollection(
doc._class,
doc.space,
adoc._id,
@ -248,7 +257,7 @@ export class TxOperations implements Omit<Client, 'notify'> {
modifiedBy
)
}
return this.updateDoc(doc._class, doc.space, doc._id, update, retrieve, modifiedOn, modifiedBy)
return await this.updateDoc(doc._class, doc.space, doc._id, update, retrieve, modifiedOn, modifiedBy)
}
remove<T extends Doc>(doc: T, modifiedOn?: Timestamp, modifiedBy?: Ref<Account>): Promise<TxResult> {
@ -322,6 +331,56 @@ export class TxOperations implements Omit<Client, 'notify'> {
}
return doc
}
private splitMixinUpdate<T extends Doc>(
update: DocumentUpdate<T>,
mixClass: Ref<Class<T>>,
baseClass: Ref<Class<T>>
): Map<Ref<Class<Doc>>, DocumentUpdate<T>> {
const hierarchy = this.getHierarchy()
const attributes = hierarchy.getAllAttributes(mixClass)
const updateAttrs = Object.fromEntries(
Object.entries(update).filter((it) => !it[0].startsWith('$'))
) as DocumentUpdate<T>
const updateOps = Object.fromEntries(
Object.entries(update).filter((it) => it[0].startsWith('$'))
) as DocumentUpdate<T>
const result: Map<Ref<Class<Doc>>, DocumentUpdate<T>> = this.splitObjectAttributes(
updateAttrs,
baseClass,
attributes
)
for (const [key, value] of Object.entries(updateOps)) {
const updates = this.splitObjectAttributes(value as object, baseClass, attributes)
for (const [opsClass, opsUpdate] of updates) {
const upd: DocumentUpdate<T> = result.get(opsClass) ?? {}
result.set(opsClass, { ...upd, [key]: opsUpdate })
}
}
return result
}
private splitObjectAttributes<T extends object>(
obj: T,
objClass: Ref<Class<Doc>>,
attributes: Map<String, AnyAttribute>
): Map<Ref<Class<Doc>>, object> {
const hierarchy = this.getHierarchy()
const result: Map<Ref<Class<Doc>>, any> = new Map()
for (const [key, value] of Object.entries(obj)) {
const attributeOf = attributes.get(key)?.attributeOf
const clazz = attributeOf !== undefined && hierarchy.isMixin(attributeOf) ? attributeOf : objClass
result.set(clazz, { ...(result.get(clazz) ?? {}), [key]: value })
}
return result
}
}
/**

View File

@ -1,6 +1,6 @@
{
"compilerOptions": {
"target": "ES2017",
"target": "ES2019",
"module": "commonjs",
"declaration": true,
"strict": true,