zitadel/internal/command/preparation/command.go
Silvan e3d1ca4d58
fix(eventstore): improve pagination of handler filter (#6968)
* fix(setup): add filter_offset to `projections.current_states`

* fix(eventstore): allow offset in query

* fix(handler): offset for already processed events
2023-12-01 12:25:41 +00:00

80 lines
2.5 KiB
Go

package preparation
import (
"context"
"github.com/zitadel/zitadel/internal/errors"
"github.com/zitadel/zitadel/internal/eventstore"
)
// Validation of the input values of the command and if correct returns
// the function to create commands or if not valid an error
type Validation func() (CreateCommands, error)
// CreateCommands builds the commands
// the filter param is an extended version of the eventstore filter method
// it filters for events including the commands on the current context
type CreateCommands func(context.Context, FilterToQueryReducer) ([]eventstore.Command, error)
// FilterToQueryReducer is an abstraction of the eventstore method
type FilterToQueryReducer func(ctx context.Context, queryFactory *eventstore.SearchQueryBuilder) ([]eventstore.Event, error)
var (
//ErrNotExecutable is thrown if no command creator was created
ErrNotExecutable = errors.ThrowInvalidArgument(nil, "PREPA-pH70n", "Errors.Internal")
)
// PrepareCommands checks the passed validations and if ok creates the commands
//
// Deprecated: filter causes unneeded allocation. Use [eventstore.FilterToQueryReducer] instead.
func PrepareCommands(ctx context.Context, filter FilterToQueryReducer, validations ...Validation) (cmds []eventstore.Command, err error) {
commanders, err := validate(validations)
if err != nil {
return nil, err
}
return create(ctx, filter, commanders)
}
func validate(validations []Validation) ([]CreateCommands, error) {
creators := make([]CreateCommands, 0, len(validations))
for _, validate := range validations {
cmds, err := validate()
if err != nil {
return nil, err
}
creators = append(creators, cmds)
}
if len(creators) == 0 {
return nil, ErrNotExecutable
}
return creators, nil
}
func create(ctx context.Context, filter FilterToQueryReducer, commanders []CreateCommands) (cmds []eventstore.Command, err error) {
for _, command := range commanders {
cmd, err := command(ctx, transactionFilter(filter, cmds))
if err != nil {
return nil, err
}
cmds = append(cmds, cmd...)
}
return cmds, nil
}
func transactionFilter(filter FilterToQueryReducer, commands []eventstore.Command) FilterToQueryReducer {
return func(ctx context.Context, query *eventstore.SearchQueryBuilder) ([]eventstore.Event, error) {
events, err := filter(ctx, query)
if err != nil {
return nil, err
}
matches := query.Matches(commands...)
for _, command := range matches {
events = append(events, command.(eventstore.Event))
}
return events, nil
}
}