change Tx hierarchy

Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
Andrey Platov 2021-08-05 14:39:43 +02:00
parent e1f87b97ea
commit f90f9d5521
No known key found for this signature in database
GPG Key ID: C8787EFEB4B64AF0
5 changed files with 39 additions and 24 deletions

View File

@ -25,7 +25,7 @@ const txes = genMinModel()
async function createModel (): Promise<{ model: ModelDb, hierarchy: Hierarchy }> { async function createModel (): Promise<{ model: ModelDb, hierarchy: Hierarchy }> {
const hierarchy = new Hierarchy() const hierarchy = new Hierarchy()
for (const tx of txes) await hierarchy.tx(tx) for (const tx of txes) hierarchy.tx(tx)
const model = new ModelDb(hierarchy) const model = new ModelDb(hierarchy)
for (const tx of txes) await model.tx(tx) for (const tx of txes) await model.tx(tx)
return { model, hierarchy } return { model, hierarchy }
@ -144,7 +144,7 @@ describe('memdb', () => {
it('should push to array', async () => { it('should push to array', async () => {
const hierarchy = new Hierarchy() const hierarchy = new Hierarchy()
for (const tx of txes) await hierarchy.tx(tx) for (const tx of txes) hierarchy.tx(tx)
const model = new TxOperations(new ModelDb(hierarchy), core.account.System) const model = new TxOperations(new ModelDb(hierarchy), core.account.System)
for (const tx of txes) await model.tx(tx) for (const tx of txes) await model.tx(tx)
const space = await model.createDoc(core.class.Space, core.space.Model, { const space = await model.createDoc(core.class.Space, core.space.Model, {

View File

@ -17,7 +17,7 @@ import type { Plugin } from '@anticrm/platform'
import { plugin } from '@anticrm/platform' import { plugin } from '@anticrm/platform'
import type { Class, Data, Doc, Obj, Ref, Mixin, Arr } from '../classes' import type { Class, Data, Doc, Obj, Ref, Mixin, Arr } from '../classes'
import { ClassifierKind, DOMAIN_MODEL } from '../classes' import { ClassifierKind, DOMAIN_MODEL } from '../classes'
import type { Tx, TxCreateDoc } from '../tx' import type { TxCUD, TxCreateDoc } from '../tx'
import core from '../component' import core from '../component'
import { DOMAIN_TX, TxFactory } from '../tx' import { DOMAIN_TX, TxFactory } from '../tx'
@ -45,7 +45,7 @@ export const test = plugin('test' as Plugin, {
* Generate minimal model for testing purposes. * Generate minimal model for testing purposes.
* @returns R * @returns R
*/ */
export function genMinModel (): Tx[] { export function genMinModel (): TxCUD<Doc>[] {
const txes = [] const txes = []
// Fill Tx'es with basic model classes. // Fill Tx'es with basic model classes.
txes.push(createClass(core.class.Obj, { kind: ClassifierKind.CLASS })) txes.push(createClass(core.class.Obj, { kind: ClassifierKind.CLASS }))

View File

@ -78,6 +78,7 @@ export async function createClient (
txBuffer?.push(tx) txBuffer?.push(tx)
} else { } else {
if (tx.objectSpace === core.space.Model) { if (tx.objectSpace === core.space.Model) {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
hierarchy.tx(tx) hierarchy.tx(tx)
// eslint-disable-next-line @typescript-eslint/no-floating-promises // eslint-disable-next-line @typescript-eslint/no-floating-promises
model.tx(tx) model.tx(tx)

View File

@ -86,28 +86,35 @@ export class Hierarchy {
} }
tx (tx: Tx): void { tx (tx: Tx): void {
if (tx._class !== core.class.TxCreateDoc) { switch (tx._class) {
if (tx._class === core.class.TxMixin) { case core.class.TxCreateDoc:
const mixinTx = tx as TxMixin<Doc, Doc> this.txCreateDoc(tx as TxCreateDoc<Doc>)
if (tx.objectClass !== core.class.Class) { return } return
const obj = this.getClass(tx.objectId as Ref<Class<Obj>>) as any case core.class.TxMixin:
obj[mixinTx.mixin] = mixinTx.attributes this.txMixin(tx as TxMixin<Doc, Doc>)
}
return
} }
const createTx = tx as TxCreateDoc<Doc> }
if (createTx.objectClass === core.class.Class) {
private txCreateDoc (tx: TxCreateDoc<Doc>): void {
if (tx.objectClass === core.class.Class) {
const createTx = tx as TxCreateDoc<Class<Obj>> const createTx = tx as TxCreateDoc<Class<Obj>>
const _id = createTx.objectId const _id = createTx.objectId
this.classes.set(_id, TxProcessor.createDoc2Doc(createTx)) this.classes.set(_id, TxProcessor.createDoc2Doc(createTx))
this.addAncestors(_id) this.addAncestors(_id)
this.addDescendant(_id) this.addDescendant(_id)
} else if (createTx.objectClass === core.class.Attribute) { } else if (tx.objectClass === core.class.Attribute) {
const createTx = tx as TxCreateDoc<AnyAttribute> const createTx = tx as TxCreateDoc<AnyAttribute>
this.addAttribute(TxProcessor.createDoc2Doc(createTx)) this.addAttribute(TxProcessor.createDoc2Doc(createTx))
} }
} }
private txMixin (tx: TxMixin<Doc, Doc>): void {
if (tx.objectClass === core.class.Class) {
const obj = this.getClass(tx.objectId as Ref<Class<Obj>>) as any
obj[tx.mixin] = tx.attributes
}
}
isDerived<T extends Obj>(_class: Ref<Class<T>>, from: Ref<Class<T>>): boolean { isDerived<T extends Obj>(_class: Ref<Class<T>>, from: Ref<Class<T>>): boolean {
let cl: Ref<Class<Obj>> | undefined = _class let cl: Ref<Class<Obj>> | undefined = _class
while (cl !== undefined) { while (cl !== undefined) {

View File

@ -22,16 +22,22 @@ import { generateId } from './utils'
/** /**
* @public * @public
*/ */
export interface Tx<T extends Doc = Doc> extends Doc { export interface Tx extends Doc {
objectId: Ref<T> objectSpace: Ref<Space> // space where transaction will operate
objectClass: Ref<Class<T>>
objectSpace: Ref<Space>
} }
/** /**
* @public * @public
*/ */
export interface TxCreateDoc<T extends Doc> extends Tx<T> { export interface TxCUD<T extends Doc> extends Tx {
objectId: Ref<T>
objectClass: Ref<Class<T>>
}
/**
* @public
*/
export interface TxCreateDoc<T extends Doc> extends TxCUD<T> {
attributes: Data<T> attributes: Data<T>
} }
@ -43,7 +49,7 @@ export type ExtendedAttributes<D extends Doc, M extends D> = Omit<M, keyof D>
/** /**
* @public * @public
*/ */
export interface TxMixin<D extends Doc, M extends D> extends Tx<D> { export interface TxMixin<D extends Doc, M extends D> extends TxCUD<D> {
mixin: Ref<Mixin<M>> mixin: Ref<Mixin<M>>
attributes: ExtendedAttributes<D, M> attributes: ExtendedAttributes<D, M>
} }
@ -85,14 +91,14 @@ export type DocumentUpdate<T extends Doc> = Partial<Data<T>> & PushOptions<T> &
/** /**
* @public * @public
*/ */
export interface TxUpdateDoc<T extends Doc> extends Tx<T> { export interface TxUpdateDoc<T extends Doc> extends TxCUD<T> {
operations: DocumentUpdate<T> operations: DocumentUpdate<T>
} }
/** /**
* @public * @public
*/ */
export interface TxRemoveDoc<T extends Doc> extends Tx<T> { export interface TxRemoveDoc<T extends Doc> extends TxCUD<T> {
} }
/** /**
@ -122,6 +128,7 @@ export class TxProcessor implements WithTx {
case core.class.TxMixin: case core.class.TxMixin:
return await this.txMixin(tx as TxMixin<Doc, Doc>) return await this.txMixin(tx as TxMixin<Doc, Doc>)
} }
throw new Error('TxProcessor: unhandled transaction class: ' + tx._class)
} }
static createDoc2Doc<T extends Doc> (tx: TxCreateDoc<T>): T { static createDoc2Doc<T extends Doc> (tx: TxCreateDoc<T>): T {
@ -156,7 +163,7 @@ export class TxOperations implements Storage {
return this.storage.findAll(_class, query, options) return this.storage.findAll(_class, query, options)
} }
tx (tx: Tx<Doc>): Promise<void> { tx (tx: Tx): Promise<void> {
return this.storage.tx(tx) return this.storage.tx(tx)
} }