Compare commits

...

4 Commits

Author SHA1 Message Date
2a548634fd config: add Save/Load options
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-06-20 23:57:13 +03:00
598dddc476 util/reflect: fix time.Time StructFields parsing
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-06-19 15:58:36 +03:00
887b48f1e7 util/reflect: improve StructFields func
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-06-17 12:53:23 +03:00
6e55d07636 client: allow to publish body only
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
2021-06-13 12:20:35 +03:00
5 changed files with 87 additions and 16 deletions

View File

@@ -221,5 +221,8 @@ func (n *noopClient) Publish(ctx context.Context, p Message, opts ...PublishOpti
return n.opts.Broker.Publish(ctx, topic, &broker.Message{
Header: md,
Body: body,
}, broker.PublishContext(options.Context))
},
broker.PublishContext(options.Context),
broker.PublishBodyOnly(options.BodyOnly),
)
}

View File

@@ -20,25 +20,27 @@ var (
// Config is an interface abstraction for dynamic configuration
type Config interface {
// Name returns name of config
Name() string
// Init the config
Init(opts ...Option) error
// Options in the config
Options() Options
// Load config from sources
Load(context.Context) error
Load(context.Context, ...LoadOption) error
// Save config to sources
Save(context.Context) error
Save(context.Context, ...SaveOption) error
// Watch a value for changes
// Watch(interface{}) (Watcher, error)
//Watch(context.Context) (Watcher, error)
// String returns config type name
String() string
}
// Watcher is the config watcher
// type Watcher interface {
// Next() (, error)
// Stop() error
// }
type Watcher interface {
// Next() (, error)
Stop() error
}
// Load loads config from config sources
func Load(ctx context.Context, cs ...Config) error {

View File

@@ -25,18 +25,27 @@ func (c *defaultConfig) Init(opts ...Option) error {
return nil
}
func (c *defaultConfig) Load(ctx context.Context) error {
func (c *defaultConfig) Load(ctx context.Context, opts ...LoadOption) error {
for _, fn := range c.opts.BeforeLoad {
if err := fn(ctx, c); err != nil && !c.opts.AllowFail {
return err
}
}
options := NewLoadOptions(opts...)
mopts := []func(*mergo.Config){mergo.WithTypeCheck}
if options.Override {
mopts = append(mopts, mergo.WithOverride)
}
if options.Append {
mopts = append(mopts, mergo.WithAppendSlice)
}
src, err := rutil.Zero(c.opts.Struct)
if err == nil {
valueOf := reflect.ValueOf(src)
if err = c.fillValues(valueOf); err == nil {
err = mergo.Merge(c.opts.Struct, src, mergo.WithOverride, mergo.WithTypeCheck, mergo.WithAppendSlice)
err = mergo.Merge(c.opts.Struct, src, mopts...)
}
}
@@ -232,7 +241,7 @@ func (c *defaultConfig) fillValues(valueOf reflect.Value) error {
return nil
}
func (c *defaultConfig) Save(ctx context.Context) error {
func (c *defaultConfig) Save(ctx context.Context, opts ...SaveOption) error {
for _, fn := range c.opts.BeforeSave {
if err := fn(ctx, c); err != nil && !c.opts.AllowFail {
return err

View File

@@ -57,6 +57,52 @@ func NewOptions(opts ...Option) Options {
return options
}
// LoadOption function signature
type LoadOption func(o *LoadOptions)
// LoadOptions struct
type LoadOptions struct {
Override bool
Append bool
}
func NewLoadOptions(opts ...LoadOption) LoadOptions {
options := LoadOptions{}
for _, o := range opts {
o(&options)
}
return options
}
// LoadOverride override values when load
func LoadOverride(b bool) LoadOption {
return func(o *LoadOptions) {
o.Override = b
}
}
// LoadAppend override values when load
func LoadAppend(b bool) LoadOption {
return func(o *LoadOptions) {
o.Append = b
}
}
// SaveOption function signature
type SaveOption func(o *SaveOptions)
// SaveOptions struct
type SaveOptions struct {
}
func NewSaveOptions(opts ...SaveOption) SaveOptions {
options := SaveOptions{}
for _, o := range opts {
o(&options)
}
return options
}
// AllowFail allows config source to fail
func AllowFail(b bool) Option {
return func(o *Options) {

View File

@@ -7,6 +7,7 @@ import (
"reflect"
"regexp"
"strings"
"time"
)
// ErrInvalidParam specifies invalid url query params
@@ -14,6 +15,13 @@ var ErrInvalidParam = errors.New("invalid url query param provided")
var bracketSplitter = regexp.MustCompile(`\[|\]`)
var timeKind = reflect.TypeOf(time.Time{}).Kind()
type StructField struct {
Field reflect.StructField
Value reflect.Value
}
func StructFieldByTag(src interface{}, tkey string, tval string) (interface{}, error) {
sv := reflect.ValueOf(src)
if sv.Kind() == reflect.Ptr {
@@ -98,8 +106,8 @@ func StructFieldByName(src interface{}, tkey string) (interface{}, error) {
}
// StructFields returns slice of struct fields
func StructFields(src interface{}) ([]reflect.StructField, error) {
var fields []reflect.StructField
func StructFields(src interface{}) ([]StructField, error) {
var fields []StructField
sv := reflect.ValueOf(src)
if sv.Kind() == reflect.Ptr {
@@ -116,14 +124,17 @@ func StructFields(src interface{}) ([]reflect.StructField, error) {
if !val.CanSet() || len(fld.PkgPath) != 0 {
continue
}
if val.Kind() == reflect.Struct {
switch val.Kind() {
case timeKind:
fields = append(fields, StructField{Field: fld, Value: val})
case reflect.Struct:
infields, err := StructFields(val.Interface())
if err != nil {
return nil, err
}
fields = append(fields, infields...)
} else {
fields = append(fields, fld)
default:
fields = append(fields, StructField{Field: fld, Value: val})
}
}