src

Go monorepo.
git clone git://code.dwrz.net/src
Log | Files | Refs

step_build.go (6107B)


      1 package middleware
      2 
      3 import (
      4 	"context"
      5 )
      6 
      7 // BuildInput provides the input parameters for the BuildMiddleware to consume.
      8 // BuildMiddleware may modify the Request value before forwarding the input
      9 // along to the next BuildHandler.
     10 type BuildInput struct {
     11 	Request interface{}
     12 }
     13 
     14 // BuildOutput provides the result returned by the next BuildHandler.
     15 type BuildOutput struct {
     16 	Result interface{}
     17 }
     18 
     19 // BuildHandler provides the interface for the next handler the
     20 // BuildMiddleware will call in the middleware chain.
     21 type BuildHandler interface {
     22 	HandleBuild(ctx context.Context, in BuildInput) (
     23 		out BuildOutput, metadata Metadata, err error,
     24 	)
     25 }
     26 
     27 // BuildMiddleware provides the interface for middleware specific to the
     28 // serialize step. Delegates to the next BuildHandler for further
     29 // processing.
     30 type BuildMiddleware interface {
     31 	// Unique ID for the middleware in theBuildStep. The step does not allow
     32 	// duplicate IDs.
     33 	ID() string
     34 
     35 	// Invokes the middleware behavior which must delegate to the next handler
     36 	// for the middleware chain to continue. The method must return a result or
     37 	// error to its caller.
     38 	HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
     39 		out BuildOutput, metadata Metadata, err error,
     40 	)
     41 }
     42 
     43 // BuildMiddlewareFunc returns a BuildMiddleware with the unique ID provided,
     44 // and the func to be invoked.
     45 func BuildMiddlewareFunc(id string, fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)) BuildMiddleware {
     46 	return buildMiddlewareFunc{
     47 		id: id,
     48 		fn: fn,
     49 	}
     50 }
     51 
     52 type buildMiddlewareFunc struct {
     53 	// Unique ID for the middleware.
     54 	id string
     55 
     56 	// Middleware function to be called.
     57 	fn func(context.Context, BuildInput, BuildHandler) (BuildOutput, Metadata, error)
     58 }
     59 
     60 // ID returns the unique ID for the middleware.
     61 func (s buildMiddlewareFunc) ID() string { return s.id }
     62 
     63 // HandleBuild invokes the middleware Fn.
     64 func (s buildMiddlewareFunc) HandleBuild(ctx context.Context, in BuildInput, next BuildHandler) (
     65 	out BuildOutput, metadata Metadata, err error,
     66 ) {
     67 	return s.fn(ctx, in, next)
     68 }
     69 
     70 var _ BuildMiddleware = (buildMiddlewareFunc{})
     71 
     72 // BuildStep provides the ordered grouping of BuildMiddleware to be invoked on
     73 // a handler.
     74 type BuildStep struct {
     75 	ids *orderedIDs
     76 }
     77 
     78 // NewBuildStep returns a BuildStep ready to have middleware for
     79 // initialization added to it.
     80 func NewBuildStep() *BuildStep {
     81 	return &BuildStep{
     82 		ids: newOrderedIDs(),
     83 	}
     84 }
     85 
     86 var _ Middleware = (*BuildStep)(nil)
     87 
     88 // ID returns the unique name of the step as a middleware.
     89 func (s *BuildStep) ID() string {
     90 	return "Build stack step"
     91 }
     92 
     93 // HandleMiddleware invokes the middleware by decorating the next handler
     94 // provided. Returns the result of the middleware and handler being invoked.
     95 //
     96 // Implements Middleware interface.
     97 func (s *BuildStep) HandleMiddleware(ctx context.Context, in interface{}, next Handler) (
     98 	out interface{}, metadata Metadata, err error,
     99 ) {
    100 	order := s.ids.GetOrder()
    101 
    102 	var h BuildHandler = buildWrapHandler{Next: next}
    103 	for i := len(order) - 1; i >= 0; i-- {
    104 		h = decoratedBuildHandler{
    105 			Next: h,
    106 			With: order[i].(BuildMiddleware),
    107 		}
    108 	}
    109 
    110 	sIn := BuildInput{
    111 		Request: in,
    112 	}
    113 
    114 	res, metadata, err := h.HandleBuild(ctx, sIn)
    115 	return res.Result, metadata, err
    116 }
    117 
    118 // Get retrieves the middleware identified by id. If the middleware is not present, returns false.
    119 func (s *BuildStep) Get(id string) (BuildMiddleware, bool) {
    120 	get, ok := s.ids.Get(id)
    121 	if !ok {
    122 		return nil, false
    123 	}
    124 	return get.(BuildMiddleware), ok
    125 }
    126 
    127 // Add injects the middleware to the relative position of the middleware group.
    128 // Returns an error if the middleware already exists.
    129 func (s *BuildStep) Add(m BuildMiddleware, pos RelativePosition) error {
    130 	return s.ids.Add(m, pos)
    131 }
    132 
    133 // Insert injects the middleware relative to an existing middleware id.
    134 // Returns an error if the original middleware does not exist, or the middleware
    135 // being added already exists.
    136 func (s *BuildStep) Insert(m BuildMiddleware, relativeTo string, pos RelativePosition) error {
    137 	return s.ids.Insert(m, relativeTo, pos)
    138 }
    139 
    140 // Swap removes the middleware by id, replacing it with the new middleware.
    141 // Returns the middleware removed, or an error if the middleware to be removed
    142 // doesn't exist.
    143 func (s *BuildStep) Swap(id string, m BuildMiddleware) (BuildMiddleware, error) {
    144 	removed, err := s.ids.Swap(id, m)
    145 	if err != nil {
    146 		return nil, err
    147 	}
    148 
    149 	return removed.(BuildMiddleware), nil
    150 }
    151 
    152 // Remove removes the middleware by id. Returns error if the middleware
    153 // doesn't exist.
    154 func (s *BuildStep) Remove(id string) (BuildMiddleware, error) {
    155 	removed, err := s.ids.Remove(id)
    156 	if err != nil {
    157 		return nil, err
    158 	}
    159 
    160 	return removed.(BuildMiddleware), nil
    161 }
    162 
    163 // List returns a list of the middleware in the step.
    164 func (s *BuildStep) List() []string {
    165 	return s.ids.List()
    166 }
    167 
    168 // Clear removes all middleware in the step.
    169 func (s *BuildStep) Clear() {
    170 	s.ids.Clear()
    171 }
    172 
    173 type buildWrapHandler struct {
    174 	Next Handler
    175 }
    176 
    177 var _ BuildHandler = (*buildWrapHandler)(nil)
    178 
    179 // Implements BuildHandler, converts types and delegates to underlying
    180 // generic handler.
    181 func (w buildWrapHandler) HandleBuild(ctx context.Context, in BuildInput) (
    182 	out BuildOutput, metadata Metadata, err error,
    183 ) {
    184 	res, metadata, err := w.Next.Handle(ctx, in.Request)
    185 	return BuildOutput{
    186 		Result: res,
    187 	}, metadata, err
    188 }
    189 
    190 type decoratedBuildHandler struct {
    191 	Next BuildHandler
    192 	With BuildMiddleware
    193 }
    194 
    195 var _ BuildHandler = (*decoratedBuildHandler)(nil)
    196 
    197 func (h decoratedBuildHandler) HandleBuild(ctx context.Context, in BuildInput) (
    198 	out BuildOutput, metadata Metadata, err error,
    199 ) {
    200 	return h.With.HandleBuild(ctx, in, h.Next)
    201 }
    202 
    203 // BuildHandlerFunc provides a wrapper around a function to be used as a build middleware handler.
    204 type BuildHandlerFunc func(context.Context, BuildInput) (BuildOutput, Metadata, error)
    205 
    206 // HandleBuild invokes the wrapped function with the provided arguments.
    207 func (b BuildHandlerFunc) HandleBuild(ctx context.Context, in BuildInput) (BuildOutput, Metadata, error) {
    208 	return b(ctx, in)
    209 }
    210 
    211 var _ BuildHandler = BuildHandlerFunc(nil)