# Aether **Distributed event sourcing primitives for Go, powered by NATS.** --- ## Development Commands ```bash make build # go build ./... make test # go test ./... make lint # golangci-lint run make clean # go clean ``` ## NATS Server Requirement Integration tests require NATS with JetStream enabled: ```bash brew install nats-server nats-server -js ``` Run tests in a separate terminal after starting NATS. ## Project Structure ``` aether/ ├── event.go # Event, ActorSnapshot, EventStore interface ├── eventbus.go # EventBus, EventBroadcaster interface ├── nats_eventbus.go # NATSEventBus implementation ├── metrics*.go # Prometheus metrics ├── store/ # EventStore implementations │ ├── memory.go # InMemoryEventStore (testing) │ └── jetstream.go # JetStreamEventStore (production) ├── cluster/ # Cluster management │ ├── manager.go # ClusterManager │ ├── discovery.go # NodeDiscovery │ ├── hashring.go # ConsistentHashRing │ ├── shard.go # ShardManager │ ├── leader.go # LeaderElection │ └── types.go # Cluster types ├── examples/ # Usage examples └── eventstorming/ # Domain modeling reference ``` ## Core Patterns ### Event Versioning Events for each actor must have monotonically increasing versions: ```go currentVersion, _ := store.GetLatestVersion(actorID) event := &aether.Event{ ActorID: actorID, Version: currentVersion + 1, // ... } err := store.SaveEvent(event) if errors.Is(err, aether.ErrVersionConflict) { // Reload and retry } ``` ### Namespace Isolation Namespaces provide logical boundaries for events: ```go // Event bus namespace ch := eventBus.Subscribe("tenant-abc") eventBus.Publish("tenant-abc", event) // Store namespace store, _ := store.NewJetStreamEventStoreWithNamespace(natsConn, "events", "tenant-abc") ``` Namespaces sanitize special characters and prefix stream names for complete data isolation. ### JetStream Cache Behavior `JetStreamEventStore` caches actor versions for performance. Cache is invalidated when `GetLatestVersion` detects a newer version from external writes. ## Testing - Unit tests: `go test -v ./...` - Single test: `go test -v -run TestName` - Single file: `go test -v ./store/...` - Benchmarks: `go test -bench=. -benchmem` Integration tests require running NATS server first. ## Linting ```bash golangci-lint run golangci-lint run --fix ``` ## References - [vision.md](./vision.md) - Product vision and principles - [examples/README.md](./examples/README.md) - Example patterns