event-local
Version:
Event client
131 lines (124 loc) • 4.9 kB
text/typescript
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;
}
}