@durable-streams/state
Version:
State change event protocol for Durable Streams
94 lines (82 loc) • 1.96 kB
text/typescript
import type { ChangeEvent } from "./types"
/**
* MaterializedState maintains an in-memory view of state from change events.
*
* It organizes data by type, where each type contains a map of key -> value.
* This supports multi-type streams where different entity types can coexist.
*/
export class MaterializedState {
private data: Map<string, Map<string, unknown>>
constructor() {
this.data = new Map()
}
/**
* Apply a single change event to update the materialized state
*/
apply(event: ChangeEvent): void {
const { type, key, value, headers } = event
// Get or create the type map
let typeMap = this.data.get(type)
if (!typeMap) {
typeMap = new Map()
this.data.set(type, typeMap)
}
// Apply the operation
switch (headers.operation) {
case `insert`:
typeMap.set(key, value)
break
case `update`:
typeMap.set(key, value)
break
case `upsert`:
typeMap.set(key, value)
break
case `delete`:
typeMap.delete(key)
break
}
}
/**
* Apply a batch of change events
*/
applyBatch(events: Array<ChangeEvent>): void {
for (const event of events) {
this.apply(event)
}
}
/**
* Get a specific value by type and key
*/
get<T = unknown>(type: string, key: string): T | undefined {
const typeMap = this.data.get(type)
if (!typeMap) {
return undefined
}
return typeMap.get(key) as T | undefined
}
/**
* Get all entries for a specific type
*/
getType(type: string): Map<string, unknown> {
return this.data.get(type) || new Map()
}
/**
* Clear all state
*/
clear(): void {
this.data.clear()
}
/**
* Get the number of types in the state
*/
get typeCount(): number {
return this.data.size
}
/**
* Get all type names
*/
get types(): Array<string> {
return Array.from(this.data.keys())
}
}