From 71ae8d185638c0707bedc32796c84b8e4062f7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Pablo=20Villaf=C3=A1=C3=B1ez?= Date: Tue, 1 Feb 2022 17:30:07 +0100 Subject: [PATCH] Use decorator pattern and allow more methods to be decorated --- thumbnails/pkg/server/grpc/server.go | 9 +-- thumbnails/pkg/service/v0/decorators/base.go | 59 +++++++++++++++++++ .../service/v0/{ => decorators}/instrument.go | 10 ++-- .../service/v0/{ => decorators}/logging.go | 10 ++-- .../service/v0/{ => decorators}/tracing.go | 8 +-- thumbnails/pkg/service/v0/service.go | 3 +- 6 files changed, 80 insertions(+), 19 deletions(-) create mode 100644 thumbnails/pkg/service/v0/decorators/base.go rename thumbnails/pkg/service/v0/{ => decorators}/instrument.go (80%) rename thumbnails/pkg/service/v0/{ => decorators}/logging.go (79%) rename thumbnails/pkg/service/v0/{ => decorators}/tracing.go (87%) diff --git a/thumbnails/pkg/server/grpc/server.go b/thumbnails/pkg/server/grpc/server.go index 815154c7a7..af21ec485b 100644 --- a/thumbnails/pkg/server/grpc/server.go +++ b/thumbnails/pkg/server/grpc/server.go @@ -6,6 +6,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/version" thumbnailssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/thumbnails/v0" svc "github.com/owncloud/ocis/thumbnails/pkg/service/v0" + "github.com/owncloud/ocis/thumbnails/pkg/service/v0/decorators" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail/imgsource" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail/storage" ) @@ -30,7 +31,7 @@ func NewService(opts ...Option) grpc.Service { options.Logger.Error().Err(err).Msg("could not get gateway client") return grpc.Service{} } - var thumbnail thumbnailssvc.ThumbnailServiceHandler + var thumbnail decorators.DecoratedService { thumbnail = svc.NewService( svc.Config(options.Config), @@ -45,9 +46,9 @@ func NewService(opts ...Option) grpc.Service { svc.CS3Source(imgsource.NewCS3Source(tconf, gc)), svc.CS3Client(gc), ) - thumbnail = svc.NewInstrument(thumbnail, options.Metrics) - thumbnail = svc.NewLogging(thumbnail, options.Logger) - thumbnail = svc.NewTracing(thumbnail) + thumbnail = decorators.NewInstrument(thumbnail, options.Metrics) + thumbnail = decorators.NewLogging(thumbnail, options.Logger) + thumbnail = decorators.NewTracing(thumbnail) } _ = thumbnailssvc.RegisterThumbnailServiceHandler( diff --git a/thumbnails/pkg/service/v0/decorators/base.go b/thumbnails/pkg/service/v0/decorators/base.go new file mode 100644 index 0000000000..d2970886af --- /dev/null +++ b/thumbnails/pkg/service/v0/decorators/base.go @@ -0,0 +1,59 @@ +package decorators + +import ( + "context" + + thumbnailssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/thumbnails/v0" +) + +// Interface acting as facade, holding all the interfaces that this +// thumbnails microservice is expecting to implement. +// For now, only the thumbnailssvc.ThumbnailServiceHandler is present, +// but a future configsvc.ConfigServiceHandler is expected to be added here +// +// This interface will also act as the base interface to implement +// a decorator pattern. +type DecoratedService interface { + thumbnailssvc.ThumbnailServiceHandler +} + +// Base type to implement the decorators. It will provide a basic implementation +// by delegating to the decoratedService +// +// Expected implementations will be like: +// ``` +// type MyDecorator struct { +// Decorator +// myCustomOpts *opts +// additionalSrv *srv +// } +// +// func NewMyDecorator(next DecoratedService, customOpts *customOpts) DecoratedService { +// ..... +// return MyDecorator{ +// Decorator: Decorator{next: next}, +// myCustomOpts: opts, +// additionalSrv: srv, +// } +// } +// ``` +type Decorator struct { + next DecoratedService +} + +// Base implementation for the GetThumbnail (for the thumbnailssvc). +// It will just delegate to the underlying decoratedService +// +// Your custom decorator is expected to overwrite this function, +// but it MUST call the underlying decoratedService at some point +// ``` +// func (d MyDecorator) GetThumbnail(ctx context.Context, req *thumbnailssvc.GetThumbnailRequest, resp *thumbnailssvc.GetThumbnailResponse) error { +// doSomething() +// err := d.next.GetThumbnail(ctx, req, resp) +// doAnotherThing() +// return err +// } +// ``` +func (deco Decorator) GetThumbnail(ctx context.Context, req *thumbnailssvc.GetThumbnailRequest, resp *thumbnailssvc.GetThumbnailResponse) error { + return deco.next.GetThumbnail(ctx, req, resp) +} diff --git a/thumbnails/pkg/service/v0/instrument.go b/thumbnails/pkg/service/v0/decorators/instrument.go similarity index 80% rename from thumbnails/pkg/service/v0/instrument.go rename to thumbnails/pkg/service/v0/decorators/instrument.go index 9423349d8e..32db036f1e 100644 --- a/thumbnails/pkg/service/v0/instrument.go +++ b/thumbnails/pkg/service/v0/decorators/instrument.go @@ -1,4 +1,4 @@ -package svc +package decorators import ( "context" @@ -9,15 +9,15 @@ import ( ) // NewInstrument returns a service that instruments metrics. -func NewInstrument(next thumbnailssvc.ThumbnailServiceHandler, metrics *metrics.Metrics) thumbnailssvc.ThumbnailServiceHandler { +func NewInstrument(next DecoratedService, metrics *metrics.Metrics) DecoratedService { return instrument{ - next: next, - metrics: metrics, + Decorator: Decorator{next: next}, + metrics: metrics, } } type instrument struct { - next thumbnailssvc.ThumbnailServiceHandler + Decorator metrics *metrics.Metrics } diff --git a/thumbnails/pkg/service/v0/logging.go b/thumbnails/pkg/service/v0/decorators/logging.go similarity index 79% rename from thumbnails/pkg/service/v0/logging.go rename to thumbnails/pkg/service/v0/decorators/logging.go index c4e8453558..8a69a392f2 100644 --- a/thumbnails/pkg/service/v0/logging.go +++ b/thumbnails/pkg/service/v0/decorators/logging.go @@ -1,4 +1,4 @@ -package svc +package decorators import ( "context" @@ -9,15 +9,15 @@ import ( ) // NewLogging returns a service that logs messages. -func NewLogging(next thumbnailssvc.ThumbnailServiceHandler, logger log.Logger) thumbnailssvc.ThumbnailServiceHandler { +func NewLogging(next DecoratedService, logger log.Logger) DecoratedService { return logging{ - next: next, - logger: logger, + Decorator: Decorator{next: next}, + logger: logger, } } type logging struct { - next thumbnailssvc.ThumbnailServiceHandler + Decorator logger log.Logger } diff --git a/thumbnails/pkg/service/v0/tracing.go b/thumbnails/pkg/service/v0/decorators/tracing.go similarity index 87% rename from thumbnails/pkg/service/v0/tracing.go rename to thumbnails/pkg/service/v0/decorators/tracing.go index fcd8cc4491..634cc348b8 100644 --- a/thumbnails/pkg/service/v0/tracing.go +++ b/thumbnails/pkg/service/v0/decorators/tracing.go @@ -1,4 +1,4 @@ -package svc +package decorators import ( "context" @@ -11,14 +11,14 @@ import ( ) // NewTracing returns a service that instruments traces. -func NewTracing(next thumbnailssvc.ThumbnailServiceHandler) thumbnailssvc.ThumbnailServiceHandler { +func NewTracing(next DecoratedService) DecoratedService { return tracing{ - next: next, + Decorator: Decorator{next: next}, } } type tracing struct { - next thumbnailssvc.ThumbnailServiceHandler + Decorator } // GetThumbnail implements the ThumbnailServiceHandler interface. diff --git a/thumbnails/pkg/service/v0/service.go b/thumbnails/pkg/service/v0/service.go index 5a99c6d7f6..eb80ef9738 100644 --- a/thumbnails/pkg/service/v0/service.go +++ b/thumbnails/pkg/service/v0/service.go @@ -14,6 +14,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/log" thumbnailssvc "github.com/owncloud/ocis/protogen/gen/ocis/services/thumbnails/v0" "github.com/owncloud/ocis/thumbnails/pkg/preprocessor" + "github.com/owncloud/ocis/thumbnails/pkg/service/v0/decorators" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail" "github.com/owncloud/ocis/thumbnails/pkg/thumbnail/imgsource" "github.com/pkg/errors" @@ -22,7 +23,7 @@ import ( ) // NewService returns a service implementation for Service. -func NewService(opts ...Option) thumbnailssvc.ThumbnailServiceHandler { +func NewService(opts ...Option) decorators.DecoratedService { options := newOptions(opts...) logger := options.Logger resolutions, err := thumbnail.ParseResolutions(options.Config.Thumbnail.Resolutions)