mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 21:37:32 +00:00
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:
@@ -91,13 +91,7 @@ func VerifyTokenAndCreateCtxData(ctx context.Context, token, orgID, orgDomain st
|
||||
|
||||
verifiedOrgID, err := t.ExistsOrg(ctx, orgID, orgDomain)
|
||||
if err != nil {
|
||||
err = retry(func() error {
|
||||
verifiedOrgID, err = t.ExistsOrg(ctx, orgID, orgDomain)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return CtxData{}, errors.ThrowPermissionDenied(nil, "AUTH-Bs7Ds", "Organisation doesn't exist")
|
||||
}
|
||||
return CtxData{}, errors.ThrowPermissionDenied(nil, "AUTH-Bs7Ds", "Organisation doesn't exist")
|
||||
}
|
||||
|
||||
return CtxData{
|
||||
|
@@ -16,10 +16,8 @@ func CheckPermission(ctx context.Context, resolver MembershipsResolver, roleMapp
|
||||
_, userPermissionSpan := tracing.NewNamedSpan(ctx, "checkUserPermissions")
|
||||
err = checkUserResourcePermissions(requestedPermissions, resourceID)
|
||||
userPermissionSpan.EndWithError(err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// getUserPermissions retrieves the memberships of the authenticated user (on instance and provided organisation level),
|
||||
@@ -33,23 +31,17 @@ func getUserPermissions(ctx context.Context, resolver MembershipsResolver, requi
|
||||
}
|
||||
|
||||
ctx = context.WithValue(ctx, dataKey, ctxData)
|
||||
memberships, err := resolver.SearchMyMemberships(ctx, orgID)
|
||||
memberships, err := resolver.SearchMyMemberships(ctx, orgID, false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if len(memberships) == 0 {
|
||||
err = retry(func() error {
|
||||
memberships, err = resolver.SearchMyMemberships(ctx, orgID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(memberships) == 0 {
|
||||
return errors.ThrowNotFound(nil, "AUTHZ-cdgFk", "membership not found")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
memberships, err = resolver.SearchMyMemberships(ctx, orgID, true)
|
||||
if len(memberships) == 0 {
|
||||
return nil, nil, errors.ThrowNotFound(nil, "AUTHZ-cdgFk", "membership not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, nil, nil
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
requestedPermissions, allPermissions = mapMembershipsToPermissions(requiredPerm, memberships, roleMappings)
|
||||
|
@@ -18,7 +18,7 @@ type testVerifier struct {
|
||||
func (v *testVerifier) VerifyAccessToken(ctx context.Context, token, clientID, projectID string) (string, string, string, string, string, error) {
|
||||
return "userID", "agentID", "clientID", "de", "orgID", nil
|
||||
}
|
||||
func (v *testVerifier) SearchMyMemberships(ctx context.Context, orgID string) ([]*Membership, error) {
|
||||
func (v *testVerifier) SearchMyMemberships(ctx context.Context, orgID string, _ bool) ([]*Membership, error) {
|
||||
return v.memberships, nil
|
||||
}
|
||||
|
||||
|
@@ -1,15 +0,0 @@
|
||||
package authz
|
||||
|
||||
import "time"
|
||||
|
||||
//TODO: workaround if org projection is not yet up-to-date
|
||||
func retry(retriable func() error) (err error) {
|
||||
for i := 0; i < 3; i++ {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
err = retriable()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
@@ -1,88 +0,0 @@
|
||||
package authz
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_retry(t *testing.T) {
|
||||
type args struct {
|
||||
retriable func(*int) func() error
|
||||
}
|
||||
type want struct {
|
||||
executions int
|
||||
err bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want want
|
||||
}{
|
||||
{
|
||||
name: "1 execution",
|
||||
args: args{
|
||||
retriable: func(execs *int) func() error {
|
||||
return func() error {
|
||||
if *execs < 1 {
|
||||
*execs++
|
||||
return errors.New("not 1")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
err: false,
|
||||
executions: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "2 execution",
|
||||
args: args{
|
||||
retriable: func(execs *int) func() error {
|
||||
return func() error {
|
||||
if *execs < 2 {
|
||||
*execs++
|
||||
return errors.New("not 2")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
err: false,
|
||||
executions: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "too many execution",
|
||||
args: args{
|
||||
retriable: func(execs *int) func() error {
|
||||
return func() error {
|
||||
if *execs < 3 {
|
||||
*execs++
|
||||
return errors.New("not 3")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
err: true,
|
||||
executions: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var execs int
|
||||
|
||||
if err := retry(tt.args.retriable(&execs)); (err != nil) != tt.want.err {
|
||||
t.Errorf("retry() error = %v, want.err %v", err, tt.want.err)
|
||||
}
|
||||
if execs != tt.want.executions {
|
||||
t.Errorf("retry() executions: want: %d got: %d", tt.want.executions, execs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -32,13 +32,13 @@ type TokenVerifier struct {
|
||||
}
|
||||
|
||||
type MembershipsResolver interface {
|
||||
SearchMyMemberships(ctx context.Context, orgID string) ([]*Membership, error)
|
||||
SearchMyMemberships(ctx context.Context, orgID string, shouldTriggerBulk bool) ([]*Membership, error)
|
||||
}
|
||||
|
||||
type authZRepo interface {
|
||||
MembershipsResolver
|
||||
VerifyAccessToken(ctx context.Context, token, verifierClientID, projectID string) (userID, agentID, clientID, prefLang, resourceOwner string, err error)
|
||||
VerifierClientID(ctx context.Context, name string) (clientID, projectID string, err error)
|
||||
SearchMyMemberships(ctx context.Context, orgID string) ([]*Membership, error)
|
||||
ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (projectID string, origins []string, err error)
|
||||
ExistsOrg(ctx context.Context, id, domain string) (string, error)
|
||||
}
|
||||
@@ -135,10 +135,10 @@ func (v *TokenVerifier) RegisterServer(appName, methodPrefix string, mappings Me
|
||||
}
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) SearchMyMemberships(ctx context.Context, orgID string) (_ []*Membership, err error) {
|
||||
func (v *TokenVerifier) SearchMyMemberships(ctx context.Context, orgID string, shouldTriggerBulk bool) (_ []*Membership, err error) {
|
||||
ctx, span := tracing.NewSpan(ctx)
|
||||
defer func() { span.EndWithError(err) }()
|
||||
return v.authZRepo.SearchMyMemberships(ctx, orgID)
|
||||
return v.authZRepo.SearchMyMemberships(ctx, orgID, shouldTriggerBulk)
|
||||
}
|
||||
|
||||
func (v *TokenVerifier) ProjectIDAndOriginsByClientID(ctx context.Context, clientID string) (_ string, _ []string, err error) {
|
||||
|
Reference in New Issue
Block a user