feat(eventstore): increase parallel write capabilities (#5940)

This implementation increases parallel write capabilities of the eventstore.
Please have a look at the technical advisories: [05](https://zitadel.com/docs/support/advisory/a10005) and  [06](https://zitadel.com/docs/support/advisory/a10006).
The implementation of eventstore.push is rewritten and stored events are migrated to a new table `eventstore.events2`.
If you are using cockroach: make sure that the database user of ZITADEL has `VIEWACTIVITY` grant. This is used to query events.
This commit is contained in:
Silvan
2023-10-19 12:19:10 +02:00
committed by GitHub
parent 259faba3f0
commit b5564572bc
791 changed files with 30326 additions and 43202 deletions

View File

@@ -2,21 +2,27 @@ package eventstore
import (
"context"
"encoding/json"
"time"
"github.com/zitadel/zitadel/internal/api/authz"
"github.com/zitadel/zitadel/internal/api/service"
"github.com/zitadel/zitadel/internal/eventstore/repository"
)
//BaseEvent represents the minimum metadata of an event
var (
_ Event = (*BaseEvent)(nil)
)
// BaseEvent represents the minimum metadata of an event
type BaseEvent struct {
ID string
EventType EventType `json:"-"`
aggregate Aggregate
Agg *Aggregate
sequence uint64
creationDate time.Time
Seq uint64
Pos float64
Creation time.Time
previousAggregateSequence uint64
previousAggregateTypeSequence uint64
@@ -27,78 +33,91 @@ type BaseEvent struct {
Data []byte `json:"-"`
}
// Position implements Event.
func (e *BaseEvent) Position() float64 {
return e.Pos
}
// EditorService implements Command
func (e *BaseEvent) EditorService() string {
return e.Service
}
//EditorUser implements Command
// EditorUser implements Command
func (e *BaseEvent) EditorUser() string {
return e.User
}
//Type implements Command
// Creator implements action
func (e *BaseEvent) Creator() string {
return e.EditorUser()
}
// Type implements action
func (e *BaseEvent) Type() EventType {
return e.EventType
}
//Sequence is an upcounting unique number of the event
// Sequence is an upcounting unique number of the event
func (e *BaseEvent) Sequence() uint64 {
return e.sequence
return e.Seq
}
//CreationDate is the the time, the event is inserted into the eventstore
// CreationDate is the the time, the event is inserted into the eventstore
func (e *BaseEvent) CreationDate() time.Time {
return e.creationDate
return e.Creation
}
//Aggregate represents the metadata of the event's aggregate
func (e *BaseEvent) Aggregate() Aggregate {
return e.aggregate
// CreatedAt implements Event
func (e *BaseEvent) CreatedAt() time.Time {
return e.CreationDate()
}
//Data returns the payload of the event. It represent the changed fields by the event
// Aggregate implements action
func (e *BaseEvent) Aggregate() *Aggregate {
return e.Agg
}
// Data returns the payload of the event. It represent the changed fields by the event
func (e *BaseEvent) DataAsBytes() []byte {
return e.Data
}
//PreviousAggregateSequence implements EventReader
func (e *BaseEvent) PreviousAggregateSequence() uint64 {
return e.previousAggregateSequence
// Revision implements action
func (*BaseEvent) Revision() uint16 {
return 0
}
//PreviousAggregateTypeSequence implements EventReader
func (e *BaseEvent) PreviousAggregateTypeSequence() uint64 {
return e.previousAggregateTypeSequence
// Unmarshal implements Event
func (e *BaseEvent) Unmarshal(ptr any) error {
if len(e.Data) == 0 {
return nil
}
return json.Unmarshal(e.Data, ptr)
}
//BaseEventFromRepo maps a stored event to a BaseEvent
func BaseEventFromRepo(event *repository.Event) *BaseEvent {
const defaultService = "zitadel"
// BaseEventFromRepo maps a stored event to a BaseEvent
func BaseEventFromRepo(event Event) *BaseEvent {
return &BaseEvent{
aggregate: Aggregate{
ID: event.AggregateID,
Type: AggregateType(event.AggregateType),
ResourceOwner: event.ResourceOwner.String,
InstanceID: event.InstanceID,
Version: Version(event.Version),
},
EventType: EventType(event.Type),
creationDate: event.CreationDate,
sequence: event.Sequence,
previousAggregateSequence: event.PreviousAggregateSequence,
previousAggregateTypeSequence: event.PreviousAggregateTypeSequence,
Service: event.EditorService,
User: event.EditorUser,
Data: event.Data,
Agg: event.Aggregate(),
EventType: event.Type(),
Creation: event.CreatedAt(),
Seq: event.Sequence(),
Service: defaultService,
User: event.Creator(),
Data: event.DataAsBytes(),
Pos: event.Position(),
}
}
//NewBaseEventForPush is the constructor for event's which will be pushed into the eventstore
// NewBaseEventForPush is the constructor for event's which will be pushed into the eventstore
// the resource owner of the aggregate is only used if it's the first event of this aggregate type
// afterwards the resource owner of the first previous events is taken
func NewBaseEventForPush(ctx context.Context, aggregate *Aggregate, typ EventType) *BaseEvent {
return &BaseEvent{
aggregate: *aggregate,
Agg: aggregate,
User: authz.GetCtxData(ctx).UserID,
Service: service.FromContext(ctx),
EventType: typ,