diff --git a/cmd/listener.go b/cmd/listener.go index 5e02b36..9f61091 100644 --- a/cmd/listener.go +++ b/cmd/listener.go @@ -86,12 +86,21 @@ var listenCmd = &cobra.Command{ log.Fatal().Err(err).Msg("failed to create client from config") } + // Build shared components to maximize reuse across modes + ioHandler, err := workspacefile.NewIOHandler(appCfg.OpenApiDefinitionsPath) + if err != nil { + log.Fatal().Err(err).Msg("unable to create IO handler") + } + schemaResolver := apischema.NewResolver(log) + reconcilerOpts := reconciler.ReconcilerOpts{ Scheme: scheme, Client: clt, Config: restCfg, ManagerOpts: mgrOpts, OpenAPIDefinitionsPath: appCfg.OpenApiDefinitionsPath, + IOHandler: ioHandler, + SchemaResolver: schemaResolver, } // Create the appropriate reconciler based on configuration @@ -114,12 +123,8 @@ var listenCmd = &cobra.Command{ reconcilerInstance = kcpReconciler } else { - ioHandler, err := workspacefile.NewIOHandler(appCfg.OpenApiDefinitionsPath) - if err != nil { - log.Fatal().Err(err).Msg("unable to create IO handler") - } - - reconcilerInstance, err = clusteraccess.NewClusterAccessReconciler(ctx, appCfg, reconcilerOpts, ioHandler, apischema.NewResolver(log), log) + // Reuse shared IO handler and schema resolver via opts (pass nils to use opts) + reconcilerInstance, err = clusteraccess.NewClusterAccessReconciler(ctx, appCfg, reconcilerOpts, nil, nil, log) if err != nil { log.Fatal().Err(err).Msg("unable to create cluster access reconciler") } diff --git a/listener/reconciler/clusteraccess/reconciler.go b/listener/reconciler/clusteraccess/reconciler.go index 093d797..f686b74 100644 --- a/listener/reconciler/clusteraccess/reconciler.go +++ b/listener/reconciler/clusteraccess/reconciler.go @@ -40,6 +40,14 @@ func NewClusterAccessReconciler( schemaResolver apischema.Resolver, log *logger.Logger, ) (reconciler.CustomReconciler, error) { + // Allow dependencies to be supplied via opts when not provided explicitly for reuse + if ioHandler == nil { + ioHandler = opts.IOHandler + } + if schemaResolver == nil { + schemaResolver = opts.SchemaResolver + } + // Validate required dependencies if ioHandler == nil { return nil, fmt.Errorf("ioHandler is required") diff --git a/listener/reconciler/kcp/reconciler.go b/listener/reconciler/kcp/reconciler.go index 598240a..77eedaa 100644 --- a/listener/reconciler/kcp/reconciler.go +++ b/listener/reconciler/kcp/reconciler.go @@ -37,15 +37,25 @@ func NewKCPReconciler( return nil, err } - // Create IO handler for schema files - ioHandler, err := workspacefile.NewIOHandler(appCfg.OpenApiDefinitionsPath) - if err != nil { - log.Error().Err(err).Msg("failed to create IO handler") - return nil, err + // Create or reuse IO handler for schema files + var ioHandler *workspacefile.FileHandler + if opts.IOHandler != nil { + ioHandler = opts.IOHandler + } else { + ioHandler, err = workspacefile.NewIOHandler(appCfg.OpenApiDefinitionsPath) + if err != nil { + log.Error().Err(err).Msg("failed to create IO handler") + return nil, err + } } - // Create schema resolver - schemaResolver := apischema.NewResolver(log) + // Create or reuse schema resolver + var schemaResolver apischema.Resolver + if opts.SchemaResolver != nil { + schemaResolver = opts.SchemaResolver + } else { + schemaResolver = apischema.NewResolver(log) + } // Create cluster path resolver clusterPathResolver, err := NewClusterPathResolver(opts.Config, opts.Scheme) diff --git a/listener/reconciler/types.go b/listener/reconciler/types.go index a7632f4..077c381 100644 --- a/listener/reconciler/types.go +++ b/listener/reconciler/types.go @@ -3,6 +3,9 @@ package reconciler import ( "context" + "github.com/platform-mesh/kubernetes-graphql-gateway/listener/pkg/apischema" + "github.com/platform-mesh/kubernetes-graphql-gateway/listener/pkg/workspacefile" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" @@ -23,4 +26,8 @@ type ReconcilerOpts struct { client.Client ManagerOpts ctrl.Options OpenAPIDefinitionsPath string + // Optional shared dependencies to maximize reuse across modes. If nil, + // each reconciler may construct its own defaults. + IOHandler *workspacefile.FileHandler + SchemaResolver apischema.Resolver }