From ff25a516cffdf1c9d7141b1a6aba77cdacacbdef Mon Sep 17 00:00:00 2001 From: adlerhurst <27845747+adlerhurst@users.noreply.github.com> Date: Sun, 16 Mar 2025 11:36:00 +0100 Subject: [PATCH] simplify options --- backend/repository/orchestrate/instance.go | 43 +++++++------------ .../repository/orchestrate/instance_test.go | 18 ++++---- backend/repository/orchestrate/option.go | 25 ++++++++--- backend/repository/orchestrate/user.go | 43 ++++++++----------- 4 files changed, 60 insertions(+), 69 deletions(-) diff --git a/backend/repository/orchestrate/instance.go b/backend/repository/orchestrate/instance.go index 1b1c3fd27f..9c87a609c5 100644 --- a/backend/repository/orchestrate/instance.go +++ b/backend/repository/orchestrate/instance.go @@ -2,7 +2,6 @@ package orchestrate import ( "context" - "fmt" "github.com/zitadel/zitadel/backend/repository" "github.com/zitadel/zitadel/backend/repository/cache" @@ -15,43 +14,33 @@ import ( "github.com/zitadel/zitadel/backend/telemetry/tracing" ) -type instance struct { - options - +type InstanceOptions struct { cache *cache.Instance } -func Instance(opts ...InstanceConfig) *instance { - i := new(instance) +type instance struct { + options[InstanceOptions] + *InstanceOptions +} + +func Instance(opts ...Option[InstanceOptions]) *instance { + i := instance{ + options: newOptions[InstanceOptions](), + } + i.InstanceOptions = i.options.custom for _, opt := range opts { - opt.applyInstance(i) + opt.apply(&i.options) } - return i + return &i } -func WithInstanceCache(cache *cache.Instance) instanceOption { - return func(i *instance) { - i.cache = cache +func WithInstanceCache(cache *cache.Instance) Option[InstanceOptions] { + return func(opts *options[InstanceOptions]) { + opts.custom.cache = cache } } -type InstanceConfig interface { - applyInstance(*instance) -} - -// instanceOption applies an option to the instance. -type instanceOption func(*instance) - -func (io instanceOption) applyInstance(i *instance) { - io(i) -} - -func (o Option) applyInstance(i *instance) { - o(&i.options) -} - func (i *instance) Create(ctx context.Context, tx database.Transaction, instance *repository.Instance) (*repository.Instance, error) { - fmt.Println("----------------") return traced.Wrap(i.tracer, "instance.SetUp", handler.Chains( handler.Decorates( diff --git a/backend/repository/orchestrate/instance_test.go b/backend/repository/orchestrate/instance_test.go index 4e03983f51..d33fef89b3 100644 --- a/backend/repository/orchestrate/instance_test.go +++ b/backend/repository/orchestrate/instance_test.go @@ -24,16 +24,16 @@ func Test_instance_SetUp(t *testing.T) { } tests := []struct { name string - opts []orchestrate.InstanceConfig + opts []orchestrate.Option[orchestrate.InstanceOptions] args args want *repository.Instance wantErr bool }{ { name: "simple", - opts: []orchestrate.InstanceConfig{ - orchestrate.WithTracer(tracing.NewTracer("test")), - orchestrate.WithLogger(logging.New(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))), + opts: []orchestrate.Option[orchestrate.InstanceOptions]{ + orchestrate.WithTracer[orchestrate.InstanceOptions](tracing.NewTracer("test")), + orchestrate.WithLogger[orchestrate.InstanceOptions](logging.New(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))), orchestrate.WithInstanceCache(cache.NewInstance()), }, args: args{ @@ -52,9 +52,9 @@ func Test_instance_SetUp(t *testing.T) { }, { name: "without cache", - opts: []orchestrate.InstanceConfig{ - orchestrate.WithTracer(tracing.NewTracer("test")), - orchestrate.WithLogger(logging.New(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))), + opts: []orchestrate.Option[orchestrate.InstanceOptions]{ + orchestrate.WithTracer[orchestrate.InstanceOptions](tracing.NewTracer("test")), + orchestrate.WithLogger[orchestrate.InstanceOptions](logging.New(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))), }, args: args{ ctx: context.Background(), @@ -72,8 +72,8 @@ func Test_instance_SetUp(t *testing.T) { }, { name: "without cache, tracer", - opts: []orchestrate.InstanceConfig{ - orchestrate.WithLogger(logging.New(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))), + opts: []orchestrate.Option[orchestrate.InstanceOptions]{ + orchestrate.WithLogger[orchestrate.InstanceOptions](logging.New(slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})))), }, args: args{ ctx: context.Background(), diff --git a/backend/repository/orchestrate/option.go b/backend/repository/orchestrate/option.go index 11fe7fca06..d8bef009e9 100644 --- a/backend/repository/orchestrate/option.go +++ b/backend/repository/orchestrate/option.go @@ -6,25 +6,36 @@ import ( ) // options are the default options for orchestrators. -type options struct { +type options[T any] struct { + custom *T tracer *tracing.Tracer logger *logging.Logger } -type Option func(*options) +func newOptions[T any]() options[T] { + return options[T]{ + custom: new(T), + } +} -func WithTracer(tracer *tracing.Tracer) Option { - return func(o *options) { +type applier interface { + apply() +} + +type Option[T any] func(*options[T]) + +func WithTracer[T any](tracer *tracing.Tracer) Option[T] { + return func(o *options[T]) { o.tracer = tracer } } -func WithLogger(logger *logging.Logger) Option { - return func(o *options) { +func WithLogger[T any](logger *logging.Logger) Option[T] { + return func(o *options[T]) { o.logger = logger } } -func (o Option) apply(opts *options) { +func (o Option[T]) apply(opts *options[T]) { o(opts) } diff --git a/backend/repository/orchestrate/user.go b/backend/repository/orchestrate/user.go index e3c9385d1a..a9fb48ba77 100644 --- a/backend/repository/orchestrate/user.go +++ b/backend/repository/orchestrate/user.go @@ -13,41 +13,32 @@ import ( "github.com/zitadel/zitadel/backend/telemetry/tracing" ) -type user struct { - options - +type UserOptions struct { cache *cache.User } -func User(opts ...Option) *user { - i := new(user) +type user struct { + options[UserOptions] + *UserOptions +} + +func User(opts ...Option[UserOptions]) *user { + i := user{ + options: newOptions[UserOptions](), + } + i.UserOptions = i.options.custom for _, opt := range opts { opt(&i.options) } - return i + return &i } -func WithUserCache(cache *cache.User) userOption { - return func(i *user) { - i.cache = cache +func WithUserCache(cache *cache.User) Option[UserOptions] { + return func(i *options[UserOptions]) { + i.custom.cache = cache } } -type UserConfig interface { - applyUser(*user) -} - -// userOption applies an option to the user. -type userOption func(*user) - -func (io userOption) applyUser(i *user) { - io(i) -} - -func (o Option) applyUser(i *user) { - o(&i.options) -} - func (i *user) Create(ctx context.Context, tx database.Transaction, user *repository.User) (*repository.User, error) { return traced.Wrap(i.tracer, "user.Create", handler.Chain( @@ -65,13 +56,13 @@ func (i *user) Create(ctx context.Context, tx database.Transaction, user *reposi func (i *user) ByID(ctx context.Context, querier database.Querier, id string) (*repository.User, error) { return handler.SkipNext( - i.cache.ByID, + i.custom.cache.ByID, handler.Chain( handler.Decorate( sql.Query(querier).UserByID, traced.Decorate[string, *repository.User](i.tracer, tracing.WithSpanName("user.sql.ByID")), ), - handler.SkipNilHandler(i.cache, i.cache.Set), + handler.SkipNilHandler(i.custom.cache, i.custom.cache.Set), ), )(ctx, id) }