fix: move v2 pkgs (#1331)

* fix: move eventstore pkgs

* fix: move eventstore pkgs

* fix: remove v2 view

* fix: remove v2 view
This commit is contained in:
Fabi
2021-02-23 15:13:04 +01:00
committed by GitHub
parent 57b277bc7c
commit d8e42744b4
797 changed files with 2116 additions and 2224 deletions

View File

@@ -6,7 +6,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/api/service"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
)
//BaseEvent represents the minimum metadata of an event

View File

@@ -2,74 +2,223 @@ package eventstore
import (
"context"
"encoding/json"
"reflect"
"sync"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/internal/repository"
"github.com/caos/zitadel/internal/eventstore/models"
es_v2 "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/repository"
)
type Eventstore interface {
AggregateCreator() *models.AggregateCreator
Health(ctx context.Context) error
PushAggregates(ctx context.Context, aggregates ...*models.Aggregate) error
FilterEvents(ctx context.Context, searchQuery *models.SearchQuery) (events []*models.Event, err error)
LatestSequence(ctx context.Context, searchQuery *models.SearchQueryFactory) (uint64, error)
V2() *es_v2.Eventstore
Subscribe(aggregates ...models.AggregateType) *Subscription
//Eventstore abstracts all functions needed to store valid events
// and filters the stored events
type Eventstore struct {
repo repository.Repository
interceptorMutex sync.Mutex
eventInterceptors map[EventType]eventTypeInterceptors
}
var _ Eventstore = (*eventstore)(nil)
type eventstore struct {
repo repository.Repository
aggregateCreator *models.AggregateCreator
esV2 *es_v2.Eventstore
type eventTypeInterceptors struct {
eventMapper func(*repository.Event) (EventReader, error)
}
func (es *eventstore) AggregateCreator() *models.AggregateCreator {
return es.aggregateCreator
func NewEventstore(repo repository.Repository) *Eventstore {
return &Eventstore{
repo: repo,
eventInterceptors: map[EventType]eventTypeInterceptors{},
interceptorMutex: sync.Mutex{},
}
}
func (es *eventstore) PushAggregates(ctx context.Context, aggregates ...*models.Aggregate) (err error) {
for _, aggregate := range aggregates {
if len(aggregate.Events) == 0 {
return errors.ThrowInvalidArgument(nil, "EVENT-cNhIj", "no events in aggregate")
//Health checks if the eventstore can properly work
// It checks if the repository can serve load
func (es *Eventstore) Health(ctx context.Context) error {
return es.repo.Health(ctx)
}
//PushEvents pushes the events in a single transaction
// an event needs at least an aggregate
func (es *Eventstore) PushEvents(ctx context.Context, pushEvents ...EventPusher) ([]EventReader, error) {
events, constraints, err := eventsToRepository(pushEvents)
if err != nil {
return nil, err
}
err = es.repo.Push(ctx, events, constraints...)
if err != nil {
return nil, err
}
return es.mapEvents(events)
}
func eventsToRepository(pushEvents []EventPusher) (events []*repository.Event, constraints []*repository.UniqueConstraint, err error) {
events = make([]*repository.Event, len(pushEvents))
for i, event := range pushEvents {
data, err := eventData(event)
if err != nil {
return nil, nil, err
}
for _, event := range aggregate.Events {
if err = event.Validate(); err != nil {
return errors.ThrowInvalidArgument(err, "EVENT-tzIhl", "validate event failed")
}
events[i] = &repository.Event{
AggregateID: event.Aggregate().ID,
AggregateType: repository.AggregateType(event.Aggregate().Typ),
ResourceOwner: event.Aggregate().ResourceOwner,
EditorService: event.EditorService(),
EditorUser: event.EditorUser(),
Type: repository.EventType(event.Type()),
Version: repository.Version(event.Aggregate().Version),
Data: data,
}
if len(event.UniqueConstraints()) > 0 {
constraints = append(constraints, uniqueConstraintsToRepository(event.UniqueConstraints())...)
}
}
err = es.repo.PushAggregates(ctx, aggregates...)
return events, constraints, nil
}
func uniqueConstraintsToRepository(constraints []*EventUniqueConstraint) (uniqueConstraints []*repository.UniqueConstraint) {
uniqueConstraints = make([]*repository.UniqueConstraint, len(constraints))
for i, constraint := range constraints {
uniqueConstraints[i] = &repository.UniqueConstraint{
UniqueType: constraint.UniqueType,
UniqueField: constraint.UniqueField,
Action: uniqueConstraintActionToRepository(constraint.Action),
ErrorMessage: constraint.ErrorMessage,
}
}
return uniqueConstraints
}
//FilterEvents filters the stored events based on the searchQuery
// and maps the events to the defined event structs
func (es *Eventstore) FilterEvents(ctx context.Context, queryFactory *SearchQueryBuilder) ([]EventReader, error) {
query, err := queryFactory.build()
if err != nil {
return nil, err
}
events, err := es.repo.Filter(ctx, query)
if err != nil {
return nil, err
}
return es.mapEvents(events)
}
func (es *Eventstore) mapEvents(events []*repository.Event) (mappedEvents []EventReader, err error) {
mappedEvents = make([]EventReader, len(events))
es.interceptorMutex.Lock()
defer es.interceptorMutex.Unlock()
for i, event := range events {
interceptors, ok := es.eventInterceptors[EventType(event.Type)]
if !ok || interceptors.eventMapper == nil {
mappedEvents[i] = BaseEventFromRepo(event)
//TODO: return error if unable to map event
continue
// return nil, errors.ThrowPreconditionFailed(nil, "V2-usujB", "event mapper not defined")
}
mappedEvents[i], err = interceptors.eventMapper(event)
if err != nil {
return nil, err
}
}
return mappedEvents, nil
}
type reducer interface {
//Reduce handles the events of the internal events list
// it only appends the newly added events
Reduce() error
//AppendEvents appends the passed events to an internal list of events
AppendEvents(...EventReader)
}
//FilterToReducer filters the events based on the search query, appends all events to the reducer and calls it's reduce function
func (es *Eventstore) FilterToReducer(ctx context.Context, searchQuery *SearchQueryBuilder, r reducer) error {
events, err := es.FilterEvents(ctx, searchQuery)
if err != nil {
return err
}
go notify(aggregates)
return nil
r.AppendEvents(events...)
return r.Reduce()
}
func (es *eventstore) FilterEvents(ctx context.Context, searchQuery *models.SearchQuery) ([]*models.Event, error) {
if err := searchQuery.Validate(); err != nil {
return nil, err
//LatestSequence filters the latest sequence for the given search query
func (es *Eventstore) LatestSequence(ctx context.Context, queryFactory *SearchQueryBuilder) (uint64, error) {
query, err := queryFactory.build()
if err != nil {
return 0, err
}
return es.repo.Filter(ctx, models.FactoryFromSearchQuery(searchQuery))
return es.repo.LatestSequence(ctx, query)
}
func (es *eventstore) LatestSequence(ctx context.Context, queryFactory *models.SearchQueryFactory) (uint64, error) {
sequenceFactory := *queryFactory
sequenceFactory = *(&sequenceFactory).Columns(models.Columns_Max_Sequence)
sequenceFactory = *(&sequenceFactory).SequenceGreater(0)
return es.repo.LatestSequence(ctx, &sequenceFactory)
type queryReducer interface {
reducer
//Query returns the SearchQueryFactory for the events needed in reducer
Query() *SearchQueryBuilder
}
func (es *eventstore) Health(ctx context.Context) error {
return es.repo.Health(ctx)
//FilterToQueryReducer filters the events based on the search query of the query function,
// appends all events to the reducer and calls it's reduce function
func (es *Eventstore) FilterToQueryReducer(ctx context.Context, r queryReducer) error {
events, err := es.FilterEvents(ctx, r.Query())
if err != nil {
return err
}
r.AppendEvents(events...)
return r.Reduce()
}
func (es *eventstore) V2() *es_v2.Eventstore {
return es.esV2
//RegisterFilterEventMapper registers a function for mapping an eventstore event to an event
func (es *Eventstore) RegisterFilterEventMapper(eventType EventType, mapper func(*repository.Event) (EventReader, error)) *Eventstore {
if mapper == nil || eventType == "" {
return es
}
es.interceptorMutex.Lock()
defer es.interceptorMutex.Unlock()
interceptor := es.eventInterceptors[eventType]
interceptor.eventMapper = mapper
es.eventInterceptors[eventType] = interceptor
return es
}
func eventData(event EventPusher) ([]byte, error) {
switch data := event.Data().(type) {
case nil:
return nil, nil
case []byte:
if json.Valid(data) {
return data, nil
}
return nil, errors.ThrowInvalidArgument(nil, "V2-6SbbS", "data bytes are not json")
}
dataType := reflect.TypeOf(event.Data())
if dataType.Kind() == reflect.Ptr {
dataType = dataType.Elem()
}
if dataType.Kind() == reflect.Struct {
dataBytes, err := json.Marshal(event.Data())
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "V2-xG87M", "could not marshal data")
}
return dataBytes, nil
}
return nil, errors.ThrowInvalidArgument(nil, "V2-91NRm", "wrong type of event data")
}
func uniqueConstraintActionToRepository(action UniqueConstraintAction) repository.UniqueConstraintAction {
switch action {
case UniqueConstraintAdd:
return repository.UniqueConstraintAdd
case UniqueConstraintRemove:
return repository.UniqueConstraintRemoved
default:
return repository.UniqueConstraintAdd
}
}

View File

@@ -10,7 +10,7 @@ import (
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/api/service"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
)
type testAggregate struct {

View File

@@ -4,13 +4,13 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/caos/zitadel/internal/eventstore"
"testing"
"time"
"github.com/caos/zitadel/internal/api/authz"
"github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/v2/repository/sql"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/caos/zitadel/internal/eventstore/repository/sql"
)
// ------------------------------------------------------------
@@ -30,7 +30,7 @@ func NewUserAggregate(id string) *eventstore.Aggregate {
// ------------------------------------------------------------
type UserAddedEvent struct {
eventstore.BaseEvent `json:"-"`
eventstore.eventstore `json:"-"`
FirstName string `json:"firstName"`
}

View File

@@ -10,7 +10,7 @@ import (
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/cockroachdb/cockroach-go/v2/crdb"
//sql import for cockroach

View File

@@ -5,7 +5,7 @@ import (
"sync"
"testing"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/lib/pq"
_ "github.com/lib/pq"
)

View File

@@ -11,7 +11,7 @@ import (
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
z_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/lib/pq"
)

View File

@@ -10,7 +10,7 @@ import (
"github.com/DATA-DOG/go-sqlmock"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
"github.com/lib/pq"
)

View File

@@ -2,7 +2,7 @@ package eventstore
import (
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
)
//SearchQueryBuilder represents the builder for your filter

View File

@@ -6,7 +6,7 @@ import (
"testing"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
)
func testSetColumns(columns Columns) func(factory *SearchQueryBuilder) *SearchQueryBuilder {

View File

@@ -1,11 +1,11 @@
package eventstore
package v1
import (
"github.com/caos/zitadel/internal/cache/config"
"github.com/caos/zitadel/internal/eventstore/internal/repository/sql"
"github.com/caos/zitadel/internal/eventstore/models"
es_v2 "github.com/caos/zitadel/internal/eventstore/v2"
sql_v2 "github.com/caos/zitadel/internal/eventstore/v2/repository/sql"
eventstore2 "github.com/caos/zitadel/internal/eventstore"
sql_v2 "github.com/caos/zitadel/internal/eventstore/repository/sql"
"github.com/caos/zitadel/internal/eventstore/v1/internal/repository/sql"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
type Config struct {
@@ -23,6 +23,6 @@ func Start(conf Config) (Eventstore, error) {
return &eventstore{
repo: repo,
aggregateCreator: models.NewAggregateCreator(conf.ServiceName),
esV2: es_v2.NewEventstore(sql_v2.NewCRDB(sqlClient)),
esV2: eventstore2.NewEventstore(sql_v2.NewCRDB(sqlClient)),
}, nil
}

View File

@@ -0,0 +1,75 @@
package v1
import (
"context"
eventstore2 "github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v1/internal/repository"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
type Eventstore interface {
AggregateCreator() *models.AggregateCreator
Health(ctx context.Context) error
PushAggregates(ctx context.Context, aggregates ...*models.Aggregate) error
FilterEvents(ctx context.Context, searchQuery *models.SearchQuery) (events []*models.Event, err error)
LatestSequence(ctx context.Context, searchQuery *models.SearchQueryFactory) (uint64, error)
V2() *eventstore2.Eventstore
Subscribe(aggregates ...models.AggregateType) *Subscription
}
var _ Eventstore = (*eventstore)(nil)
type eventstore struct {
repo repository.Repository
aggregateCreator *models.AggregateCreator
esV2 *eventstore2.Eventstore
}
func (es *eventstore) AggregateCreator() *models.AggregateCreator {
return es.aggregateCreator
}
func (es *eventstore) PushAggregates(ctx context.Context, aggregates ...*models.Aggregate) (err error) {
for _, aggregate := range aggregates {
if len(aggregate.Events) == 0 {
return errors.ThrowInvalidArgument(nil, "EVENT-cNhIj", "no events in aggregate")
}
for _, event := range aggregate.Events {
if err = event.Validate(); err != nil {
return errors.ThrowInvalidArgument(err, "EVENT-tzIhl", "validate event failed")
}
}
}
err = es.repo.PushAggregates(ctx, aggregates...)
if err != nil {
return err
}
go notify(aggregates)
return nil
}
func (es *eventstore) FilterEvents(ctx context.Context, searchQuery *models.SearchQuery) ([]*models.Event, error) {
if err := searchQuery.Validate(); err != nil {
return nil, err
}
return es.repo.Filter(ctx, models.FactoryFromSearchQuery(searchQuery))
}
func (es *eventstore) LatestSequence(ctx context.Context, queryFactory *models.SearchQueryFactory) (uint64, error) {
sequenceFactory := *queryFactory
sequenceFactory = *(&sequenceFactory).Columns(models.Columns_Max_Sequence)
sequenceFactory = *(&sequenceFactory).SequenceGreater(0)
return es.repo.LatestSequence(ctx, &sequenceFactory)
}
func (es *eventstore) Health(ctx context.Context) error {
return es.repo.Health(ctx)
}
func (es *eventstore) V2() *eventstore2.Eventstore {
return es.esV2
}

View File

@@ -1,3 +1,3 @@
package eventstore
package v1
//go:generate mockgen -package mock -destination ./mock/eventstore.mock.go github.com/caos/zitadel/internal/eventstore Eventstore

View File

@@ -4,7 +4,7 @@ import (
"context"
"testing"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
gomock "github.com/golang/mock/gomock"
)

View File

@@ -6,7 +6,7 @@ package mock
import (
context "context"
models "github.com/caos/zitadel/internal/eventstore/models"
models "github.com/caos/zitadel/internal/eventstore/v1/models"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)

View File

@@ -3,7 +3,7 @@ package repository
import (
"context"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
type Repository interface {

View File

@@ -7,7 +7,7 @@ import (
"time"
"github.com/DATA-DOG/go-sqlmock"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
const (

View File

@@ -6,8 +6,7 @@ import (
"github.com/caos/logging"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/telemetry/tracing"
)
@@ -15,7 +14,7 @@ type Querier interface {
Query(query string, args ...interface{}) (*sql.Rows, error)
}
func (db *SQL) Filter(ctx context.Context, searchQuery *es_models.SearchQueryFactory) (events []*models.Event, err error) {
func (db *SQL) Filter(ctx context.Context, searchQuery *es_models.SearchQueryFactory) (events []*es_models.Event, err error) {
return filter(db.client, searchQuery)
}
@@ -35,7 +34,7 @@ func filter(querier Querier, searchQuery *es_models.SearchQueryFactory) (events
events = make([]*es_models.Event, 0, limit)
for rows.Next() {
event := new(models.Event)
event := new(es_models.Event)
err := rowScanner(rows.Scan, event)
if err != nil {
return nil, err

View File

@@ -7,7 +7,7 @@ import (
"testing"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestSQL_Filter(t *testing.T) {

View File

@@ -7,7 +7,7 @@ import (
"github.com/caos/logging"
caos_errs "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/cockroachdb/cockroach-go/v2/crdb"
)

View File

@@ -9,7 +9,7 @@ import (
"testing"
z_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
type mockEvents struct {

View File

@@ -9,8 +9,7 @@ import (
"github.com/caos/logging"
z_errors "github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/lib/pq"
)
@@ -30,7 +29,7 @@ const (
" FROM eventstore.events"
)
func buildQuery(queryFactory *models.SearchQueryFactory) (query string, limit uint64, values []interface{}, rowScanner func(s scan, dest interface{}) error) {
func buildQuery(queryFactory *es_models.SearchQueryFactory) (query string, limit uint64, values []interface{}, rowScanner func(s scan, dest interface{}) error) {
searchQuery, err := queryFactory.Build()
if err != nil {
logging.Log("SQL-cshKu").WithError(err).Warn("search query factory invalid")
@@ -43,7 +42,7 @@ func buildQuery(queryFactory *models.SearchQueryFactory) (query string, limit ui
}
query += where
if searchQuery.Columns != models.Columns_Max_Sequence {
if searchQuery.Columns != es_models.Columns_Max_Sequence {
query += " ORDER BY event_sequence"
if searchQuery.Desc {
query += " DESC"
@@ -60,7 +59,7 @@ func buildQuery(queryFactory *models.SearchQueryFactory) (query string, limit ui
return query, searchQuery.Limit, values, rowScanner
}
func prepareCondition(filters []*models.Filter) (clause string, values []interface{}) {
func prepareCondition(filters []*es_models.Filter) (clause string, values []interface{}) {
values = make([]interface{}, len(filters))
clauses := make([]string, len(filters))
@@ -70,7 +69,7 @@ func prepareCondition(filters []*models.Filter) (clause string, values []interfa
for i, filter := range filters {
value := filter.GetValue()
switch value.(type) {
case []bool, []float64, []int64, []string, []models.AggregateType, []models.EventType, *[]bool, *[]float64, *[]int64, *[]string, *[]models.AggregateType, *[]models.EventType:
case []bool, []float64, []int64, []string, []es_models.AggregateType, []es_models.EventType, *[]bool, *[]float64, *[]int64, *[]string, *[]es_models.AggregateType, *[]es_models.EventType:
value = pq.Array(value)
}
@@ -85,9 +84,9 @@ func prepareCondition(filters []*models.Filter) (clause string, values []interfa
type scan func(dest ...interface{}) error
func prepareColumns(columns models.Columns) (string, func(s scan, dest interface{}) error) {
func prepareColumns(columns es_models.Columns) (string, func(s scan, dest interface{}) error) {
switch columns {
case models.Columns_Max_Sequence:
case es_models.Columns_Max_Sequence:
return "SELECT MAX(event_sequence) FROM eventstore.events", func(row scan, dest interface{}) (err error) {
sequence, ok := dest.(*Sequence)
if !ok {
@@ -99,9 +98,9 @@ func prepareColumns(columns models.Columns) (string, func(s scan, dest interface
}
return z_errors.ThrowInternal(err, "SQL-bN5xg", "something went wrong")
}
case models.Columns_Event:
case es_models.Columns_Event:
return selectStmt, func(row scan, dest interface{}) (err error) {
event, ok := dest.(*models.Event)
event, ok := dest.(*es_models.Event)
if !ok {
return z_errors.ThrowInvalidArgument(nil, "SQL-4GP6F", "type must be event")
}

View File

@@ -7,8 +7,7 @@ import (
"time"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/lib/pq"
)
@@ -182,7 +181,7 @@ func Test_getCondition(t *testing.T) {
func Test_prepareColumns(t *testing.T) {
type args struct {
columns models.Columns
columns es_models.Columns
dest interface{}
dbErr error
}
@@ -232,12 +231,12 @@ func Test_prepareColumns(t *testing.T) {
name: "event",
args: args{
columns: es_models.Columns_Event,
dest: new(models.Event),
dest: new(es_models.Event),
},
res: res{
query: "SELECT creation_date, event_type, event_sequence, previous_sequence, event_data, editor_service, editor_user, resource_owner, aggregate_type, aggregate_id, aggregate_version FROM eventstore.events",
dbRow: []interface{}{time.Time{}, models.EventType(""), uint64(5), Sequence(0), Data(nil), "", "", "", models.AggregateType("user"), "hodor", models.Version("")},
expected: models.Event{AggregateID: "hodor", AggregateType: "user", Sequence: 5, Data: make(Data, 0)},
dbRow: []interface{}{time.Time{}, es_models.EventType(""), uint64(5), Sequence(0), Data(nil), "", "", "", es_models.AggregateType("user"), "hodor", es_models.Version("")},
expected: es_models.Event{AggregateID: "hodor", AggregateType: "user", Sequence: 5, Data: make(Data, 0)},
},
},
{
@@ -255,7 +254,7 @@ func Test_prepareColumns(t *testing.T) {
name: "event query error",
args: args{
columns: es_models.Columns_Event,
dest: new(models.Event),
dest: new(es_models.Event),
dbErr: sql.ErrConnDone,
},
res: res{
@@ -308,7 +307,7 @@ func prepareTestScan(err error, res []interface{}) scan {
func Test_prepareCondition(t *testing.T) {
type args struct {
filters []*models.Filter
filters []*es_models.Filter
}
type res struct {
clause string
@@ -399,7 +398,7 @@ func Test_prepareCondition(t *testing.T) {
func Test_buildQuery(t *testing.T) {
type args struct {
queryFactory *models.SearchQueryFactory
queryFactory *es_models.SearchQueryFactory
}
type res struct {
query string

View File

@@ -6,9 +6,9 @@ package mock
import (
context "context"
eventstore "github.com/caos/zitadel/internal/eventstore"
models "github.com/caos/zitadel/internal/eventstore/models"
eventstore0 "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/v1"
models "github.com/caos/zitadel/internal/eventstore/v1/models"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
@@ -114,14 +114,14 @@ func (mr *MockEventstoreMockRecorder) PushAggregates(arg0 interface{}, arg1 ...i
}
// Subscribe mocks base method
func (m *MockEventstore) Subscribe(arg0 ...models.AggregateType) *eventstore.Subscription {
func (m *MockEventstore) Subscribe(arg0 ...models.AggregateType) *v1.Subscription {
m.ctrl.T.Helper()
varargs := []interface{}{}
for _, a := range arg0 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "Subscribe", varargs...)
ret0, _ := ret[0].(*eventstore.Subscription)
ret0, _ := ret[0].(*v1.Subscription)
return ret0
}
@@ -132,10 +132,10 @@ func (mr *MockEventstoreMockRecorder) Subscribe(arg0 ...interface{}) *gomock.Cal
}
// V2 mocks base method
func (m *MockEventstore) V2() *eventstore0.Eventstore {
func (m *MockEventstore) V2() *eventstore.Eventstore {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "V2")
ret0, _ := ret[0].(*eventstore0.Eventstore)
ret0, _ := ret[0].(*eventstore.Eventstore)
return ret0
}

View File

@@ -2,12 +2,12 @@ package query
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v1"
"time"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
const (
@@ -26,7 +26,7 @@ type Handler interface {
AggregateTypes() []models.AggregateType
CurrentSequence() (uint64, error)
Eventstore() eventstore.Eventstore
Eventstore() v1.Eventstore
}
func ReduceEvent(handler Handler, event *models.Event) {

View File

@@ -4,8 +4,7 @@ import (
"context"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
type filterFunc func(context.Context, *es_models.SearchQuery) ([]*es_models.Event, error)
@@ -50,7 +49,7 @@ func Push(ctx context.Context, push pushFunc, appender appendFunc, aggregaters .
return appendAggregates(appender, aggregates)
}
func PushAggregates(ctx context.Context, push pushFunc, appender appendFunc, aggregates ...*models.Aggregate) (err error) {
func PushAggregates(ctx context.Context, push pushFunc, appender appendFunc, aggregates ...*es_models.Aggregate) (err error) {
if len(aggregates) < 1 {
return errors.ThrowPreconditionFailed(nil, "SDK-q9wjp", "Errors.Internal")
}
@@ -66,7 +65,7 @@ func PushAggregates(ctx context.Context, push pushFunc, appender appendFunc, agg
return appendAggregates(appender, aggregates)
}
func appendAggregates(appender appendFunc, aggregates []*models.Aggregate) error {
func appendAggregates(appender appendFunc, aggregates []*es_models.Aggregate) error {
for _, aggregate := range aggregates {
err := appender(aggregate.Events...)
if err != nil {
@@ -76,8 +75,8 @@ func appendAggregates(appender appendFunc, aggregates []*models.Aggregate) error
return nil
}
func makeAggregates(ctx context.Context, aggregaters []AggregateFunc) (aggregates []*models.Aggregate, err error) {
aggregates = make([]*models.Aggregate, len(aggregaters))
func makeAggregates(ctx context.Context, aggregaters []AggregateFunc) (aggregates []*es_models.Aggregate, err error) {
aggregates = make([]*es_models.Aggregate, len(aggregaters))
for i, aggregater := range aggregaters {
aggregates[i], err = aggregater(ctx)
if err != nil {

View File

@@ -5,7 +5,7 @@ import (
"testing"
"github.com/caos/zitadel/internal/errors"
es_models "github.com/caos/zitadel/internal/eventstore/models"
es_models "github.com/caos/zitadel/internal/eventstore/v1/models"
)
func TestFilter(t *testing.T) {

View File

@@ -1,17 +1,17 @@
package spooler
import (
"github.com/caos/zitadel/internal/eventstore/v1"
"math/rand"
"os"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/id"
)
type Config struct {
Eventstore eventstore.Eventstore
Eventstore v1.Eventstore
Locker Locker
ViewHandlers []query.Handler
ConcurrentWorkers int

View File

@@ -2,14 +2,14 @@ package spooler
import (
"context"
"github.com/caos/zitadel/internal/eventstore/v1"
"strconv"
"sync"
"time"
"github.com/caos/logging"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/telemetry/tracing"
"github.com/caos/zitadel/internal/view/repository"
)
@@ -18,7 +18,7 @@ type Spooler struct {
handlers []query.Handler
locker Locker
lockID string
eventstore eventstore.Eventstore
eventstore v1.Eventstore
workers int
queue chan *spooledHandler
}
@@ -31,7 +31,7 @@ type spooledHandler struct {
query.Handler
locker Locker
queuedAt time.Time
eventstore eventstore.Eventstore
eventstore v1.Eventstore
}
func (s *Spooler) Start() {

View File

@@ -3,15 +3,15 @@ package spooler
import (
"context"
"fmt"
es_v2 "github.com/caos/zitadel/internal/eventstore/v2"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/v1"
"testing"
"time"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/query"
"github.com/caos/zitadel/internal/eventstore/spooler/mock"
"github.com/caos/zitadel/internal/eventstore/v1/models"
"github.com/caos/zitadel/internal/eventstore/v1/query"
"github.com/caos/zitadel/internal/eventstore/v1/spooler/mock"
"github.com/caos/zitadel/internal/view/repository"
"github.com/golang/mock/gomock"
)
@@ -34,7 +34,7 @@ func (h *testHandler) CurrentSequence() (uint64, error) {
return 0, nil
}
func (h *testHandler) Eventstore() eventstore.Eventstore {
func (h *testHandler) Eventstore() v1.Eventstore {
return nil
}
@@ -83,7 +83,7 @@ type eventstoreStub struct {
err error
}
func (es *eventstoreStub) Subscribe(...models.AggregateType) *eventstore.Subscription { return nil }
func (es *eventstoreStub) Subscribe(...models.AggregateType) *v1.Subscription { return nil }
func (es *eventstoreStub) Health(ctx context.Context) error {
return nil
@@ -106,7 +106,7 @@ func (es *eventstoreStub) PushAggregates(ctx context.Context, in ...*models.Aggr
func (es *eventstoreStub) LatestSequence(ctx context.Context, in *models.SearchQueryFactory) (uint64, error) {
return 0, nil
}
func (es *eventstoreStub) V2() *es_v2.Eventstore {
func (es *eventstoreStub) V2() *eventstore.Eventstore {
return nil
}
@@ -237,7 +237,7 @@ func TestSpooler_load(t *testing.T) {
type fields struct {
currentHandler query.Handler
locker *testLocker
eventstore eventstore.Eventstore
eventstore v1.Eventstore
}
tests := []struct {
name string

View File

@@ -1,9 +1,9 @@
package eventstore
package v1
import (
"sync"
"github.com/caos/zitadel/internal/eventstore/models"
"github.com/caos/zitadel/internal/eventstore/v1/models"
)
var (

View File

@@ -1,224 +0,0 @@
package eventstore
import (
"context"
"encoding/json"
"reflect"
"sync"
"github.com/caos/zitadel/internal/errors"
"github.com/caos/zitadel/internal/eventstore/v2/repository"
)
//Eventstore abstracts all functions needed to store valid events
// and filters the stored events
type Eventstore struct {
repo repository.Repository
interceptorMutex sync.Mutex
eventInterceptors map[EventType]eventTypeInterceptors
}
type eventTypeInterceptors struct {
eventMapper func(*repository.Event) (EventReader, error)
}
func NewEventstore(repo repository.Repository) *Eventstore {
return &Eventstore{
repo: repo,
eventInterceptors: map[EventType]eventTypeInterceptors{},
interceptorMutex: sync.Mutex{},
}
}
//Health checks if the eventstore can properly work
// It checks if the repository can serve load
func (es *Eventstore) Health(ctx context.Context) error {
return es.repo.Health(ctx)
}
//PushEvents pushes the events in a single transaction
// an event needs at least an aggregate
func (es *Eventstore) PushEvents(ctx context.Context, pushEvents ...EventPusher) ([]EventReader, error) {
events, constraints, err := eventsToRepository(pushEvents)
if err != nil {
return nil, err
}
err = es.repo.Push(ctx, events, constraints...)
if err != nil {
return nil, err
}
return es.mapEvents(events)
}
func eventsToRepository(pushEvents []EventPusher) (events []*repository.Event, constraints []*repository.UniqueConstraint, err error) {
events = make([]*repository.Event, len(pushEvents))
for i, event := range pushEvents {
data, err := eventData(event)
if err != nil {
return nil, nil, err
}
events[i] = &repository.Event{
AggregateID: event.Aggregate().ID,
AggregateType: repository.AggregateType(event.Aggregate().Typ),
ResourceOwner: event.Aggregate().ResourceOwner,
EditorService: event.EditorService(),
EditorUser: event.EditorUser(),
Type: repository.EventType(event.Type()),
Version: repository.Version(event.Aggregate().Version),
Data: data,
}
if len(event.UniqueConstraints()) > 0 {
constraints = append(constraints, uniqueConstraintsToRepository(event.UniqueConstraints())...)
}
}
return events, constraints, nil
}
func uniqueConstraintsToRepository(constraints []*EventUniqueConstraint) (uniqueConstraints []*repository.UniqueConstraint) {
uniqueConstraints = make([]*repository.UniqueConstraint, len(constraints))
for i, constraint := range constraints {
uniqueConstraints[i] = &repository.UniqueConstraint{
UniqueType: constraint.UniqueType,
UniqueField: constraint.UniqueField,
Action: uniqueConstraintActionToRepository(constraint.Action),
ErrorMessage: constraint.ErrorMessage,
}
}
return uniqueConstraints
}
//FilterEvents filters the stored events based on the searchQuery
// and maps the events to the defined event structs
func (es *Eventstore) FilterEvents(ctx context.Context, queryFactory *SearchQueryBuilder) ([]EventReader, error) {
query, err := queryFactory.build()
if err != nil {
return nil, err
}
events, err := es.repo.Filter(ctx, query)
if err != nil {
return nil, err
}
return es.mapEvents(events)
}
func (es *Eventstore) mapEvents(events []*repository.Event) (mappedEvents []EventReader, err error) {
mappedEvents = make([]EventReader, len(events))
es.interceptorMutex.Lock()
defer es.interceptorMutex.Unlock()
for i, event := range events {
interceptors, ok := es.eventInterceptors[EventType(event.Type)]
if !ok || interceptors.eventMapper == nil {
mappedEvents[i] = BaseEventFromRepo(event)
//TODO: return error if unable to map event
continue
// return nil, errors.ThrowPreconditionFailed(nil, "V2-usujB", "event mapper not defined")
}
mappedEvents[i], err = interceptors.eventMapper(event)
if err != nil {
return nil, err
}
}
return mappedEvents, nil
}
type reducer interface {
//Reduce handles the events of the internal events list
// it only appends the newly added events
Reduce() error
//AppendEvents appends the passed events to an internal list of events
AppendEvents(...EventReader)
}
//FilterToReducer filters the events based on the search query, appends all events to the reducer and calls it's reduce function
func (es *Eventstore) FilterToReducer(ctx context.Context, searchQuery *SearchQueryBuilder, r reducer) error {
events, err := es.FilterEvents(ctx, searchQuery)
if err != nil {
return err
}
r.AppendEvents(events...)
return r.Reduce()
}
//LatestSequence filters the latest sequence for the given search query
func (es *Eventstore) LatestSequence(ctx context.Context, queryFactory *SearchQueryBuilder) (uint64, error) {
query, err := queryFactory.build()
if err != nil {
return 0, err
}
return es.repo.LatestSequence(ctx, query)
}
type queryReducer interface {
reducer
//Query returns the SearchQueryFactory for the events needed in reducer
Query() *SearchQueryBuilder
}
//FilterToQueryReducer filters the events based on the search query of the query function,
// appends all events to the reducer and calls it's reduce function
func (es *Eventstore) FilterToQueryReducer(ctx context.Context, r queryReducer) error {
events, err := es.FilterEvents(ctx, r.Query())
if err != nil {
return err
}
r.AppendEvents(events...)
return r.Reduce()
}
//RegisterFilterEventMapper registers a function for mapping an eventstore event to an event
func (es *Eventstore) RegisterFilterEventMapper(eventType EventType, mapper func(*repository.Event) (EventReader, error)) *Eventstore {
if mapper == nil || eventType == "" {
return es
}
es.interceptorMutex.Lock()
defer es.interceptorMutex.Unlock()
interceptor := es.eventInterceptors[eventType]
interceptor.eventMapper = mapper
es.eventInterceptors[eventType] = interceptor
return es
}
func eventData(event EventPusher) ([]byte, error) {
switch data := event.Data().(type) {
case nil:
return nil, nil
case []byte:
if json.Valid(data) {
return data, nil
}
return nil, errors.ThrowInvalidArgument(nil, "V2-6SbbS", "data bytes are not json")
}
dataType := reflect.TypeOf(event.Data())
if dataType.Kind() == reflect.Ptr {
dataType = dataType.Elem()
}
if dataType.Kind() == reflect.Struct {
dataBytes, err := json.Marshal(event.Data())
if err != nil {
return nil, errors.ThrowInvalidArgument(err, "V2-xG87M", "could not marshal data")
}
return dataBytes, nil
}
return nil, errors.ThrowInvalidArgument(nil, "V2-91NRm", "wrong type of event data")
}
func uniqueConstraintActionToRepository(action UniqueConstraintAction) repository.UniqueConstraintAction {
switch action {
case UniqueConstraintAdd:
return repository.UniqueConstraintAdd
case UniqueConstraintRemove:
return repository.UniqueConstraintRemoved
default:
return repository.UniqueConstraintAdd
}
}

View File

@@ -1,7 +1,7 @@
package eventstore
import (
"github.com/caos/zitadel/internal/eventstore/v2/repository"
"github.com/caos/zitadel/internal/eventstore/repository"
)
type Version repository.Version