You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
3.4 KiB
Go
175 lines
3.4 KiB
Go
package components
|
|
|
|
import (
|
|
"context"
|
|
"sort"
|
|
|
|
"go-micro.dev/v4"
|
|
"go-micro.dev/v4/errors"
|
|
"go-micro.dev/v4/server"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
var (
|
|
errorRetrievingComponents = errors.InternalServerError("RETRIEVING_COMPONENTS", "error while retrieving components")
|
|
errorComponentsIsNil = errors.InternalServerError("COMPONENTS_NIL", "components is nil")
|
|
)
|
|
|
|
type HealthInfo struct {
|
|
Message string `json:"message"`
|
|
IsError bool `json:"is_error"`
|
|
}
|
|
|
|
type HealthInfoMap map[string]HealthInfo
|
|
|
|
type ComponentsKey struct{}
|
|
|
|
type Components struct {
|
|
components map[string]Component
|
|
|
|
service micro.Service
|
|
}
|
|
|
|
func Context(ctx context.Context) (*Components, error) {
|
|
c, ok := ctx.Value(ComponentsKey{}).(*Components)
|
|
if !ok {
|
|
return nil, errorRetrievingComponents
|
|
}
|
|
|
|
if c == nil {
|
|
return nil, errorComponentsIsNil
|
|
}
|
|
|
|
return c, nil
|
|
}
|
|
|
|
func Must(ctx context.Context) *Components {
|
|
c, err := Context(ctx)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return c
|
|
}
|
|
|
|
func New(components ...Component) *Components {
|
|
com := &Components{components: make(map[string]Component)}
|
|
|
|
com.Add(components...)
|
|
|
|
return com
|
|
}
|
|
|
|
func (c *Components) SetService(service micro.Service) {
|
|
c.service = service
|
|
}
|
|
|
|
func (c *Components) Service() micro.Service {
|
|
return c.service
|
|
}
|
|
|
|
func (c *Components) Add(components ...Component) {
|
|
for _, component := range components {
|
|
if component == nil {
|
|
continue
|
|
}
|
|
|
|
if _, ok := c.components[component.Name()]; ok {
|
|
continue
|
|
}
|
|
|
|
c.components[component.Name()] = component
|
|
}
|
|
}
|
|
|
|
func (c *Components) Get(name string) (Component, error) {
|
|
if component, ok := c.components[name]; ok {
|
|
return component, nil
|
|
}
|
|
|
|
return nil, errors.InternalServerError("COMPONENT_NOT_FOUND", "component '%s' has not been found", name)
|
|
}
|
|
|
|
func (c *Components) Must(name string) Component {
|
|
component, err := c.Get(name)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return component
|
|
}
|
|
|
|
func (c *Components) MergeFlags(flags []cli.Flag) []cli.Flag {
|
|
for _, component := range c.components {
|
|
flags = component.MergeFlags(flags)
|
|
}
|
|
|
|
return flags
|
|
}
|
|
|
|
func (c *Components) Initialized() bool {
|
|
for _, component := range c.components {
|
|
if !component.Initialized() {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func (c *Components) Init(context *cli.Context) error {
|
|
// Sort Components by Priority ASC
|
|
components := make([]Component, len(c.components))
|
|
for _, com := range c.components {
|
|
components = append(components, com)
|
|
}
|
|
sort.SliceStable(components, func(i, j int) bool {
|
|
if components[i] == nil || components[j] == nil {
|
|
return false
|
|
}
|
|
|
|
return components[i].Priority() < components[j].Priority()
|
|
})
|
|
|
|
// Init them sorted now
|
|
for _, component := range components {
|
|
if c == nil {
|
|
continue
|
|
}
|
|
|
|
if err := component.Init(c, context); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (c *Components) Health(context context.Context) HealthInfoMap {
|
|
result := make(HealthInfoMap, len(c.components))
|
|
|
|
for _, component := range c.components {
|
|
m, e := component.Health(context)
|
|
result[component.Name()] = HealthInfo{Message: m, IsError: e}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (c *Components) Wrapper() server.HandlerWrapper {
|
|
return func(h server.HandlerFunc) server.HandlerFunc {
|
|
return func(ctx context.Context, req server.Request, rsp interface{}) error {
|
|
ctx = context.WithValue(ctx, ComponentsKey{}, c)
|
|
|
|
for _, component := range c.components {
|
|
if err := component.WrapperFunc(ctx, req, rsp); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return h(ctx, req, rsp)
|
|
}
|
|
}
|
|
}
|