package aether import ( "time" ) // Event represents a domain event in the system type Event struct { ID string `json:"id"` EventType string `json:"eventType"` ActorID string `json:"actorId"` CommandID string `json:"commandId,omitempty"` // Correlation ID for command that triggered this event Version int64 `json:"version"` Data map[string]interface{} `json:"data"` Metadata map[string]string `json:"metadata,omitempty"` // Optional metadata for tracing and auditing Timestamp time.Time `json:"timestamp"` } // Common metadata keys for distributed tracing and auditing const ( // MetadataKeyCorrelationID identifies related events across services MetadataKeyCorrelationID = "correlationId" // MetadataKeyCausationID identifies the event that caused this event MetadataKeyCausationID = "causationId" // MetadataKeyUserID identifies the user who triggered this event MetadataKeyUserID = "userId" // MetadataKeyTraceID for distributed tracing integration (e.g., OpenTelemetry) MetadataKeyTraceID = "traceId" // MetadataKeySpanID for distributed tracing integration MetadataKeySpanID = "spanId" ) // SetMetadata sets a metadata key-value pair, initializing the map if needed func (e *Event) SetMetadata(key, value string) { if e.Metadata == nil { e.Metadata = make(map[string]string) } e.Metadata[key] = value } // GetMetadata returns the value for a metadata key, or empty string if not found func (e *Event) GetMetadata(key string) string { if e.Metadata == nil { return "" } return e.Metadata[key] } // SetCorrelationID sets the correlation ID metadata func (e *Event) SetCorrelationID(correlationID string) { e.SetMetadata(MetadataKeyCorrelationID, correlationID) } // GetCorrelationID returns the correlation ID metadata func (e *Event) GetCorrelationID() string { return e.GetMetadata(MetadataKeyCorrelationID) } // SetCausationID sets the causation ID metadata func (e *Event) SetCausationID(causationID string) { e.SetMetadata(MetadataKeyCausationID, causationID) } // GetCausationID returns the causation ID metadata func (e *Event) GetCausationID() string { return e.GetMetadata(MetadataKeyCausationID) } // SetUserID sets the user ID metadata func (e *Event) SetUserID(userID string) { e.SetMetadata(MetadataKeyUserID, userID) } // GetUserID returns the user ID metadata func (e *Event) GetUserID() string { return e.GetMetadata(MetadataKeyUserID) } // SetTraceID sets the trace ID metadata for distributed tracing func (e *Event) SetTraceID(traceID string) { e.SetMetadata(MetadataKeyTraceID, traceID) } // GetTraceID returns the trace ID metadata func (e *Event) GetTraceID() string { return e.GetMetadata(MetadataKeyTraceID) } // SetSpanID sets the span ID metadata for distributed tracing func (e *Event) SetSpanID(spanID string) { e.SetMetadata(MetadataKeySpanID, spanID) } // GetSpanID returns the span ID metadata func (e *Event) GetSpanID() string { return e.GetMetadata(MetadataKeySpanID) } // WithMetadataFrom copies metadata from another event (useful for event chaining) func (e *Event) WithMetadataFrom(source *Event) { if source == nil || source.Metadata == nil { return } if e.Metadata == nil { e.Metadata = make(map[string]string) } for k, v := range source.Metadata { e.Metadata[k] = v } } // ActorSnapshot represents a point-in-time state snapshot type ActorSnapshot struct { ActorID string `json:"actorId"` Version int64 `json:"version"` State map[string]interface{} `json:"state"` Timestamp time.Time `json:"timestamp"` } // EventStore defines the interface for event persistence type EventStore interface { SaveEvent(event *Event) error GetEvents(actorID string, fromVersion int64) ([]*Event, error) GetLatestVersion(actorID string) (int64, error) } // SnapshotStore extends EventStore with snapshot capabilities type SnapshotStore interface { EventStore GetLatestSnapshot(actorID string) (*ActorSnapshot, error) SaveSnapshot(snapshot *ActorSnapshot) error }