calculate and push 4 in 6 milestones

This commit is contained in:
Elio Bischof
2023-06-28 08:19:34 +02:00
parent 1b5f5e9e62
commit 51a9a54cfd
22 changed files with 667 additions and 229 deletions

View File

@@ -5,6 +5,8 @@ import (
"database/sql"
"fmt"
"github.com/zitadel/zitadel/internal/repository/pseudo"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/database"
@@ -49,6 +51,8 @@ type StatementHandler struct {
initialized chan bool
bulkLimit uint64
subscribe bool
}
func NewStatementHandler(
@@ -57,9 +61,16 @@ func NewStatementHandler(
) StatementHandler {
aggregateTypes := make([]eventstore.AggregateType, 0, len(config.Reducers))
reduces := make(map[eventstore.EventType]handler.Reduce, len(config.Reducers))
subscribe := true
for _, aggReducer := range config.Reducers {
aggregateTypes = append(aggregateTypes, aggReducer.Aggregate)
if aggReducer.Aggregate == pseudo.AggregateType {
subscribe = false
}
for _, eventReducer := range aggReducer.EventRedusers {
if eventReducer.Event == pseudo.TimestampEventType {
subscribe = false
}
reduces[eventReducer.Event] = eventReducer.Reduce
}
}
@@ -80,7 +91,7 @@ func NewStatementHandler(
initialized: make(chan bool),
}
h.ProjectionHandler = handler.NewProjectionHandler(ctx, config.ProjectionHandlerConfig, h.reduce, h.Update, h.SearchQuery, h.Lock, h.Unlock, h.initialized)
h.ProjectionHandler = handler.NewProjectionHandler(ctx, config.ProjectionHandlerConfig, h.reduce, h.Update, h.SearchQuery, h.Lock, h.Unlock, h.initialized, subscribe)
return h
}
@@ -88,6 +99,9 @@ func NewStatementHandler(
func (h *StatementHandler) Start() {
h.initialized <- true
close(h.initialized)
if !h.subscribe {
return
}
h.Subscribe(h.aggregates...)
}

View File

@@ -1,6 +1,7 @@
package crdb
import (
"fmt"
"strconv"
"strings"
@@ -285,6 +286,24 @@ func NewCopyCol(column, from string) handler.Column {
}
}
func NewIsNullCond(column string) handler.Condition {
return handler.Condition{
Name: column,
Value: specialWhere(func(colName, param string) (clause string, needsParam bool) {
return fmt.Sprintf("%s IS NULL", colName), false
}),
}
}
func NewIsNotNullCond(column string) handler.Condition {
return handler.Condition{
Name: column,
Value: specialWhere(func(colName, param string) (clause string, needsParam bool) {
return fmt.Sprintf("%s IS NOT NULL", colName), false
}),
}
}
// NewCopyStatement creates a new upsert statement which updates a column from an existing row
// cols represent the columns which are objective to change.
// if the value of a col is empty the data will be copied from the selected row
@@ -384,13 +403,25 @@ func columnsToQuery(cols []handler.Column) (names []string, parameters []string,
return names, parameters, values[:parameterIndex]
}
type specialWhere func(colName, param string) (clause string, needsParam bool)
func conditionsToWhere(cols []handler.Condition, paramOffset int) (wheres []string, values []interface{}) {
wheres = make([]string, len(cols))
values = make([]interface{}, len(cols))
values = make([]interface{}, 0, len(cols))
for i, col := range cols {
wheres[i] = "(" + col.Name + " = $" + strconv.Itoa(i+1+paramOffset) + ")"
values[i] = col.Value
param := strconv.Itoa(i + 1 + paramOffset)
special, ok := col.Value.(specialWhere)
if !ok {
wheres[i] = "(" + col.Name + " = $" + param + ")"
values = append(values, col.Value)
continue
}
clause, needsValueParam := special(col.Name, param)
wheres[i] = clause
if needsValueParam {
values = append(values, col.Value)
}
}
return wheres, values

View File

@@ -6,6 +6,8 @@ import (
"runtime/debug"
"time"
"github.com/zitadel/zitadel/internal/repository/pseudo"
"github.com/zitadel/logging"
"github.com/zitadel/zitadel/internal/api/authz"
@@ -73,6 +75,7 @@ func NewProjectionHandler(
lock Lock,
unlock Unlock,
initialized <-chan bool,
subscribe bool,
) *ProjectionHandler {
concurrentInstances := int(config.ConcurrentInstances)
if concurrentInstances < 1 {
@@ -97,8 +100,9 @@ func NewProjectionHandler(
go func() {
<-initialized
go h.subscribe(ctx)
if subscribe {
go h.subscribe(ctx)
}
go h.schedule(ctx)
}()
@@ -112,6 +116,13 @@ func (h *ProjectionHandler) Trigger(ctx context.Context, instances ...string) er
if len(instances) > 0 {
ids = instances
}
if h.searchQuery == nil {
return h.processTimestamp(ctx, ids...)
}
return h.processEvents(ctx, ids...)
}
func (h *ProjectionHandler) processEvents(ctx context.Context, ids ...string) error {
for {
events, hasLimitExceeded, err := h.FetchEvents(ctx, ids...)
if err != nil {
@@ -130,6 +141,11 @@ func (h *ProjectionHandler) Trigger(ctx context.Context, instances ...string) er
}
}
func (h *ProjectionHandler) processTimestamp(ctx context.Context, instances ...string) error {
_, err := h.Process(ctx, pseudo.NewTimestampEvent(h.nowFunc(), instances...))
return err
}
// Process handles multiple events by reducing them to statements and updating the projection
func (h *ProjectionHandler) Process(ctx context.Context, events ...eventstore.Event) (index int, err error) {
if len(events) == 0 {