Files
aether/store/memory.go
Hugo Nijhuis 0b2b6a3125
All checks were successful
CI / build (pull_request) Successful in 17s
Add comprehensive unit tests for SnapshotStore
Implement SaveSnapshot and GetLatestSnapshot methods on InMemoryEventStore
to satisfy the SnapshotStore interface, and add comprehensive tests covering:

- SaveSnapshot persists snapshots correctly
- GetLatestSnapshot returns most recent snapshot by version
- Behavior when no snapshot exists (returns nil, nil)
- Snapshot versioning is respected across actors
- Version ordering (higher version wins, not insertion order)
- Data integrity for complex, nested, and special character states
- Edge cases: zero version, large version, empty/nil state

Closes #4

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 17:13:02 +01:00

89 lines
2.5 KiB
Go

package store
import (
"git.flowmade.one/flowmade-one/aether"
)
// InMemoryEventStore provides a simple in-memory event store for testing
type InMemoryEventStore struct {
events map[string][]*aether.Event // actorID -> events
snapshots map[string][]*aether.ActorSnapshot // actorID -> snapshots (sorted by version)
}
// NewInMemoryEventStore creates a new in-memory event store
func NewInMemoryEventStore() *InMemoryEventStore {
return &InMemoryEventStore{
events: make(map[string][]*aether.Event),
snapshots: make(map[string][]*aether.ActorSnapshot),
}
}
// SaveEvent saves an event to the in-memory store
func (es *InMemoryEventStore) SaveEvent(event *aether.Event) error {
if _, exists := es.events[event.ActorID]; !exists {
es.events[event.ActorID] = make([]*aether.Event, 0)
}
es.events[event.ActorID] = append(es.events[event.ActorID], event)
return nil
}
// GetEvents retrieves events for an actor from a specific version
func (es *InMemoryEventStore) GetEvents(actorID string, fromVersion int64) ([]*aether.Event, error) {
events, exists := es.events[actorID]
if !exists {
return []*aether.Event{}, nil
}
var filteredEvents []*aether.Event
for _, event := range events {
if event.Version >= fromVersion {
filteredEvents = append(filteredEvents, event)
}
}
return filteredEvents, nil
}
// GetLatestVersion returns the latest version for an actor
func (es *InMemoryEventStore) GetLatestVersion(actorID string) (int64, error) {
events, exists := es.events[actorID]
if !exists || len(events) == 0 {
return 0, nil
}
latestVersion := int64(0)
for _, event := range events {
if event.Version > latestVersion {
latestVersion = event.Version
}
}
return latestVersion, nil
}
// SaveSnapshot saves a snapshot to the in-memory store
func (es *InMemoryEventStore) SaveSnapshot(snapshot *aether.ActorSnapshot) error {
if _, exists := es.snapshots[snapshot.ActorID]; !exists {
es.snapshots[snapshot.ActorID] = make([]*aether.ActorSnapshot, 0)
}
es.snapshots[snapshot.ActorID] = append(es.snapshots[snapshot.ActorID], snapshot)
return nil
}
// GetLatestSnapshot returns the most recent snapshot for an actor
func (es *InMemoryEventStore) GetLatestSnapshot(actorID string) (*aether.ActorSnapshot, error) {
snapshots, exists := es.snapshots[actorID]
if !exists || len(snapshots) == 0 {
return nil, nil
}
var latest *aether.ActorSnapshot
for _, snapshot := range snapshots {
if latest == nil || snapshot.Version > latest.Version {
latest = snapshot
}
}
return latest, nil
}