mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-13 20:48:31 +00:00
112 lines
2.7 KiB
Go
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
|
|
}
|