diff --git a/backend/v3/api/org/v2/domain.go b/backend/v3/api/org/v2/domain.go new file mode 100644 index 0000000000..80be85541f --- /dev/null +++ b/backend/v3/api/org/v2/domain.go @@ -0,0 +1,34 @@ +package org + +import ( + "context" + + "connectrpc.com/connect" + + org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta" +) + +// AddOrganizationDomain implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) AddOrganizationDomain(ctx context.Context, req *connect.Request[org.AddOrganizationDomainRequest]) (*connect.Response[org.AddOrganizationDomainResponse], error) { + return s.UnimplementedOrganizationServiceHandler.AddOrganizationDomain(ctx, req) +} + +// DeleteOrganizationDomain implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) DeleteOrganizationDomain(ctx context.Context, req *connect.Request[org.DeleteOrganizationDomainRequest]) (*connect.Response[org.DeleteOrganizationDomainResponse], error) { + return s.UnimplementedOrganizationServiceHandler.DeleteOrganizationDomain(ctx, req) +} + +// GenerateOrganizationDomainValidation implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) GenerateOrganizationDomainValidation(ctx context.Context, req *connect.Request[org.GenerateOrganizationDomainValidationRequest]) (*connect.Response[org.GenerateOrganizationDomainValidationResponse], error) { + return s.UnimplementedOrganizationServiceHandler.GenerateOrganizationDomainValidation(ctx, req) +} + +// ListOrganizationDomains implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) ListOrganizationDomains(ctx context.Context, req *connect.Request[org.ListOrganizationDomainsRequest]) (*connect.Response[org.ListOrganizationDomainsResponse], error) { + return s.UnimplementedOrganizationServiceHandler.ListOrganizationDomains(ctx, req) +} + +// VerifyOrganizationDomain implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) VerifyOrganizationDomain(ctx context.Context, req *connect.Request[org.VerifyOrganizationDomainRequest]) (*connect.Response[org.VerifyOrganizationDomainResponse], error) { + return s.UnimplementedOrganizationServiceHandler.VerifyOrganizationDomain(ctx, req) +} diff --git a/backend/v3/api/org/v2/metadata.go b/backend/v3/api/org/v2/metadata.go new file mode 100644 index 0000000000..b7955a61e3 --- /dev/null +++ b/backend/v3/api/org/v2/metadata.go @@ -0,0 +1,24 @@ +package org + +import ( + "context" + + "connectrpc.com/connect" + + org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta" +) + +// DeleteOrganizationMetadata implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) DeleteOrganizationMetadata(ctx context.Context, req *connect.Request[org.DeleteOrganizationMetadataRequest]) (*connect.Response[org.DeleteOrganizationMetadataResponse], error) { + return s.UnimplementedOrganizationServiceHandler.DeleteOrganizationMetadata(ctx, req) +} + +// ListOrganizationMetadata implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) ListOrganizationMetadata(ctx context.Context, req *connect.Request[org.ListOrganizationMetadataRequest]) (*connect.Response[org.ListOrganizationMetadataResponse], error) { + return s.UnimplementedOrganizationServiceHandler.ListOrganizationMetadata(ctx, req) +} + +// SetOrganizationMetadata implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) SetOrganizationMetadata(ctx context.Context, req *connect.Request[org.SetOrganizationMetadataRequest]) (*connect.Response[org.SetOrganizationMetadataResponse], error) { + return s.UnimplementedOrganizationServiceHandler.SetOrganizationMetadata(ctx, req) +} diff --git a/backend/v3/api/org/v2/org.go b/backend/v3/api/org/v2/org.go index 601846848a..f450692151 100644 --- a/backend/v3/api/org/v2/org.go +++ b/backend/v3/api/org/v2/org.go @@ -1,4 +1,12 @@ -package orgv2 +package org + +import ( + "context" + + "connectrpc.com/connect" + + org "github.com/zitadel/zitadel/pkg/grpc/org/v2beta" +) // import ( // "context" @@ -31,3 +39,33 @@ package orgv2 // } // return cmds // } + +// ActivateOrganization implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) ActivateOrganization(ctx context.Context, req *connect.Request[org.ActivateOrganizationRequest]) (*connect.Response[org.ActivateOrganizationResponse], error) { + return s.UnimplementedOrganizationServiceHandler.ActivateOrganization(ctx, req) +} + +// CreateOrganization implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) CreateOrganization(ctx context.Context, req *connect.Request[org.CreateOrganizationRequest]) (*connect.Response[org.CreateOrganizationResponse], error) { + return s.UnimplementedOrganizationServiceHandler.CreateOrganization(ctx, req) +} + +// DeactivateOrganization implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) DeactivateOrganization(ctx context.Context, req *connect.Request[org.DeactivateOrganizationRequest]) (*connect.Response[org.DeactivateOrganizationResponse], error) { + return s.UnimplementedOrganizationServiceHandler.DeactivateOrganization(ctx, req) +} + +// DeleteOrganization implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) DeleteOrganization(ctx context.Context, req *connect.Request[org.DeleteOrganizationRequest]) (*connect.Response[org.DeleteOrganizationResponse], error) { + return s.UnimplementedOrganizationServiceHandler.DeleteOrganization(ctx, req) +} + +// ListOrganizations implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) ListOrganizations(ctx context.Context, req *connect.Request[org.ListOrganizationsRequest]) (*connect.Response[org.ListOrganizationsResponse], error) { + return s.UnimplementedOrganizationServiceHandler.ListOrganizations(ctx, req) +} + +// UpdateOrganization implements [orgconnect.OrganizationServiceHandler]. +func (s *Server) UpdateOrganization(ctx context.Context, req *connect.Request[org.UpdateOrganizationRequest]) (*connect.Response[org.UpdateOrganizationResponse], error) { + return s.UnimplementedOrganizationServiceHandler.UpdateOrganization(ctx, req) +} diff --git a/backend/v3/api/org/v2/server.go b/backend/v3/api/org/v2/server.go index fdfc45a2b9..532cc0dda0 100644 --- a/backend/v3/api/org/v2/server.go +++ b/backend/v3/api/org/v2/server.go @@ -1,21 +1,23 @@ -package orgv2 +package org -// this file has been commented out to pass the linter +import ( + "github.com/zitadel/zitadel/backend/v3/telemetry/logging" + "github.com/zitadel/zitadel/backend/v3/telemetry/tracing" + "github.com/zitadel/zitadel/pkg/grpc/org/v2beta/orgconnect" +) -// import ( -// "github.com/zitadel/zitadel/backend/v3/telemetry/logging" -// "github.com/zitadel/zitadel/backend/v3/telemetry/tracing" -// ) +var _ orgconnect.OrganizationServiceHandler = (*Server)(nil) -// var ( -// logger logging.Logger -// tracer tracing.Tracer -// ) +type Server struct { + orgconnect.UnimplementedOrganizationServiceHandler -// func SetLogger(l logging.Logger) { -// logger = l -// } + logger logging.Logger + tracer tracing.Tracer +} -// func SetTracer(t tracing.Tracer) { -// tracer = t -// } +func NewServer(logger logging.Logger, tracer tracing.Tracer) *Server { + return &Server{ + logger: logger, + tracer: tracer, + } +} diff --git a/backend/v3/domain/command.go b/backend/v3/domain/command.go index d63da49512..16bcc59ca5 100644 --- a/backend/v3/domain/command.go +++ b/backend/v3/domain/command.go @@ -1,131 +1,135 @@ package domain -// import ( -// "context" -// "fmt" +import ( + "context" + "fmt" -// "github.com/zitadel/zitadel/backend/v3/storage/database" -// ) + "github.com/zitadel/zitadel/backend/v3/storage/database" +) -// // Commander is the all it needs to implement the command pattern. -// // It is the interface all manipulations need to implement. -// // If possible it should also be used for queries. We will find out if this is possible in the future. -// type Commander interface { -// Execute(ctx context.Context, opts *CommandOpts) (err error) -// fmt.Stringer -// } +// Commander is all it needs to implement the [command pattern](https://refactoring.guru/design-patterns/command). +// It is the interface all manipulations need to implement. +// If possible it should also be used for queries. We will find out if this is possible in the future. +type Commander interface { + Execute(ctx context.Context, opts *CommandOpts) (err error) + fmt.Stringer +} -// // Invoker is part of the command pattern. -// // It is the interface that is used to execute commands. -// type Invoker interface { -// Invoke(ctx context.Context, command Commander, opts *CommandOpts) error -// } +// Invoker is part of the command pattern. +// It is the interface that is used to execute commands. +type Invoker interface { + Invoke(ctx context.Context, command Commander, opts *CommandOpts) error +} -// // CommandOpts are passed to each command -// // the provide common fields used by commands like the database client. -// type CommandOpts struct { -// DB database.QueryExecutor -// Invoker Invoker -// } +// CommandOpts are passed to each command +// they provide common fields used by commands like the database client. +type CommandOpts struct { + DB database.QueryExecutor + Invoker Invoker +} -// type ensureTxOpts struct { -// *database.TransactionOptions -// } +type ensureTxOpts struct { + *database.TransactionOptions +} -// type EnsureTransactionOpt func(*ensureTxOpts) +type EnsureTransactionOpt func(*ensureTxOpts) -// // EnsureTx ensures that the DB is a transaction. If it is not, it will start a new transaction. -// // The returned close function will end the transaction. If the DB is already a transaction, the close function -// // will do nothing because another [Commander] is already responsible for ending the transaction. -// func (o *CommandOpts) EnsureTx(ctx context.Context, opts ...EnsureTransactionOpt) (close func(context.Context, error) error, err error) { -// beginner, ok := o.DB.(database.Beginner) -// if !ok { -// // db is already a transaction -// return func(_ context.Context, err error) error { -// return err -// }, nil -// } +// EnsureTx ensures that o.DB is a [database.Transaction]. If it is not, it will start a new [database.Transaction]. +// The returned close function will end the [database.Transaction]. If the DB is already a [database.Transaction], the close function +// will do nothing because another [Commander] is already responsible for ending the [database.Transaction]. +func (o *CommandOpts) EnsureTx(ctx context.Context, opts ...EnsureTransactionOpt) (close func(context.Context, error) error, err error) { + beginner, ok := o.DB.(database.Beginner) + if !ok { + // db is already a transaction + return func(_ context.Context, err error) error { + return err + }, nil + } -// txOpts := &ensureTxOpts{ -// TransactionOptions: new(database.TransactionOptions), -// } -// for _, opt := range opts { -// opt(txOpts) -// } + txOpts := &ensureTxOpts{ + TransactionOptions: new(database.TransactionOptions), + } + for _, opt := range opts { + opt(txOpts) + } -// tx, err := beginner.Begin(ctx, txOpts.TransactionOptions) -// if err != nil { -// return nil, err -// } -// o.DB = tx + tx, err := beginner.Begin(ctx, txOpts.TransactionOptions) + if err != nil { + return nil, err + } + o.DB = tx -// return func(ctx context.Context, err error) error { -// return tx.End(ctx, err) -// }, nil -// } + return func(ctx context.Context, err error) error { + return tx.End(ctx, err) + }, nil +} -// // EnsureClient ensures that the o.DB is a client. If it is not, it will get a new client from the [database.Pool]. -// // The returned close function will release the client. If the o.DB is already a client or transaction, the close function -// // will do nothing because another [Commander] is already responsible for releasing the client. -// func (o *CommandOpts) EnsureClient(ctx context.Context) (close func(_ context.Context) error, err error) { -// pool, ok := o.DB.(database.Pool) -// if !ok { -// // o.DB is already a client -// return func(_ context.Context) error { -// return nil -// }, nil -// } -// client, err := pool.Acquire(ctx) -// if err != nil { -// return nil, err -// } -// o.DB = client -// return func(ctx context.Context) error { -// return client.Release(ctx) -// }, nil -// } +// EnsureClient ensures that o.DB is a [database.Client]. If it is not, it will get a new [database.Client] from the [database.Pool]. +// The returned close function will release the [database.Client]. If the o.DB is already a [database.Client] or transaction, the close function +// will do nothing because another [Commander] is already responsible for releasing the [database.Client]. +func (o *CommandOpts) EnsureClient(ctx context.Context) (close func(_ context.Context) error, err error) { + pool, ok := o.DB.(database.Pool) + if !ok { + // o.DB is already a client + return func(_ context.Context) error { + return nil + }, nil + } + client, err := pool.Acquire(ctx) + if err != nil { + return nil, err + } + o.DB = client + return func(ctx context.Context) error { + return client.Release(ctx) + }, nil +} -// func (o *CommandOpts) Invoke(ctx context.Context, command Commander) error { -// if o.Invoker == nil { -// return command.Execute(ctx, o) -// } -// return o.Invoker.Invoke(ctx, command, o) -// } +// Invoke implements the [Invoker] interface. +func (o *CommandOpts) Invoke(ctx context.Context, command Commander) error { + if o.Invoker == nil { + return command.Execute(ctx, o) + } + return o.Invoker.Invoke(ctx, command, o) +} -// func DefaultOpts(invoker Invoker) *CommandOpts { -// if invoker == nil { -// invoker = &noopInvoker{} -// } -// return &CommandOpts{ -// DB: pool, -// Invoker: invoker, -// } -// } +func DefaultOpts(invoker Invoker) *CommandOpts { + if invoker == nil { + invoker = &noopInvoker{} + } + return &CommandOpts{ + DB: pool, + Invoker: invoker, + } +} -// // commandBatch is a batch of commands. -// // It uses the [Invoker] provided by the opts to execute each command. -// type commandBatch struct { -// Commands []Commander -// } +// commandBatch is a batch of commands. +// It uses the [Invoker] provided by the opts to execute each command. +type commandBatch struct { + Commands []Commander +} -// func BatchCommands(cmds ...Commander) *commandBatch { -// return &commandBatch{ -// Commands: cmds, -// } -// } +// BatchCommands creates a new command batch. +// The commands are executed in the order they are provided. +// If any command fails, the batch will stop executing and return the error. +func BatchCommands(cmds ...Commander) *commandBatch { + return &commandBatch{ + Commands: cmds, + } +} -// // String implements [Commander]. -// func (cmd *commandBatch) String() string { -// return "commandBatch" -// } +// String implements [Commander]. +func (cmd *commandBatch) String() string { + return "commandBatch" +} -// func (b *commandBatch) Execute(ctx context.Context, opts *CommandOpts) (err error) { -// for _, cmd := range b.Commands { -// if err = opts.Invoke(ctx, cmd); err != nil { -// return err -// } -// } -// return nil -// } +func (b *commandBatch) Execute(ctx context.Context, opts *CommandOpts) (err error) { + for _, cmd := range b.Commands { + if err = opts.Invoke(ctx, cmd); err != nil { + return err + } + } + return nil +} -// var _ Commander = (*commandBatch)(nil) +var _ Commander = (*commandBatch)(nil) diff --git a/backend/v3/domain/constants.go b/backend/v3/domain/constants.go new file mode 100644 index 0000000000..aee91d63bd --- /dev/null +++ b/backend/v3/domain/constants.go @@ -0,0 +1,63 @@ +package domain + +import ( + "math/rand/v2" + "strconv" + + "github.com/zitadel/zitadel/backend/v3/storage/database" + "github.com/zitadel/zitadel/backend/v3/telemetry/logging" + "github.com/zitadel/zitadel/backend/v3/telemetry/tracing" +) + +// The variables could also be moved to a struct. +// I just started with the [singleton pattern](https://refactoring.guru/design-patterns/singleton) and kept it like this. +var ( + pool database.Pool + // userCodeAlgorithm crypto.EncryptionAlgorithm + tracer tracing.Tracer + logger logging.Logger + + userRepo func(database.QueryExecutor) UserRepository + orgRepo func(database.QueryExecutor) OrganizationRepository + // instanceRepo func(database.QueryExecutor) InstanceRepository + // cryptoRepo func(database.QueryExecutor) CryptoRepository + + // instanceCache cache.Cache[instanceCacheIndex, string, *Instance] + // orgCache cache.Cache[orgCacheIndex, string, *Organization] + + generateID func() (string, error) = func() (string, error) { + return strconv.FormatUint(rand.Uint64(), 10), nil + } +) + +func SetPool(p database.Pool) { + pool = p +} + +// func SetUserCodeAlgorithm(algorithm crypto.EncryptionAlgorithm) { +// userCodeAlgorithm = algorithm +// } + +func SetTracer(t tracing.Tracer) { + tracer = t +} + +func SetLogger(l logging.Logger) { + logger = l +} + +func SetUserRepository(repo func(database.QueryExecutor) UserRepository) { + userRepo = repo +} + +func SetOrgRepository(repo func(database.QueryExecutor) OrganizationRepository) { + orgRepo = repo +} + +// func SetInstanceRepository(repo func(database.QueryExecutor) InstanceRepository) { +// instanceRepo = repo +// } + +// func SetCryptoRepository(repo func(database.QueryExecutor) CryptoRepository) { +// cryptoRepo = repo +// } diff --git a/backend/v3/domain/domain.go b/backend/v3/domain/domain.go index 03e6c8e243..f0ac706e95 100644 --- a/backend/v3/domain/domain.go +++ b/backend/v3/domain/domain.go @@ -63,68 +63,3 @@ type domainChanges interface { // This is used for reducing events. SetUpdatedAt(t time.Time) database.Change } - -// import ( -// "math/rand/v2" -// "strconv" - -// "github.com/zitadel/zitadel/backend/v3/storage/cache" -// "github.com/zitadel/zitadel/backend/v3/storage/database" - -// // "github.com/zitadel/zitadel/backend/v3/telemetry/logging" -// "github.com/zitadel/zitadel/backend/v3/telemetry/tracing" -// "github.com/zitadel/zitadel/internal/crypto" -// ) - -// // The variables could also be moved to a struct. -// // I just started with the singleton pattern and kept it like this. -// var ( -// pool database.Pool -// userCodeAlgorithm crypto.EncryptionAlgorithm -// tracer tracing.Tracer -// // logger logging.Logger - -// userRepo func(database.QueryExecutor) UserRepository -// // instanceRepo func(database.QueryExecutor) InstanceRepository -// cryptoRepo func(database.QueryExecutor) CryptoRepository -// orgRepo func(database.QueryExecutor) OrgRepository - -// // instanceCache cache.Cache[instanceCacheIndex, string, *Instance] -// orgCache cache.Cache[orgCacheIndex, string, *Org] - -// generateID func() (string, error) = func() (string, error) { -// return strconv.FormatUint(rand.Uint64(), 10), nil -// } -// ) - -// func SetPool(p database.Pool) { -// pool = p -// } - -// func SetUserCodeAlgorithm(algorithm crypto.EncryptionAlgorithm) { -// userCodeAlgorithm = algorithm -// } - -// func SetTracer(t tracing.Tracer) { -// tracer = t -// } - -// // func SetLogger(l logging.Logger) { -// // logger = l -// // } - -// func SetUserRepository(repo func(database.QueryExecutor) UserRepository) { -// userRepo = repo -// } - -// func SetOrgRepository(repo func(database.QueryExecutor) OrgRepository) { -// orgRepo = repo -// } - -// // func SetInstanceRepository(repo func(database.QueryExecutor) InstanceRepository) { -// // instanceRepo = repo -// // } - -// func SetCryptoRepository(repo func(database.QueryExecutor) CryptoRepository) { -// cryptoRepo = repo -// } diff --git a/backend/v3/domain/invoke.go b/backend/v3/domain/invoke.go index 8c25bad6ba..762bebfa71 100644 --- a/backend/v3/domain/invoke.go +++ b/backend/v3/domain/invoke.go @@ -1,158 +1,165 @@ package domain -// import ( -// "context" -// "fmt" +import ( + "context" + "fmt" -// "github.com/zitadel/zitadel/backend/v3/storage/eventstore" -// ) + "github.com/zitadel/zitadel/backend/v3/storage/eventstore" +) -// // Invoke provides a way to execute commands within the domain package. -// // It uses a chain of responsibility pattern to handle the command execution. -// // The default chain includes logging, tracing, and event publishing. -// // If you want to invoke multiple commands in a single transaction, you can use the [commandBatch]. -// func Invoke(ctx context.Context, cmd Commander) error { -// invoker := newEventStoreInvoker(newLoggingInvoker(newTraceInvoker(nil))) -// opts := &CommandOpts{ -// Invoker: invoker.collector, -// DB: pool, -// } -// return invoker.Invoke(ctx, cmd, opts) -// } +// Invoke provides a way to execute commands within the domain package. +// It uses the [chain of responsibility](https://refactoring.guru/design-patterns/chain-of-responsibility) pattern to handle the command execution. +// The default chain includes logging, tracing, and event publishing. +// If you want to invoke multiple commands in a single transaction, you can use the [commandBatch]. +func Invoke(ctx context.Context, cmd Commander) error { + invoker := newEventStoreInvoker(newLoggingInvoker(newTraceInvoker(nil))) + opts := &CommandOpts{ + Invoker: invoker.collector, + DB: pool, + } + return invoker.Invoke(ctx, cmd, opts) +} -// // eventStoreInvoker checks if the command implements the [eventer] interface. -// // If it does, it collects the events and publishes them to the event store. -// type eventStoreInvoker struct { -// collector *eventCollector -// } +// eventStoreInvoker checks if the command implements the [eventer] interface. +// If it does, it collects the events and publishes them to the event store. +type eventStoreInvoker struct { + collector *eventCollector +} -// func newEventStoreInvoker(next Invoker) *eventStoreInvoker { -// return &eventStoreInvoker{collector: &eventCollector{next: next}} -// } +func newEventStoreInvoker(next Invoker) *eventStoreInvoker { + return &eventStoreInvoker{collector: &eventCollector{next: next}} +} -// func (i *eventStoreInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { -// err = i.collector.Invoke(ctx, command, opts) -// if err != nil { -// return err -// } -// if len(i.collector.events) > 0 { -// err = eventstore.Publish(ctx, i.collector.events, opts.DB) -// if err != nil { -// return err -// } -// } -// return nil -// } +// Invoke implements the [Invoker] interface. +func (i *eventStoreInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { + err = i.collector.Invoke(ctx, command, opts) + if err != nil { + return err + } + if len(i.collector.events) > 0 { + err = eventstore.Publish(ctx, i.collector.events, opts.DB) + if err != nil { + return err + } + } + return nil +} -// // eventCollector collects events from all commands. The [eventStoreInvoker] pushes the collected events after all commands are executed. -// type eventCollector struct { -// next Invoker -// events []*eventstore.Event -// } +// eventCollector collects events from all commands. The [eventStoreInvoker] pushes the collected events after all commands are executed. +type eventCollector struct { + next Invoker + events []*eventstore.Event +} -// type eventer interface { -// Events() []*eventstore.Event -// } +type eventer interface { + Events() []*eventstore.Event +} -// func (i *eventCollector) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { -// if e, ok := command.(eventer); ok && len(e.Events()) > 0 { -// // we need to ensure all commands are executed in the same transaction -// close, err := opts.EnsureTx(ctx) -// if err != nil { -// return err -// } -// defer func() { err = close(ctx, err) }() +// Invoke implements the [Invoker] interface. +func (i *eventCollector) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { + if e, ok := command.(eventer); ok && len(e.Events()) > 0 { + // we need to ensure all commands are executed in the same transaction + close, err := opts.EnsureTx(ctx) + if err != nil { + return err + } + defer func() { err = close(ctx, err) }() -// i.events = append(i.events, e.Events()...) -// } -// if i.next != nil { -// return i.next.Invoke(ctx, command, opts) -// } -// return command.Execute(ctx, opts) -// } + i.events = append(i.events, e.Events()...) + } + if i.next != nil { + return i.next.Invoke(ctx, command, opts) + } + return command.Execute(ctx, opts) +} -// // traceInvoker decorates each command with tracing. -// type traceInvoker struct { -// next Invoker -// } +// traceInvoker decorates each command with tracing. +type traceInvoker struct { + next Invoker +} -// func newTraceInvoker(next Invoker) *traceInvoker { -// return &traceInvoker{next: next} -// } +func newTraceInvoker(next Invoker) *traceInvoker { + return &traceInvoker{next: next} +} -// func (i *traceInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { -// ctx, span := tracer.Start(ctx, fmt.Sprintf("%T", command)) -// defer func() { -// if err != nil { -// span.RecordError(err) -// } -// span.End() -// }() +// Invoke implements the [Invoker] interface. +func (i *traceInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { + ctx, span := tracer.Start(ctx, fmt.Sprintf("%T", command)) + defer func() { + if err != nil { + span.RecordError(err) + } + span.End() + }() -// if i.next != nil { -// return i.next.Invoke(ctx, command, opts) -// } -// return command.Execute(ctx, opts) -// } + if i.next != nil { + return i.next.Invoke(ctx, command, opts) + } + return command.Execute(ctx, opts) +} -// // loggingInvoker decorates each command with logging. -// // It is an example implementation and logs the command name at the beginning and success or failure after the command got executed. -// type loggingInvoker struct { -// next Invoker -// } +// loggingInvoker decorates each command with logging. +// It is an example implementation and logs the command name at the beginning and success or failure after the command got executed. +type loggingInvoker struct { + next Invoker +} -// func newLoggingInvoker(next Invoker) *loggingInvoker { -// return &loggingInvoker{next: next} -// } +func newLoggingInvoker(next Invoker) *loggingInvoker { + return &loggingInvoker{next: next} +} -// func (i *loggingInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { -// logger.InfoContext(ctx, "Invoking command", "command", command.String()) +// Invoke implements the [Invoker] interface. +func (i *loggingInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { + logger.InfoContext(ctx, "Invoking command", "command", command.String()) -// if i.next != nil { -// err = i.next.Invoke(ctx, command, opts) -// } else { -// err = command.Execute(ctx, opts) -// } + if i.next != nil { + err = i.next.Invoke(ctx, command, opts) + } else { + err = command.Execute(ctx, opts) + } -// if err != nil { -// logger.ErrorContext(ctx, "Command invocation failed", "command", command.String(), "error", err) -// return err -// } -// logger.InfoContext(ctx, "Command invocation succeeded", "command", command.String()) -// return nil -// } + if err != nil { + logger.ErrorContext(ctx, "Command invocation failed", "command", command.String(), "error", err) + return err + } + logger.InfoContext(ctx, "Command invocation succeeded", "command", command.String()) + return nil +} -// type noopInvoker struct { -// next Invoker -// } +// noopInvoker executes the command without any additional decoration. +type noopInvoker struct { + next Invoker +} -// func (i *noopInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) error { -// if i.next != nil { -// return i.next.Invoke(ctx, command, opts) -// } -// return command.Execute(ctx, opts) -// } +// Invoke implements the [Invoker] interface. +func (i *noopInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) error { + if i.next != nil { + return i.next.Invoke(ctx, command, opts) + } + return command.Execute(ctx, opts) +} -// // cacheInvoker could be used in the future to do the caching. -// // My goal would be to have two interfaces: -// // - cacheSetter: which caches an object -// // - cacheGetter: which gets an object from the cache, this should also skip the command execution -// type cacheInvoker struct { -// next Invoker -// } +// cacheInvoker could be used in the future to do the caching. +// My goal would be to have two interfaces: +// - cacheSetter: which caches an object +// - cacheGetter: which gets an object from the cache, this should also skip the command execution +type cacheInvoker struct { + next Invoker +} -// type cacher interface { -// Cache(opts *CommandOpts) -// } +type cacher interface { + Cache(opts *CommandOpts) +} -// func (i *cacheInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { -// if c, ok := command.(cacher); ok { -// c.Cache(opts) -// } -// if i.next != nil { -// err = i.next.Invoke(ctx, command, opts) -// } else { -// err = command.Execute(ctx, opts) -// } -// return err -// } +// Invoke implements the [Invoker] interface. +func (i *cacheInvoker) Invoke(ctx context.Context, command Commander, opts *CommandOpts) (err error) { + if c, ok := command.(cacher); ok { + c.Cache(opts) + } + if i.next != nil { + err = i.next.Invoke(ctx, command, opts) + } else { + err = command.Execute(ctx, opts) + } + return err +} diff --git a/backend/v3/domain/organization.go b/backend/v3/domain/organization.go index 6e51fe19da..44179027b9 100644 --- a/backend/v3/domain/organization.go +++ b/backend/v3/domain/organization.go @@ -88,8 +88,8 @@ type OrganizationRepository interface { Delete(ctx context.Context, id OrgIdentifierCondition, instance_id string) (int64, error) // Domains returns the domain sub repository for the organization. - // If shouldLoad is true, the domains will be loaded from the database and written to the [Instance].Domains field. - // If shouldLoad is set to true once, the Domains field will be set event if shouldLoad is false in the future. + // If shouldLoad is true, the domains will be loaded from the database and written to the [Organization].Domains field. + // If shouldLoad is set to true once, the Domains field will be set even if shouldLoad is false in the future. Domains(shouldLoad bool) OrganizationDomainRepository }