feat: enable handling projections for inactive instances (#5523)

* fix: don't ignore failed events in handlers

* question

* fix retries

* don't instance ids query

* statements can be nil

* make unit tests pass

* add comments

* spool only active instances

* feat(config): handle inactive instances

* customizable HandleInactiveInstances

* test: handling with and w/o inactive instances

* docs: describe projection options

* enable global handling of inactive instances

* accept NowFunc, not Clock interface

* add comment about stringer usage

* remove enum stringer implementations

* fix enum format types

* Update internal/eventstore/repository/mock/repository.mock.impl.go

Co-authored-by: Silvan <silvan.reusser@gmail.com>

---------

Co-authored-by: Silvan <silvan.reusser@gmail.com>
This commit is contained in:
Elio Bischof
2023-03-27 14:34:01 +02:00
committed by GitHub
parent 41ff0bbc63
commit 62bd606593
9 changed files with 332 additions and 78 deletions

View File

@@ -29,8 +29,12 @@ func (m *MockRepository) ExpectFilterEventsError(err error) *MockRepository {
return m
}
func (m *MockRepository) ExpectInstanceIDs(instanceIDs ...string) *MockRepository {
m.EXPECT().InstanceIDs(gomock.Any(), gomock.Any()).Return(instanceIDs, nil)
func (m *MockRepository) ExpectInstanceIDs(hasFilters []*repository.Filter, instanceIDs ...string) *MockRepository {
matcher := gomock.Any()
if len(hasFilters) > 0 {
matcher = &filterQueryMatcher{Filters: [][]*repository.Filter{hasFilters}}
}
m.EXPECT().InstanceIDs(gomock.Any(), matcher).Return(instanceIDs, nil)
return m
}

View File

@@ -0,0 +1,33 @@
package mock
import (
"encoding/json"
"fmt"
"reflect"
"github.com/golang/mock/gomock"
"github.com/zitadel/zitadel/internal/eventstore/repository"
)
var _ gomock.Matcher = (*filterMatcher)(nil)
var _ gomock.GotFormatter = (*filterMatcher)(nil)
type filterMatcher repository.Filter
func (f *filterMatcher) String() string {
jsonValue, err := json.Marshal(f.Value)
if err != nil {
panic(err)
}
return fmt.Sprintf("%d %d (content=%+v,type=%T,json=%s)", f.Field, f.Operation, f.Value, f.Value, string(jsonValue))
}
func (f *filterMatcher) Matches(x interface{}) bool {
other := x.(*repository.Filter)
return f.Field == other.Field && f.Operation == other.Operation && reflect.DeepEqual(f.Value, other.Value)
}
func (f *filterMatcher) Got(got interface{}) string {
return (*filterMatcher)(got.(*repository.Filter)).String()
}

View File

@@ -0,0 +1,45 @@
package mock
import (
"fmt"
"strings"
"github.com/zitadel/zitadel/internal/eventstore/repository"
)
type filterQueryMatcher repository.SearchQuery
func (f *filterQueryMatcher) String() string {
var filterLists []string
for _, filterSlice := range f.Filters {
var str string
for _, filter := range filterSlice {
str += "," + (*filterMatcher)(filter).String()
}
filterLists = append(filterLists, fmt.Sprintf("[%s]", strings.TrimPrefix(str, ",")))
}
return fmt.Sprintf("Filters: %s", strings.Join(filterLists, " "))
}
func (f *filterQueryMatcher) Matches(x interface{}) bool {
other := x.(*repository.SearchQuery)
if len(f.Filters) != len(other.Filters) {
return false
}
for filterSliceIdx, filterSlice := range f.Filters {
if len(filterSlice) != len(other.Filters[filterSliceIdx]) {
return false
}
for filterIdx, filter := range f.Filters[filterSliceIdx] {
if !(*filterMatcher)(filter).Matches(other.Filters[filterSliceIdx][filterIdx]) {
return false
}
}
}
return true
}
func (f *filterQueryMatcher) Got(got interface{}) string {
return (*filterQueryMatcher)(got.(*repository.SearchQuery)).String()
}