mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-12 08:27:32 +00:00
refactor(v2): init eventstore package (#7806)
* refactor(v2): init database package * refactor(v2): init eventstore package * add mock package * test query constructors * option based push analog to query
This commit is contained in:
190
internal/v2/eventstore/push.go
Normal file
190
internal/v2/eventstore/push.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package eventstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
type Pusher interface {
|
||||
healthier
|
||||
// Push writes the intents to the storage
|
||||
// if an intent implements [PushReducerIntent] [PushReducerIntent.Reduce] is called after
|
||||
// the intent was stored
|
||||
Push(ctx context.Context, intent *PushIntent) error
|
||||
}
|
||||
|
||||
func NewPushIntent(instance string, opts ...PushOpt) *PushIntent {
|
||||
intent := &PushIntent{
|
||||
instance: instance,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(intent)
|
||||
}
|
||||
|
||||
return intent
|
||||
}
|
||||
|
||||
type PushIntent struct {
|
||||
instance string
|
||||
reducer Reducer
|
||||
tx *sql.Tx
|
||||
aggregates []*PushAggregate
|
||||
}
|
||||
|
||||
func (pi *PushIntent) Instance() string {
|
||||
return pi.instance
|
||||
}
|
||||
|
||||
func (pi *PushIntent) Reduce(events ...*Event[StoragePayload]) error {
|
||||
if pi.reducer == nil {
|
||||
return nil
|
||||
}
|
||||
return pi.reducer.Reduce(events...)
|
||||
}
|
||||
|
||||
func (pi *PushIntent) Tx() *sql.Tx {
|
||||
return pi.tx
|
||||
}
|
||||
|
||||
func (pi *PushIntent) Aggregates() []*PushAggregate {
|
||||
return pi.aggregates
|
||||
}
|
||||
|
||||
type PushOpt func(pi *PushIntent)
|
||||
|
||||
func PushReducer(reducer Reducer) PushOpt {
|
||||
return func(pi *PushIntent) {
|
||||
pi.reducer = reducer
|
||||
}
|
||||
}
|
||||
|
||||
func PushTx(tx *sql.Tx) PushOpt {
|
||||
return func(pi *PushIntent) {
|
||||
pi.tx = tx
|
||||
}
|
||||
}
|
||||
|
||||
func AppendAggregate(owner, typ, id string, opts ...PushAggregateOpt) PushOpt {
|
||||
return AppendAggregates(NewPushAggregate(owner, typ, id, opts...))
|
||||
}
|
||||
|
||||
func AppendAggregates(aggregates ...*PushAggregate) PushOpt {
|
||||
return func(pi *PushIntent) {
|
||||
for _, aggregate := range aggregates {
|
||||
aggregate.parent = pi
|
||||
}
|
||||
pi.aggregates = append(pi.aggregates, aggregates...)
|
||||
}
|
||||
}
|
||||
|
||||
type PushAggregate struct {
|
||||
parent *PushIntent
|
||||
// typ of the aggregate
|
||||
typ string
|
||||
// id of the aggregate
|
||||
id string
|
||||
// owner of the aggregate
|
||||
owner string
|
||||
// Commands is an ordered list of changes on the aggregate
|
||||
commands []Command
|
||||
// CurrentSequence checks the current state of the aggregate.
|
||||
// The following types match the current sequence of the aggregate as described:
|
||||
// * nil or [SequenceIgnore]: Not relevant to add the commands
|
||||
// * [SequenceMatches]: Must exactly match
|
||||
// * [SequenceAtLeast]: Must be >= the given sequence
|
||||
currentSequence CurrentSequence
|
||||
}
|
||||
|
||||
func NewPushAggregate(owner, typ, id string, opts ...PushAggregateOpt) *PushAggregate {
|
||||
pa := &PushAggregate{
|
||||
typ: typ,
|
||||
id: id,
|
||||
owner: owner,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(pa)
|
||||
}
|
||||
|
||||
return pa
|
||||
}
|
||||
|
||||
func (pa *PushAggregate) Type() string {
|
||||
return pa.typ
|
||||
}
|
||||
|
||||
func (pa *PushAggregate) ID() string {
|
||||
return pa.id
|
||||
}
|
||||
|
||||
func (pa *PushAggregate) Owner() string {
|
||||
return pa.owner
|
||||
}
|
||||
|
||||
func (pa *PushAggregate) Commands() []Command {
|
||||
return pa.commands
|
||||
}
|
||||
|
||||
func (pa *PushAggregate) Aggregate() *Aggregate {
|
||||
return &Aggregate{
|
||||
ID: pa.id,
|
||||
Type: pa.typ,
|
||||
Owner: pa.owner,
|
||||
Instance: pa.parent.instance,
|
||||
}
|
||||
}
|
||||
|
||||
func (pa *PushAggregate) CurrentSequence() CurrentSequence {
|
||||
return pa.currentSequence
|
||||
}
|
||||
|
||||
type PushAggregateOpt func(pa *PushAggregate)
|
||||
|
||||
func SetCurrentSequence(currentSequence CurrentSequence) PushAggregateOpt {
|
||||
return func(pa *PushAggregate) {
|
||||
pa.currentSequence = currentSequence
|
||||
}
|
||||
}
|
||||
|
||||
func IgnoreCurrentSequence() PushAggregateOpt {
|
||||
return func(pa *PushAggregate) {
|
||||
pa.currentSequence = SequenceIgnore()
|
||||
}
|
||||
}
|
||||
|
||||
func CurrentSequenceMatches(sequence uint32) PushAggregateOpt {
|
||||
return func(pa *PushAggregate) {
|
||||
pa.currentSequence = SequenceMatches(sequence)
|
||||
}
|
||||
}
|
||||
|
||||
func CurrentSequenceAtLeast(sequence uint32) PushAggregateOpt {
|
||||
return func(pa *PushAggregate) {
|
||||
pa.currentSequence = SequenceAtLeast(sequence)
|
||||
}
|
||||
}
|
||||
|
||||
func AppendCommands(commands ...Command) PushAggregateOpt {
|
||||
return func(pa *PushAggregate) {
|
||||
pa.commands = append(pa.commands, commands...)
|
||||
}
|
||||
}
|
||||
|
||||
type Command interface {
|
||||
// Creator is the id of the user which created the action
|
||||
Creator() string
|
||||
// Type describes the action it's in the past (e.g. user.created)
|
||||
Type() string
|
||||
// Revision of the action
|
||||
Revision() uint16
|
||||
// Payload returns the payload of the event. It represent the changed fields by the event
|
||||
// valid types are:
|
||||
// * nil: no payload
|
||||
// * struct: which can be marshalled to json
|
||||
// * pointer to struct: which can be marshalled to json
|
||||
// * []byte: json marshalled data
|
||||
Payload() any
|
||||
// UniqueConstraints should be added for unique attributes of an event, if nil constraints will not be checked
|
||||
UniqueConstraints() []*UniqueConstraint
|
||||
}
|
Reference in New Issue
Block a user