feat: initial mini simple event sourcing for pending application updates

This commit is contained in:
Pierre Martin
2024-02-07 23:48:42 +01:00
parent 76a8909dc1
commit df5bfe4e1a
14 changed files with 207 additions and 14 deletions

9
domain/AppProjections.ts Normal file
View File

@@ -0,0 +1,9 @@
import ApplicationUpdates from "./projections/ApplicationUpdates";
export default class AppProjections {
public readonly ApplicationUpdates = new ApplicationUpdates();
getAll(): DomainProjection[] {
return [this.ApplicationUpdates];
}
}

11
domain/AppQueries.ts Normal file
View File

@@ -0,0 +1,11 @@
import AppProjections from "./AppProjections";
import { UpdateDefinition } from "./projections/ApplicationUpdates";
export default class AppQueries {
constructor(private readonly projections: AppProjections) {}
pendingApplicationUpdates(appName?: string): UpdateDefinition[] {
// TODO: Implement filtering by appName
return this.projections.ApplicationUpdates.getPendingUpdates();
}
}

5
domain/DomainEvent.ts Normal file
View File

@@ -0,0 +1,5 @@
interface DomainEvent<T> {
readonly type: string;
readonly createdAt: Date;
readonly payload: T;
}

View File

@@ -0,0 +1,3 @@
interface DomainProjection {
handle(event: DomainEvent<any>): void;
}

5
domain/EventStore.ts Normal file
View File

@@ -0,0 +1,5 @@
export default interface EventStore {
append(event: DomainEvent<any>): void;
subscribe(projection: DomainProjection): void;
replay(): Promise<void>;
}

View File

@@ -0,0 +1,14 @@
type ApplicationUpdateStartedPayload = {
id: string;
newVersion: string;
};
export class ApplicationUpdateStarted
implements DomainEvent<ApplicationUpdateStartedPayload>
{
readonly type = "ApplicationUpdateStarted" as const;
constructor(
public readonly payload: ApplicationUpdateStartedPayload,
public readonly createdAt: Date
) {}
}

View File

@@ -0,0 +1,18 @@
export type UpdateDefinition = {
id: string;
newVersion: string;
};
export default class ApplicationUpdates implements DomainProjection {
private readonly pendingUpdates: UpdateDefinition[] = [];
handle(event: DomainEvent<any>): void {
if (event.type === "ApplicationUpdateStarted") {
console.log("ApplicationUpdateStarted", event.payload);
this.pendingUpdates.push(event.payload);
}
}
getPendingUpdates(): UpdateDefinition[] {
return this.pendingUpdates;
}
}