/** * In-Memory Unit of Work * * Coordinates multiple in-memory repositories. * Simulates transaction boundaries for testing. * * ADR-006: In-memory adapters for testing * - commit() persists all changes * - rollback() discards all changes * - NOT atomic in production sense, but sufficient for tests */ import { UnitOfWork, FieldSessionRepository, MissionRepository, DecisionCaseRepository, ArtifactRegistry, EventStore, } from '../repositories/repository-interfaces'; import { InMemoryFieldSessionRepository } from './in-memory-session-repository'; import { InMemoryMissionRepository } from './in-memory-mission-repository'; import { InMemoryDecisionCaseRepository } from './in-memory-decision-case-repository'; import { InMemoryArtifactRegistry } from './in-memory-artifact-registry'; import { InMemoryEventStore } from './in-memory-event-store'; export class InMemoryUnitOfWork implements UnitOfWork { sessions: FieldSessionRepository; missions: MissionRepository; decisionCases: DecisionCaseRepository; artifacts: ArtifactRegistry; events: EventStore; private snapshots: { sessions: Map; missions: Map; cases: Map; artifacts: Map; events: unknown[]; } | null = null; constructor() { this.sessions = new InMemoryFieldSessionRepository(); this.missions = new InMemoryMissionRepository(); this.decisionCases = new InMemoryDecisionCaseRepository(); this.artifacts = new InMemoryArtifactRegistry(); this.events = new InMemoryEventStore(); } async commit(): Promise { // In-memory: changes are already applied // Real implementation would flush to database this.snapshots = null; } async rollback(): Promise { if (!this.snapshots) { throw new Error('No transaction in progress'); } // Restore from snapshots (this.sessions as InMemoryFieldSessionRepository).clear(); (this.missions as InMemoryMissionRepository).clear(); (this.decisionCases as InMemoryDecisionCaseRepository).clear(); (this.artifacts as InMemoryArtifactRegistry).clear(); (this.events as InMemoryEventStore).clear(); // Re-populate from snapshots for (const [id, session] of this.snapshots.sessions) { (this.sessions as InMemoryFieldSessionRepository).save(session as any); } for (const [id, mission] of this.snapshots.missions) { (this.missions as InMemoryMissionRepository).save(mission as any); } for (const [id, c] of this.snapshots.cases) { (this.decisionCases as InMemoryDecisionCaseRepository).save(c as any); } for (const [id, artifact] of this.snapshots.artifacts) { (this.artifacts as InMemoryArtifactRegistry).register(artifact as any); } for (const event of this.snapshots.events) { (this.events as InMemoryEventStore).append(event as any); } this.snapshots = null; } /** Begin transaction: capture snapshot */ begin(): void { this.snapshots = { sessions: new Map((this.sessions as InMemoryFieldSessionRepository as any).sessions), missions: new Map((this.missions as InMemoryMissionRepository as any).missions), cases: new Map((this.decisionCases as InMemoryDecisionCaseRepository as any).cases), artifacts: new Map((this.artifacts as InMemoryArtifactRegistry as any).artifacts), events: [...(this.events as InMemoryEventStore as any).events], }; } }