UNPKG

event-local

Version:

Event client

131 lines (124 loc) 4.9 kB
import MySQLModule from "./MySQLModule"; import { Command } from "./Command"; import { ReflectionMutableCommandProccessingAggregate } from "./ReflectionMutableCommandProccessingAggregate"; import { DomenEvent } from "./DomenEvent"; /** * Мы будем создавать агрегат репозитория с шаблонным кодом, передавая в нём название * сущности, за хранение которой он ответственнен. * пример кода * * new TemoeratureRepository() { * constructor() { * super(Temperature) * } * } * * const temoeratureRepository = new TemoeratureRepository(); * temoeratureRepository.find(12) * */ export class AggregateRepository<T> { protected entity_type = "none"; protected entity: Function; private rand: number; constructor(entity: T & ReflectionMutableCommandProccessingAggregate) { this.entity_type = entity.constructor.name; this.entity = entity.constructor; this.rand = Math.round(Math.random() * 100); } /** * Вставляет события в таблицу events, и создаёт сущность entities. */ public async save(agregatCommand: Command): Promise<T> { let id = agregatCommand.entity_id; if (!id) { id = this.rand + "-" + Date.now(); } // Проверим, исполнялась ли эта команда ранее let col = await MySQLModule.db.query( "SELECT * FROM `entities` WHERE `entity_type` = '" + this.entity_type + "' AND `entity_id` = '" + id + "'" ); console.log(col.length); if (col.length > 0) throw new Error("Команда уже исполнялась"); col = await MySQLModule.db.query( "INSERT INTO `entities`(`entity_type`, `entity_id`, `entity_version`) VALUES " + `('${this.entity_type}','${id}','1')` ); console.log(col); agregatCommand.entity_id = id; const agregate = new (this.entity as any)(); console.log(agregatCommand); let events = agregate.process(agregatCommand); events.forEach(async event => { agregate.apply(event); await this.saveEvent(event); }); return agregate; } protected async saveEvent(event: DomenEvent) { let i = await MySQLModule.db.query( "INSERT INTO `events`(" + "`event_id`, `event_type`, `event_data`, `entity_type`, `entity_id`, `triggering_event`) VALUES " + `(NULL,'${event.event_type}','${JSON.stringify(event.event_data)}','${ this.entity_type }','${event.entity_id}',${ event.triggering_event ? "'" + event.triggering_event + "'" : "NULL" })` ); // await this.broker.emit( event.entity.constructor.name.toLowerCase() + '.'+event.type.toLowerCase(), JSON.stringify(event)) } async find( id: string ): Promise<T & ReflectionMutableCommandProccessingAggregate> { // поиск снимка const entity = this.entity_type; const snapshot: any[] = await MySQLModule.db.query( `SELECT * FROM \`snapshots\` WHERE \`entity_type\` = '${entity}' and \`entity_id\` = '${id}' LIMIT 0,1` ); let agregate: T & ReflectionMutableCommandProccessingAggregate = null; let event = []; // if есть снимок if (snapshot[0]) { agregate = new (this.entity as any)( JSON.parse(snapshot[0].snapshot_json) ); // ищем все события event_id > entity_version event = await MySQLModule.db.query( `SELECT * FROM \`events\` WHERE \`entity_type\` = '${entity}' and \`entity_id\` = '${id}' and \`event_id\` > '${snapshot[0].entity_version}' ORDER BY \`event_id\` ASC ` ); } else { agregate = new (this.entity as any)({}); // берём все события этой сущности event = await MySQLModule.db.query( `SELECT * FROM \`events\` WHERE \`entity_type\` = '${entity}' and \`entity_id\` = '${id}' ORDER BY \`create_at\` ASC` ); console.log( `SELECT * FROM \`events\` WHERE \`entity_type\` = '${entity}' and \`entity_id\` = '${id}' ORDER BY \`create_at\` ASC` ); } console.log(event); event.forEach(r => { agregate.apply(new DomenEvent(r)); }); return agregate; // Получает текущую версию из entities } /** * Вставляет события в таблицу events, Обновляет версию до актуальной. */ public async update(agregatCommand: Command) { const agregate = await this.find(agregatCommand.entity_id); let events = agregate.process(agregatCommand); console.log(agregatCommand, agregate, events); events.forEach(async event => { agregate.apply(event); await this.saveEvent(event); }); agregatCommand.entity = agregate; return agregate; } }