2024-10-10 14:27:53 +03:00

112 lines
2.7 KiB
Go

package eventstore
import (
"context"
"encoding/json"
"fmt"
"time"
)
type SnapshotType string
func NewSnapshotType[T any](object T) SnapshotType {
return SnapshotType(fmt.Sprintf("%T", object))
}
type SnapshotBase struct {
InstanceID string
SnapshotType SnapshotType
AggregateID string
Position float64
ChangeDate time.Time
}
type SnapshotData struct {
SnapshotBase
Payload []byte
}
type Snapshotter interface {
SetSnapshot(ctx context.Context, snapshot *SnapshotData) error
GetSnapshot(ctx context.Context, instanceID string, typ SnapshotType, aggregateID string) (*SnapshotData, error)
}
func (es *Eventstore) SetSnapshot(ctx context.Context, snapshot *SnapshotData) error {
return es.snapshots.SetSnapshot(ctx, snapshot)
}
func (es *Eventstore) GetSnapshot(ctx context.Context, instanceID string, typ SnapshotType, aggregateID string) (*SnapshotData, error) {
return es.snapshots.GetSnapshot(ctx, instanceID, typ, aggregateID)
}
type Snapshot[T any] struct {
SnapshotBase
Object T
}
// NewSnapshot returns an empty snapshot ready for Populate.
func NewSnapshot[T any](aggregate *Aggregate) *Snapshot[T] {
var object T
return &Snapshot[T]{
SnapshotBase: SnapshotBase{
InstanceID: aggregate.InstanceID,
SnapshotType: NewSnapshotType(object),
AggregateID: aggregate.ID,
},
}
}
// SnapshotFromWriteModel returns a populated snapshot ready for Store.
func SnapshotFromWriteModel[T any](model *WriteModel, object T) *Snapshot[T] {
return &Snapshot[T]{
SnapshotBase: SnapshotBase{
InstanceID: model.InstanceID,
SnapshotType: NewSnapshotType(object),
AggregateID: model.AggregateID,
Position: model.Position,
ChangeDate: model.ChangeDate,
},
Object: object,
}
}
// SnapshotFromReadModel returns a populated snapshot ready for Store.
func SnapshotFromReadModel[T any](model *ReadModel, object T) *Snapshot[T] {
return &Snapshot[T]{
SnapshotBase: SnapshotBase{
InstanceID: model.InstanceID,
SnapshotType: NewSnapshotType(object),
AggregateID: model.AggregateID,
Position: model.Position,
ChangeDate: model.ChangeDate,
},
Object: object,
}
}
func (s *Snapshot[T]) Store(ctx context.Context, repo Snapshotter) (err error) {
payload, err := json.Marshal(s.Object)
if err != nil {
return err
}
return repo.SetSnapshot(ctx, &SnapshotData{
SnapshotBase: s.SnapshotBase,
Payload: payload,
})
}
func (s *Snapshot[T]) Populate(ctx context.Context, repo Snapshotter) (err error) {
data, err := repo.GetSnapshot(ctx, s.InstanceID, NewSnapshotType(s.Object), s.AggregateID)
if err != nil {
return err
}
s.SnapshotBase = data.SnapshotBase
if len(data.Payload) == 0 {
return nil
}
if err = json.Unmarshal(data.Payload, &s.Object); err != nil {
return err
}
return nil
}