Skip to content

Commit

Permalink
refactored gateway service instantiation
Browse files Browse the repository at this point in the history
  • Loading branch information
adranwit committed Mar 28, 2024
1 parent b11c5bb commit 3b5c693
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 85 deletions.
1 change: 1 addition & 0 deletions gateway/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func (c *Config) SyncFrequency() time.Duration {
}

func NewConfigFromURL(ctx context.Context, fs afs.Service, URL string) (*Config, error) {
fs = NewFs(URL, fs)
data, err := fs.DownloadWithURL(ctx, URL)
if err != nil {
return nil, err
Expand Down
120 changes: 120 additions & 0 deletions gateway/option.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package gateway

import (
"context"
"embed"
"github.com/viant/datly/repository"
"github.com/viant/datly/view/extension"
"github.com/viant/gmetric"
"net/http"
)

type options struct {
config *Config
authorizer Authorizer
extensions *extension.Registry
metrics *gmetric.Service
repository *repository.Service
statusHandler http.Handler
embedFs *embed.FS
configURL string
authProvider func(config *Config, fs *embed.FS) (Authorizer, error)
}

func newOptions(ctx context.Context, opts ...Option) (*options, error) {
result := &options{}
for _, option := range opts {
option(result)
}
if result.metrics == nil {
result.metrics = gmetric.New()
}
if ext := result.extensions; ext == nil {
result.extensions = extension.NewRegistry()
}

if result.config == nil {
if result.configURL != "" {
var err error

if result.config, err = NewConfigFromURL(ctx, fs, result.configURL); err != nil {
return nil, err
}
}
}
if result.config == nil {
result.config = &Config{}
}

if result.authorizer == nil && result.authProvider != nil {
var err error
if result.authorizer, err = result.authProvider(result.config, result.embedFs); err != nil {
return nil, err
}
}

return result, nil
}

// Option represents a service option
type Option func(*options)

// WithConfig sets a config
func WithConfig(config *Config) Option {
return func(o *options) {
o.config = config
}
}

// WithAuthorizer sets an authorizer
func WithAuthorizer(authorizer Authorizer) Option {
return func(o *options) {
o.authorizer = authorizer
}
}

// WithExtensions sets an extension registry
func WithExtensions(registry *extension.Registry) Option {
return func(o *options) {
o.extensions = registry
}
}

// WithMetrics sets a metrics service
func WithMetrics(metrics *gmetric.Service) Option {
return func(o *options) {
o.metrics = metrics
}
}

// WithRepository sets a repository service
func WithRepository(repository *repository.Service) Option {
return func(o *options) {
o.repository = repository
}
}

// WithEmbedFs sets an embed file system
func WithEmbedFs(embedFs *embed.FS) Option {
return func(o *options) {
o.embedFs = embedFs
}
}

func WithStatusHandler(handler http.Handler) Option {
return func(o *options) {
o.statusHandler = handler
}
}

func WithAuthProvider(authProvider func(config *Config, fs *embed.FS) (Authorizer, error)) Option {
return func(o *options) {
o.authProvider = authProvider
}
}

func WithConfigURL(configURL string) Option {
return func(o *options) {
o.configURL = configURL
}
}
5 changes: 3 additions & 2 deletions gateway/runtime/gcf/handler.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gcf

import (
"context"
"fmt"
_ "github.com/go-sql-driver/mysql"
_ "github.com/viant/afs/embed"
Expand Down Expand Up @@ -38,8 +39,8 @@ func handleRequest(w http.ResponseWriter, r *http.Request) error {
if configURL == "" {
return fmt.Errorf("config was emrty")
}

service, err := gateway.Singleton(configURL, nil, nil, extension.Config, nil)
ctx := context.Background()
service, err := gateway.Singleton(ctx, gateway.WithConfigURL(configURL), gateway.WithExtensions(extension.Config))
if err != nil {
return err
}
Expand Down
30 changes: 7 additions & 23 deletions gateway/runtime/serverless/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ package serverless

import (
"context"
"embed"
"fmt"
"github.com/viant/datly/gateway"
"github.com/viant/datly/service/auth/jwt"
"github.com/viant/datly/view/extension"
"os"
"sync"
)

var gatewayConfig *gateway.Config
var configInit sync.Once

var _service *gateway.Service

Expand All @@ -23,30 +22,15 @@ func GetService() (*gateway.Service, error) {
if configURL == "" {
return nil, fmt.Errorf("config was emty")
}

var err error
fs := gateway.NewFs(configURL)
configInit.Do(func() {
gatewayConfig, err = gateway.NewConfigFromURL(context.Background(), fs, configURL)
})

if err != nil {
configInit = sync.Once{}
return nil, err
}

var authorizer gateway.Authorizer
if jwtAuthorizer, err := jwt.Init(gatewayConfig, nil); err == nil {
authorizer = jwtAuthorizer
} else {
return nil, err
}

service, err := gateway.SingletonWithConfig(gatewayConfig, nil, authorizer, extension.Config, nil)
service, err := gateway.Singleton(context.Background(),
gateway.WithAuthProvider(func(config *gateway.Config, fs *embed.FS) (gateway.Authorizer, error) {
return jwt.Init(gatewayConfig, fs)
}),
gateway.WithConfigURL(configURL),
gateway.WithExtensions(extension.Config))
if err != nil {
return nil, err
}

_service = service
return service, nil
}
10 changes: 10 additions & 0 deletions gateway/runtime/standalone/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ type Options struct {
useSingleton *bool
}

func (o *Options) UseSingleton() bool {
if o.useSingleton == nil {
return true
}
return *o.useSingleton
}

func NewOptions(ctx context.Context, opts ...Option) (*Options, error) {
options := &Options{}
for _, opt := range opts {
Expand Down Expand Up @@ -44,18 +51,21 @@ func NewOptions(ctx context.Context, opts ...Option) (*Options, error) {
// Option represents standalone option
type Option func(*Options)

// WithAuth sets an authorizer
func WithAuth(auth gateway.Authorizer) Option {
return func(o *Options) {
o.auth = auth
}
}

// WithConfig sets a config
func WithConfig(config *Config) Option {
return func(o *Options) {
o.config = config
}
}

// WithVersion sets a version
func WithUseSingleton(useSingleton *bool) Option {
return func(o *Options) {
o.useSingleton = useSingleton
Expand Down
21 changes: 13 additions & 8 deletions gateway/runtime/standalone/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,22 +47,27 @@ func New(ctx context.Context, opts ...Option) (*Server, error) {
if config.Config == nil {
return nil, fmt.Errorf("gateway config was empty")
}
service, err := gateway.SingletonWithConfig(
config.Config,
handler.NewStatus(config.Version, &config.Meta),
options.auth,
extension.Config,
metric,
)

var service *gateway.Service
var gOptions = []gateway.Option{
gateway.WithExtensions(extension.Config),
gateway.WithConfig(config.Config),
gateway.WithMetrics(metric),
gateway.WithStatusHandler(handler.NewStatus(config.Version, &config.Meta)),
gateway.WithAuthorizer(options.auth),
}
if options.UseSingleton() {
service, err = gateway.Singleton(ctx, gOptions...)
} else {
service, err = gateway.New(ctx, gOptions...)
}
if err != nil {
if service != nil {
_ = service.Close()
}

return nil, err
}

server := &Server{
Service: service,
Server: http.Server{
Expand Down
49 changes: 25 additions & 24 deletions gateway/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"github.com/viant/datly/shared"
"github.com/viant/datly/utils/httputils"
"github.com/viant/datly/view"
"github.com/viant/datly/view/extension"
"github.com/viant/gmetric"
"github.com/viant/scy/auth/jwt/signer"
"net/http"
Expand Down Expand Up @@ -76,46 +75,48 @@ func (r *Service) Close() error {
}

// New creates gateway Service. It is important to call Service.Close before Service got Garbage collected.
func New(ctx context.Context, aConfig *Config, statusHandler http.Handler, authorizer Authorizer, extensions *extension.Registry, metrics *gmetric.Service) (*Service, error) {
func New(ctx context.Context, opts ...Option) (*Service, error) {
start := time.Now()
if err := aConfig.Init(ctx); err != nil {
return nil, err
}
err := aConfig.Validate()
options, err := newOptions(ctx, opts...)
if err != nil {
return nil, err
}
aConfig := options.config

if err := aConfig.Init(ctx); err != nil {
return nil, err
}
fs, err := newFileService(aConfig)
if err != nil {
return nil, err
}

repository, err := repository.New(ctx, repository.WithComponentURL(aConfig.RouteURL),
repository.WithResourceURL(aConfig.DependencyURL),
repository.WithPluginURL(aConfig.PluginsURL),
repository.WithApiPrefix(aConfig.APIPrefix),
repository.WithExtensions(extensions),
repository.WithMetrics(metrics),
repository.WithRefreshFrequency(aConfig.SyncFrequency()),
repository.WithDispatcher(dispatcher.New),
)
if err != nil {
return nil, fmt.Errorf("failed to initialise component service: %w", err)
componentRepository := options.repository
if componentRepository == nil {
componentRepository, err = repository.New(ctx, repository.WithComponentURL(aConfig.RouteURL),
repository.WithResourceURL(aConfig.DependencyURL),
repository.WithPluginURL(aConfig.PluginsURL),
repository.WithApiPrefix(aConfig.APIPrefix),
repository.WithExtensions(options.extensions),
repository.WithMetrics(options.metrics),
repository.WithRefreshFrequency(aConfig.SyncFrequency()),
repository.WithDispatcher(dispatcher.New),
)
if err != nil {
return nil, fmt.Errorf("failed to initialise component service: %w", err)
}
}

mainRouter, err := NewRouter(ctx, repository, aConfig, metrics, statusHandler, authorizer)
mainRouter, err := NewRouter(ctx, componentRepository, aConfig, options.metrics, options.statusHandler, options.authorizer)
if err != nil {
return nil, err
}
srv := &Service{
metrics: metrics,
repository: repository,
metrics: options.metrics,
repository: componentRepository,
Config: aConfig,
mux: sync.RWMutex{},
fs: fs,
statusHandler: statusHandler,
authorizer: authorizer,
statusHandler: options.statusHandler,
authorizer: options.authorizer,
mainRouter: mainRouter,
}
if aConfig.JwtSigner != nil {
Expand Down
Loading

0 comments on commit 3b5c693

Please sign in to comment.