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.
components/components.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)
}
}
}