Zum Inhalt springen
Deutsch

Schema-Registry

Für größere Codebases mit vielen Event-Typen wird zu wissen, was existiert, ein Problem. Jeder PersistentActor deklariert seine Events; einige haben Adapter; Versionen leben in den Adapter-Configs. Kein zentraler Katalog.

SchemaRegistry ist der optionale Katalog:

import { SchemaRegistry } from 'actor-ts';
export const registry = new SchemaRegistry()
.add('Deposited', 2)
.add('Withdrawn', 1)
.add('AccountFrozen', 3)
.add('AccountClosed', 1);

Eine einfache typisierte Map von Event-Name → aktuelle Version. Verwende sie, um:

  • Den aktuellen Stand jedes Schemas zu dokumentieren.
  • Zu validieren, dass Adapter die richtige Version deklarieren.
  • Tooling anzutreiben — Admin-Dashboards, Dev-Tools, die Journal-Inhalte zeigen.

Die meisten Projekte brauchen sie nicht. Greif danach, wenn du 10+ Event-Typen hast und dich dabei ertappst, manuell zu verfolgen, welche bei welcher Version ist.

import { SchemaRegistry } from 'actor-ts';
// Geteiltes Modul — `schemas.ts`:
export const registry = new SchemaRegistry()
.add('Deposited', 2)
.add('Withdrawn', 1)
.add('Frozen', 3);
export type SchemaName = 'Deposited' | 'Withdrawn' | 'Frozen';

Dann in Actors:

import { registry } from './schemas.js';
class Account extends PersistentActor<...> {
override eventAdapter() {
return new MigratingAdapter<DepositedEventV2>({
currentVersion: registry.versionOf('Deposited'), // → 2
chain: [...],
});
}
}

Die currentVersion des Adapters und der Wert der Registry müssen übereinstimmen. Zieh aus der Registry, um das zu erzwingen.

class SchemaRegistry {
add(name: string, version: number): SchemaRegistry;
versionOf(name: string): number;
has(name: string): boolean;
list(): Array<{ name: string; version: number }>;
}
  • add(name, version) — ein Schema registrieren. Gibt die Registry zum Verketten zurück.
  • versionOf(name) — die aktuelle Version lesen. Wirft, wenn nicht registriert.
  • has(name) — Existenz prüfen.
  • list() — alles Registrierte aufzählen.

Immutable: add() gibt eine neue Registry zurück; das Original wird nicht mutiert. Nützlich für Test-Scaffolding, wo du frische Registries pro Test willst.

import { SchemaRegistry, validateAdapter } from 'actor-ts';
// Während Tests / Startup:
const adapter = new MigratingAdapter<EventV2>({ currentVersion: 2, chain: [...] });
validateAdapter(adapter, registry, 'Deposited');
// → wirft, wenn currentVersion(2) !== registry.versionOf('Deposited')

Für Produktions-Code rufe validateAdapter beim System-Startup als Sicherheitsnetz auf: wenn du die Version eines Adapters hochziehst, aber vergisst, die Registry zu aktualisieren, schlägt der Validate-Call laut fehl.

Ein paar häufige Tooling-Formen, die von der Registry profitieren:

// Admin-Panel: jeden Event-Typ und seine aktuelle Version auflisten
const all = registry.list(); // → [{ name: 'Deposited', version: 2 }, ...]
// Dev-Skript: warnen, wenn ein Event im Journal eine Version hat,
// die HÖHER ist als das, was die Registry kennt (ein Deploy-Issue)
for await (const event of query.eventsByPersistenceId(...)) {
const envelopeVersion = event.event._v;
const expectedMax = registry.versionOf(event.event._t);
if (envelopeVersion > expectedMax) {
console.warn(`event ${event.event._t} has version ${envelopeVersion}, registry knows up to ${expectedMax}`);
}
}

Die SchemaRegistry-API-Referenz deckt die vollständige Oberfläche ab.