メインコンテンツまでスキップ

Event Storeリファレンス

Storeインターフェース

import "github.com/contract-to-cash/core/eventstore"

type Store interface {
// 楽観的ロック付きイベント追加
Append(ctx context.Context, streamID string, events []Event, expectedVersion int) error

// ストリームの全イベントをロード
Load(ctx context.Context, streamID string) ([]Event, error)

// 特定バージョンまでのイベントをロード
LoadUntilVersion(ctx context.Context, streamID string, version int) ([]Event, error)

// 特定時点までのイベントをロード(時間旅行クエリ用)
LoadUntil(ctx context.Context, streamID string, until time.Time) ([]Event, error)

// 時間範囲内のイベントをロード
LoadRange(ctx context.Context, streamID string, from, to time.Time) ([]Event, error)

// 全イベントを購読(プロジェクション用)
Subscribe(ctx context.Context, fromPosition int64) (<-chan Event, error)

// スナップショット管理
SaveSnapshot(ctx context.Context, snapshot Snapshot) error
LoadSnapshot(ctx context.Context, streamID string) (*Snapshot, error)
LoadSnapshotBefore(ctx context.Context, streamID string, before time.Time) (*Snapshot, error)
}

Event

type Event struct {
ID string // ユニークイベントID
StreamID string // 集約ID
Type EventType // イベントタイプ(例: "contract.created")
Version int // ストリーム内のバージョン
SchemaVersion int // アップキャスティング用
Data json.RawMessage // イベントペイロード(JSON)
Metadata EventMetadata // 監査情報
OccurredAt time.Time // ビジネスタイムスタンプ
RecordedAt time.Time // システムタイムスタンプ
}

EventMetadata

type EventMetadata struct {
UserID string // 操作者(必須)
IPAddress *string // クライアントIP(オプション)
UserAgent *string // クライアントUA(オプション)
}
// 注: CorrelationID / CausationID は未活用のため Issue #116(Option B)で削除。
// 具体的な利用者が現れた段階で非破壊的に再導入する。

Snapshot

type Snapshot struct {
StreamID string // 集約ID
Version int // スナップショット時点のバージョン
State json.RawMessage // シリアライズされた集約状態
AsOf time.Time // スナップショット時点
CreatedAt time.Time // スナップショット作成時刻
}

DomainEventインターフェース

イベントはこのインターフェースを実装することでシリアライズ/デシリアライズ可能になります:

type DomainEvent interface {
EventType() EventType
}

BaseAggregate

イベントソース集約の基本実装:

type BaseAggregate struct { ... }

agg := eventstore.NewBaseAggregate(id, clock)

agg.ID() string
agg.Version() int
agg.SetVersion(v int)
agg.IncrementVersion()
agg.UncommittedEvents() []Event
agg.ClearUncommittedEvents()
agg.RaiseEvent(event DomainEvent, metadata EventMetadata) error
agg.Clock() Clock

EventRegistry

イベントタイプとGo構造体のマッピング:

registry := eventstore.NewEventRegistry()

registry.Register(event DomainEvent)
registry.Deserialize(eventType EventType, data json.RawMessage) (DomainEvent, error)

Upcaster

イベントスキーマの進化に対応:

type Upcaster interface {
CanUpcast(eventType EventType, fromVersion int) bool
Upcast(event Event) (Event, error)
}

契約イベントタイプ

EventType定数
contract.createdEventTypeContractCreated
contract.activatedEventTypeContractActivated
contract.suspendedEventTypeContractSuspended
contract.resumedEventTypeContractResumed
contract.cancelledEventTypeContractCancelled
contract.renewedEventTypeContractRenewed
contract.expiredEventTypeContractExpired
contract.price_changedEventTypePriceChanged
contract.price_change_scheduledEventTypePriceChangeScheduled
contract.price_change_unscheduledEventTypePriceChangeUnscheduled
contract.trial_startedEventTypeTrialStarted
contract.trial_endedEventTypeTrialEnded
contract.plan_changedEventTypePlanChanged
contract.payment_method_changedEventTypePaymentMethodChanged
contract.cancellation_scheduledEventTypeCancellationScheduled
contract.cancellation_unscheduledEventTypeCancellationUnscheduled

インメモリ実装

テスト・デモ用:

import "github.com/contract-to-cash/core/infrastructure/inmemory"

store := inmemory.NewInMemoryEventStore(clock)

スレッドセーフ。購読とスナップショットを含むStoreインターフェースの全メソッドをサポート。