From d1952cc7a5d858d9d771b86cca132342fee3b8a4 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Mon, 15 Jan 2024 01:25:46 +0800 Subject: [PATCH 01/15] feat: support customize format parsing for config file --- monitor/monitor.go | 15 +++++++++++++- monitor/monitor_test.go | 9 +++++++++ parser/parser.go | 44 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 4 deletions(-) diff --git a/monitor/monitor.go b/monitor/monitor.go index d8be4ff..cc41f81 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -32,11 +32,14 @@ type ConfigMonitor interface { WatcherID() int64 Stop() SetManager(manager parser.ConfigManager) + SetParser(parser parser.ConfigParser) RegisterCallback(callback func()) int64 DeregisterCallback(uniqueID int64) } type configMonitor struct { + // support customise parser + parser parser.ConfigParser // Parser for the config file manager parser.ConfigManager // Manager for the config file config interface{} // config details fileWatcher filewatcher.FileWatcher // local config file watcher @@ -60,6 +63,7 @@ func NewConfigMonitor(key string, watcher filewatcher.FileWatcher) (ConfigMonito fileWatcher: watcher, key: key, callbacks: make(map[int64]func(), 0), + parser: parser.DefaultConfigParse(), }, nil } @@ -103,6 +107,11 @@ func (c *configMonitor) Stop() { // SetManager set the manager for the config file func (c *configMonitor) SetManager(manager parser.ConfigManager) { c.manager = manager } +// SetParser set the parser for the config file +func (c *configMonitor) SetParser(parser parser.ConfigParser) { + c.parser = parser +} + // RegisterCallback add callback function, it will be called when file changed, return key for deregister func (c *configMonitor) RegisterCallback(callback func()) int64 { c.lock.Lock() @@ -134,7 +143,11 @@ func (c *configMonitor) DeregisterCallback(key int64) { // parseHandler parse and invoke each function in the callbacks array func (c *configMonitor) parseHandler(data []byte) { resp := c.manager - err := parser.Decode(data, resp) + + param := &parser.ConfigParam{ + Type: parser.JSON, + } + err := c.parser.Decode(param.Type, data, resp) if err != nil { klog.Errorf("[local] failed to parse the config file: %v\n", err) return diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index be09f7a..f327b0f 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -63,6 +63,15 @@ func TestSetManager(t *testing.T) { cm.SetManager(&parser.ServerFileManager{}) } +func TestSetParser(t *testing.T) { + m := mock.NewMockFileWatcher() + cm, err := NewConfigMonitor("test", m) + if err != nil { + t.Errorf("NewConfigMonitor() error = %v", err) + } + cm.SetParser(&parser.Parser{}) +} + func TestRegisterCallback(t *testing.T) { m := mock.NewMockFileWatcher() cm, err := NewConfigMonitor("test", m) diff --git a/parser/parser.go b/parser/parser.go index 3da8617..5b0b1c0 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -15,14 +15,52 @@ package parser import ( + "fmt" + + "github.com/bytedance/sonic" "sigs.k8s.io/yaml" ) +type ConfigParam struct { + Type ConfigType +} + +// CustomFunction use for customize the config parameters. +type ( + ConfigType string + ConfigFunction func(*ConfigParam) +) + +const ( + JSON ConfigType = "json" + YAML ConfigType = "yaml" +) + +// ConfigParser the parser for config file. +type ConfigParser interface { + Decode(kind ConfigType, data []byte, config interface{}) error +} + +type Parser struct{} + type ConfigManager interface { GetConfig(key string) interface{} } -// Decode parse the config file -func Decode(data []byte, resp interface{}) error { - return yaml.Unmarshal(data, resp) +var _ ConfigParser = &Parser{} + +// Decode decodes the data to struct in specified format. +func (p *Parser) Decode(kind ConfigType, data []byte, config interface{}) error { + switch kind { + case JSON: + return sonic.Unmarshal(data, config) + case YAML: + return yaml.Unmarshal(data, config) + default: + return fmt.Errorf("user customize config data type %s", kind) + } +} + +func DefaultConfigParse() ConfigParser { + return &Parser{} } From ff3ae91e7d830c1de90cdb3ea813b98def3fe5b1 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Mon, 15 Jan 2024 15:54:02 +0800 Subject: [PATCH 02/15] fix: modify Options function --- client/suite.go | 2 ++ monitor/monitor.go | 7 +++++++ monitor/monitor_test.go | 9 +++++++++ server/suite.go | 2 ++ 4 files changed, 20 insertions(+) diff --git a/client/suite.go b/client/suite.go index 8e9a6e5..b0dd778 100644 --- a/client/suite.go +++ b/client/suite.go @@ -19,6 +19,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/monitor" "github.com/kitex-contrib/config-file/parser" + ) type FileConfigClientSuite struct { @@ -42,6 +43,7 @@ func NewSuite(service, key string, watcher filewatcher.FileWatcher) *FileConfigC // Options return a list client.Option func (s *FileConfigClientSuite) Options() []kitexclient.Option { s.watcher.SetManager(&parser.ClientFileManager{}) + s.watcher.SetParser(&parser.Parser{}) opts := make([]kitexclient.Option, 0, 7) opts = append(opts, WithRetryPolicy(s.watcher)...) diff --git a/monitor/monitor.go b/monitor/monitor.go index cc41f81..4792ec7 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -22,6 +22,7 @@ import ( "github.com/cloudwego/kitex/pkg/klog" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" + ) type ConfigMonitor interface { @@ -33,6 +34,7 @@ type ConfigMonitor interface { Stop() SetManager(manager parser.ConfigManager) SetParser(parser parser.ConfigParser) + ConfigParse(kind parser.ConfigType, data []byte, config interface{}) error RegisterCallback(callback func()) int64 DeregisterCallback(uniqueID int64) } @@ -112,6 +114,11 @@ func (c *configMonitor) SetParser(parser parser.ConfigParser) { c.parser = parser } +// ConfigParse call configMonitor.parser.Decode() +func (c *configMonitor) ConfigParse(kind parser.ConfigType, data []byte, config interface{}) error { + return c.parser.Decode(kind, data, config) +} + // RegisterCallback add callback function, it will be called when file changed, return key for deregister func (c *configMonitor) RegisterCallback(callback func()) int64 { c.lock.Lock() diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index f327b0f..62f9b1a 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -70,6 +70,15 @@ func TestSetParser(t *testing.T) { t.Errorf("NewConfigMonitor() error = %v", err) } cm.SetParser(&parser.Parser{}) + + // use json format test ConfigParse + kind := parser.JSON + jsonData := []byte(`{"key": "value"}`) + var config struct{} + err = cm.ConfigParse(kind, jsonData, &config) + if err != nil { + t.Errorf("ConfigParse() error = %v", err) + } } func TestRegisterCallback(t *testing.T) { diff --git a/server/suite.go b/server/suite.go index 8cc02e9..3f542a0 100644 --- a/server/suite.go +++ b/server/suite.go @@ -19,6 +19,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/monitor" "github.com/kitex-contrib/config-file/parser" + ) type FileConfigServerSuite struct { @@ -40,6 +41,7 @@ func NewSuite(key string, watcher filewatcher.FileWatcher) *FileConfigServerSuit // Options return a list client.Option func (s *FileConfigServerSuite) Options() []kitexserver.Option { s.watcher.SetManager(&parser.ServerFileManager{}) + s.watcher.SetParser(&parser.Parser{}) opts := make([]kitexserver.Option, 0, 1) opts = append(opts, WithLimiter(s.watcher)) From 7611f924275bd6fbafc5edb4097e9d1b2c42c5a4 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 16 Jan 2024 01:49:42 +0800 Subject: [PATCH 03/15] fix: modify NewSuite() function --- client/suite.go | 13 ++++++++++--- example/client/main.go | 8 +++++++- example/server/main.go | 9 ++++++++- parser/parser.go | 4 ++-- server/suite.go | 12 ++++++++++-- 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/client/suite.go b/client/suite.go index b0dd778..c0291e5 100644 --- a/client/suite.go +++ b/client/suite.go @@ -19,31 +19,38 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/monitor" "github.com/kitex-contrib/config-file/parser" - ) type FileConfigClientSuite struct { watcher monitor.ConfigMonitor service string + fns []parser.CustomFunction } // NewSuite service is the destination service. -func NewSuite(service, key string, watcher filewatcher.FileWatcher) *FileConfigClientSuite { +func NewSuite(service, key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser, cfs ...parser.CustomFunction) *FileConfigClientSuite { cm, err := monitor.NewConfigMonitor(key, watcher) if err != nil { panic(err) } + if cp == nil { + cm.SetParser(parser.DefaultConfigParse()) + } else { + // use customized parser + cm.SetParser(cp) + } + return &FileConfigClientSuite{ watcher: cm, service: service, + fns: cfs, } } // Options return a list client.Option func (s *FileConfigClientSuite) Options() []kitexclient.Option { s.watcher.SetManager(&parser.ClientFileManager{}) - s.watcher.SetParser(&parser.Parser{}) opts := make([]kitexclient.Option, 0, 7) opts = append(opts, WithRetryPolicy(s.watcher)...) diff --git a/example/client/main.go b/example/client/main.go index e37a58a..a607195 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -27,6 +27,7 @@ import ( "github.com/cloudwego/kitex/pkg/klog" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" ) const ( @@ -57,10 +58,15 @@ func main() { os.Exit(1) }() + // customize configParam by customFunction + fn := func(cp *parser.ConfigParam) { + klog.Infof("file config %v", cp) + } + client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, nil, fn)), ) if err != nil { log.Fatal(err) diff --git a/example/server/main.go b/example/server/main.go index e2fed4a..e57205e 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -24,7 +24,9 @@ import ( "github.com/cloudwego/kitex/pkg/rpcinfo" kitexserver "github.com/cloudwego/kitex/server" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" + ) var _ api.Echo = &EchoImpl{} @@ -58,10 +60,15 @@ func main() { } defer fw.StopWatching() + // customize configParam by customFunction + fn := func(cp *parser.ConfigParam) { + klog.Infof("file config %v", cp) + } + svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw, nil,fn)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) diff --git a/parser/parser.go b/parser/parser.go index 5b0b1c0..31c110f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -28,7 +28,7 @@ type ConfigParam struct { // CustomFunction use for customize the config parameters. type ( ConfigType string - ConfigFunction func(*ConfigParam) + CustomFunction func(*ConfigParam) ) const ( @@ -57,7 +57,7 @@ func (p *Parser) Decode(kind ConfigType, data []byte, config interface{}) error case YAML: return yaml.Unmarshal(data, config) default: - return fmt.Errorf("user customize config data type %s", kind) + return fmt.Errorf("unsupported config data type %s", kind) } } diff --git a/server/suite.go b/server/suite.go index 3f542a0..0ed3323 100644 --- a/server/suite.go +++ b/server/suite.go @@ -24,24 +24,32 @@ import ( type FileConfigServerSuite struct { watcher monitor.ConfigMonitor + fns []parser.CustomFunction } // NewSuite service is the destination service. -func NewSuite(key string, watcher filewatcher.FileWatcher) *FileConfigServerSuite { +func NewSuite(key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser, cfs ...parser.CustomFunction) *FileConfigServerSuite { cm, err := monitor.NewConfigMonitor(key, watcher) if err != nil { panic(err) } + if cp == nil { + cm.SetParser(parser.DefaultConfigParse()) + } else { + // use customized parser + cm.SetParser(cp) + } + return &FileConfigServerSuite{ watcher: cm, + fns: cfs, } } // Options return a list client.Option func (s *FileConfigServerSuite) Options() []kitexserver.Option { s.watcher.SetManager(&parser.ServerFileManager{}) - s.watcher.SetParser(&parser.Parser{}) opts := make([]kitexserver.Option, 0, 1) opts = append(opts, WithLimiter(s.watcher)) From b9b21050d6a4e2e64d1018f66d0d8e9f1fa1e525 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 16 Jan 2024 15:14:49 +0800 Subject: [PATCH 04/15] chore: delete useless CustomFunction Type --- client/suite.go | 4 +--- example/client/main.go | 9 ++------- example/server/main.go | 8 +------- go.mod | 2 +- monitor/monitor.go | 1 - parser/parser.go | 4 +--- server/suite.go | 5 +---- 7 files changed, 7 insertions(+), 26 deletions(-) diff --git a/client/suite.go b/client/suite.go index c0291e5..3972e7e 100644 --- a/client/suite.go +++ b/client/suite.go @@ -24,11 +24,10 @@ import ( type FileConfigClientSuite struct { watcher monitor.ConfigMonitor service string - fns []parser.CustomFunction } // NewSuite service is the destination service. -func NewSuite(service, key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser, cfs ...parser.CustomFunction) *FileConfigClientSuite { +func NewSuite(service, key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser) *FileConfigClientSuite { cm, err := monitor.NewConfigMonitor(key, watcher) if err != nil { panic(err) @@ -44,7 +43,6 @@ func NewSuite(service, key string, watcher filewatcher.FileWatcher, cp parser.Co return &FileConfigClientSuite{ watcher: cm, service: service, - fns: cfs, } } diff --git a/example/client/main.go b/example/client/main.go index a607195..420bdf1 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -27,7 +27,7 @@ import ( "github.com/cloudwego/kitex/pkg/klog" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" - "github.com/kitex-contrib/config-file/parser" + ) const ( @@ -58,15 +58,10 @@ func main() { os.Exit(1) }() - // customize configParam by customFunction - fn := func(cp *parser.ConfigParam) { - klog.Infof("file config %v", cp) - } - client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, nil, fn)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, nil)), ) if err != nil { log.Fatal(err) diff --git a/example/server/main.go b/example/server/main.go index e57205e..6e43d83 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -24,7 +24,6 @@ import ( "github.com/cloudwego/kitex/pkg/rpcinfo" kitexserver "github.com/cloudwego/kitex/server" "github.com/kitex-contrib/config-file/filewatcher" - "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" ) @@ -60,15 +59,10 @@ func main() { } defer fw.StopWatching() - // customize configParam by customFunction - fn := func(cp *parser.ConfigParam) { - klog.Infof("file config %v", cp) - } - svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw, nil,fn)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw, nil)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) diff --git a/go.mod b/go.mod index ce5c603..1c1b2b7 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/kitex-contrib/config-file go 1.19 require ( + github.com/bytedance/sonic v1.10.2 github.com/cloudwego/kitex v0.8.0 github.com/fsnotify/fsnotify v1.7.0 github.com/stretchr/testify v1.8.4 @@ -12,7 +13,6 @@ require ( require ( github.com/apache/thrift v0.13.0 // indirect github.com/bytedance/gopkg v0.0.0-20230728082804-614d0af6619b // indirect - github.com/bytedance/sonic v1.10.2 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect github.com/choleraehyq/pid v0.0.17 // indirect diff --git a/monitor/monitor.go b/monitor/monitor.go index 4792ec7..67e7c60 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -22,7 +22,6 @@ import ( "github.com/cloudwego/kitex/pkg/klog" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" - ) type ConfigMonitor interface { diff --git a/parser/parser.go b/parser/parser.go index 31c110f..5c56bac 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -25,10 +25,8 @@ type ConfigParam struct { Type ConfigType } -// CustomFunction use for customize the config parameters. type ( - ConfigType string - CustomFunction func(*ConfigParam) + ConfigType string ) const ( diff --git a/server/suite.go b/server/suite.go index 0ed3323..164d9d2 100644 --- a/server/suite.go +++ b/server/suite.go @@ -19,16 +19,14 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/monitor" "github.com/kitex-contrib/config-file/parser" - ) type FileConfigServerSuite struct { watcher monitor.ConfigMonitor - fns []parser.CustomFunction } // NewSuite service is the destination service. -func NewSuite(key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser, cfs ...parser.CustomFunction) *FileConfigServerSuite { +func NewSuite(key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser) *FileConfigServerSuite { cm, err := monitor.NewConfigMonitor(key, watcher) if err != nil { panic(err) @@ -43,7 +41,6 @@ func NewSuite(key string, watcher filewatcher.FileWatcher, cp parser.ConfigParse return &FileConfigServerSuite{ watcher: cm, - fns: cfs, } } From 87c5fbe20870863e330b4573c34501d04691e7af Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Thu, 18 Jan 2024 18:07:50 +0800 Subject: [PATCH 05/15] feat: options for user custom --- client/suite.go | 15 +++++++++------ example/client/main.go | 16 ++++++++++++++-- example/go.mod | 1 + example/go.sum | 2 ++ example/server/main.go | 23 ++++++++++++++++++----- go.sum | 2 ++ monitor/monitor.go | 16 +++++++++++----- monitor/monitor_test.go | 10 ++++++++++ parser/parser.go | 12 ++++++++---- parser/server.go | 2 +- server/suite.go | 14 ++++++++------ utils/utils.go | 7 +++++++ 12 files changed, 91 insertions(+), 29 deletions(-) diff --git a/client/suite.go b/client/suite.go index 3972e7e..dfc2fac 100644 --- a/client/suite.go +++ b/client/suite.go @@ -19,6 +19,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/monitor" "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) type FileConfigClientSuite struct { @@ -27,17 +28,19 @@ type FileConfigClientSuite struct { } // NewSuite service is the destination service. -func NewSuite(service, key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser) *FileConfigClientSuite { +func NewSuite(service, key string, watcher filewatcher.FileWatcher, opts *utils.Options) *FileConfigClientSuite { cm, err := monitor.NewConfigMonitor(key, watcher) if err != nil { panic(err) } - if cp == nil { - cm.SetParser(parser.DefaultConfigParse()) - } else { - // use customized parser - cm.SetParser(cp) + // use custom parser + if opts.CustomParser != nil { + cm.SetParser(opts.CustomParser) + } + + if opts.CustomParams != nil { + cm.SetParams(opts.CustomParams) } return &FileConfigClientSuite{ diff --git a/example/client/main.go b/example/client/main.go index 420bdf1..e360160 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -16,6 +16,7 @@ package main import ( "context" + "fmt" "log" "os" "os/signal" @@ -27,7 +28,8 @@ import ( "github.com/cloudwego/kitex/pkg/klog" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" - + "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) const ( @@ -37,6 +39,13 @@ const ( clientName = "echo" ) +// Customed by user +type MyParser struct{} + +func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { + return fmt.Errorf("my custom parser: %s parser", kind) +} + func main() { klog.SetLevel(klog.LevelDebug) @@ -58,10 +67,13 @@ func main() { os.Exit(1) }() + // customed by user + opts := &utils.Options{} + client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, nil)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, opts)), ) if err != nil { log.Fatal(err) diff --git a/example/go.mod b/example/go.mod index bd478ce..a076f32 100644 --- a/example/go.mod +++ b/example/go.mod @@ -6,6 +6,7 @@ require ( github.com/cloudwego/kitex v0.8.0 github.com/cloudwego/kitex-examples v0.2.3 github.com/kitex-contrib/config-file v1.0.0 + gopkg.in/ini.v1 v1.67.0 ) replace github.com/kitex-contrib/config-file => ../. diff --git a/example/go.sum b/example/go.sum index c60e95e..8fc58fb 100644 --- a/example/go.sum +++ b/example/go.sum @@ -2116,6 +2116,8 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/example/server/main.go b/example/server/main.go index 6e43d83..f96741e 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -16,6 +16,7 @@ package main import ( "context" + "fmt" "log" "github.com/cloudwego/kitex-examples/kitex_gen/api" @@ -24,16 +25,18 @@ import ( "github.com/cloudwego/kitex/pkg/rpcinfo" kitexserver "github.com/cloudwego/kitex/server" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" - + "github.com/kitex-contrib/config-file/utils" ) var _ api.Echo = &EchoImpl{} const ( - filepath = "kitex_server.json" - key = "ServiceName" - serviceName = "ServiceName" + filepath = "kitex_server.json" + key = "ServiceName" + serviceName = "ServiceName" + INI parser.ConfigType = "ini" ) // EchoImpl implements the last service interface defined in the IDL. @@ -45,6 +48,13 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon return &api.Response{Message: req.Message}, nil } +// Customed by user +type MyParser struct{} + +func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { + return fmt.Errorf("my custom parser: %s parser", kind) +} + func main() { klog.SetLevel(klog.LevelDebug) @@ -59,10 +69,13 @@ func main() { } defer fw.StopWatching() + // customed by user + opts := &utils.Options{} + svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw, nil)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw, opts)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) diff --git a/go.sum b/go.sum index 34f1ae8..24a6d05 100644 --- a/go.sum +++ b/go.sum @@ -398,6 +398,8 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/monitor/monitor.go b/monitor/monitor.go index 67e7c60..09df905 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -33,6 +33,7 @@ type ConfigMonitor interface { Stop() SetManager(manager parser.ConfigManager) SetParser(parser parser.ConfigParser) + SetParams(params *parser.ConfigParam) ConfigParse(kind parser.ConfigType, data []byte, config interface{}) error RegisterCallback(callback func()) int64 DeregisterCallback(uniqueID int64) @@ -41,6 +42,7 @@ type ConfigMonitor interface { type configMonitor struct { // support customise parser parser parser.ConfigParser // Parser for the config file + params *parser.ConfigParam // params for the config file manager parser.ConfigManager // Manager for the config file config interface{} // config details fileWatcher filewatcher.FileWatcher // local config file watcher @@ -64,7 +66,8 @@ func NewConfigMonitor(key string, watcher filewatcher.FileWatcher) (ConfigMonito fileWatcher: watcher, key: key, callbacks: make(map[int64]func(), 0), - parser: parser.DefaultConfigParse(), + parser: parser.DefaultConfigParser(), + params: parser.DefaultConfigParam(), }, nil } @@ -113,6 +116,11 @@ func (c *configMonitor) SetParser(parser parser.ConfigParser) { c.parser = parser } +// SetParams set the params for the config file, such as file type +func (c *configMonitor) SetParams(params *parser.ConfigParam) { + c.params = params +} + // ConfigParse call configMonitor.parser.Decode() func (c *configMonitor) ConfigParse(kind parser.ConfigType, data []byte, config interface{}) error { return c.parser.Decode(kind, data, config) @@ -150,10 +158,8 @@ func (c *configMonitor) DeregisterCallback(key int64) { func (c *configMonitor) parseHandler(data []byte) { resp := c.manager - param := &parser.ConfigParam{ - Type: parser.JSON, - } - err := c.parser.Decode(param.Type, data, resp) + kind := c.params + err := c.parser.Decode(kind.Type, data, resp) if err != nil { klog.Errorf("[local] failed to parse the config file: %v\n", err) return diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index 62f9b1a..9105b9d 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -81,6 +81,16 @@ func TestSetParser(t *testing.T) { } } +func TestSetParams(t *testing.T) { + m := mock.NewMockFileWatcher() + cm, err := NewConfigMonitor("test", m) + if err != nil { + t.Errorf("NewConfigMonitor() error = %v", err) + } + + cm.SetParams(&parser.ConfigParam{}) +} + func TestRegisterCallback(t *testing.T) { m := mock.NewMockFileWatcher() cm, err := NewConfigMonitor("test", m) diff --git a/parser/parser.go b/parser/parser.go index 5c56bac..305dae0 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -25,9 +25,7 @@ type ConfigParam struct { Type ConfigType } -type ( - ConfigType string -) +type ConfigType string const ( JSON ConfigType = "json" @@ -59,6 +57,12 @@ func (p *Parser) Decode(kind ConfigType, data []byte, config interface{}) error } } -func DefaultConfigParse() ConfigParser { +func DefaultConfigParser() ConfigParser { return &Parser{} } + +func DefaultConfigParam() *ConfigParam { + return &ConfigParam{ + Type: JSON, + } +} diff --git a/parser/server.go b/parser/server.go index b4aabf7..ea6350c 100644 --- a/parser/server.go +++ b/parser/server.go @@ -18,7 +18,7 @@ import "github.com/cloudwego/kitex/pkg/limiter" // ServerFileConfig is config of a service type ServerFileConfig struct { - Limit limiter.LimiterConfig `mapstructure:"limit"` + Limit limiter.LimiterConfig `mapstructure:"limit" ini:"limit"` } // ServerFileManager is a map of service names to ServerFileConfig diff --git a/server/suite.go b/server/suite.go index 164d9d2..e4574ed 100644 --- a/server/suite.go +++ b/server/suite.go @@ -19,6 +19,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/monitor" "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) type FileConfigServerSuite struct { @@ -26,17 +27,18 @@ type FileConfigServerSuite struct { } // NewSuite service is the destination service. -func NewSuite(key string, watcher filewatcher.FileWatcher, cp parser.ConfigParser) *FileConfigServerSuite { +func NewSuite(key string, watcher filewatcher.FileWatcher, opts *utils.Options) *FileConfigServerSuite { cm, err := monitor.NewConfigMonitor(key, watcher) if err != nil { panic(err) } - if cp == nil { - cm.SetParser(parser.DefaultConfigParse()) - } else { - // use customized parser - cm.SetParser(cp) + // use custom parser + if opts.CustomParser != nil { + cm.SetParser(opts.CustomParser) + } + if opts.CustomParams != nil { + cm.SetParams(opts.CustomParams) } return &FileConfigServerSuite{ diff --git a/utils/utils.go b/utils/utils.go index 2123f0b..0eacd61 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -18,8 +18,15 @@ import ( "errors" "io/fs" "os" + + "github.com/kitex-contrib/config-file/parser" ) +type Options struct { + CustomParser parser.ConfigParser + CustomParams *parser.ConfigParam +} + // PathExists check whether the file or directory exists func PathExists(path string) (bool, error) { _, err := os.Stat(path) From 3b4488baafe5e65221b45f4f1b2d107cd3756749 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Sat, 20 Jan 2024 01:03:37 +0800 Subject: [PATCH 06/15] feat: example for custom parser --- example/client/kitex_client.ini | 19 +++++++++++ example/client/main.go | 60 +++++++++++++++++++++++++++++---- example/server/kitex_server.ini | 3 ++ example/server/main.go | 28 +++++++++++++-- parser/client.go | 6 ++-- parser/server.go | 2 +- 6 files changed, 105 insertions(+), 13 deletions(-) create mode 100644 example/client/kitex_client.ini create mode 100644 example/server/kitex_server.ini diff --git a/example/client/kitex_client.ini b/example/client/kitex_client.ini new file mode 100644 index 0000000..f854243 --- /dev/null +++ b/example/client/kitex_client.ini @@ -0,0 +1,19 @@ +[Timeout] +RPCTimeoutMS = 100 +ConnTimeoutMS = 2000 + +[Circuitbreaker] +Enable = true +ErrRate = 0.3 +MinSample = 100 + +[Retry] +Enable = true +Type = 0 + +[StopPolicy] +MaxRetryTimes = 2 +MaxDurationMS = 1000 + +[CBPolicy] +ErrorRate = 0.2 \ No newline at end of file diff --git a/example/client/main.go b/example/client/main.go index e360160..6044fc3 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -25,25 +25,67 @@ import ( "github.com/cloudwego/kitex-examples/kitex_gen/api" "github.com/cloudwego/kitex-examples/kitex_gen/api/echo" kitexclient "github.com/cloudwego/kitex/client" + "github.com/cloudwego/kitex/pkg/circuitbreak" "github.com/cloudwego/kitex/pkg/klog" + "github.com/cloudwego/kitex/pkg/retry" + "github.com/cloudwego/kitex/pkg/rpctimeout" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" "github.com/kitex-contrib/config-file/utils" + "gopkg.in/ini.v1" ) const ( - filepath = "kitex_client.json" - key = "ClientName/ServiceName" - serviceName = "ServiceName" - clientName = "echo" + filepath = "kitex_client.ini" + key = "ClientName/ServiceName" + serviceName = "ServiceName" + clientName = "echo" + INI parser.ConfigType = "ini" ) // Customed by user type MyParser struct{} +// one example for custom parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { - return fmt.Errorf("my custom parser: %s parser", kind) + cfg, err := ini.Load(data) + if err != nil { + return fmt.Errorf("load config error: %v", err) + } + + cfm := make(parser.ClientFileManager, 0) + cfc := &parser.ClientFileConfig{ + Timeout: make(map[string]*rpctimeout.RPCTimeout, 0), + Retry: make(map[string]*retry.Policy, 0), + Circuitbreaker: make(map[string]*circuitbreak.CBConfig, 0), + } + + timeout := &rpctimeout.RPCTimeout{} + circ := &circuitbreak.CBConfig{} + ret := &retry.Policy{} + stop := &retry.StopPolicy{} + cb := &retry.CBPolicy{} + + cfg.Section("Timeout").MapTo(timeout) + cfg.Section("Circuitbreaker").MapTo(circ) + cfg.Section("Retry").MapTo(ret) + cfg.Section("StopPolicy").MapTo(stop) + cfg.Section("CBPolicy").MapTo(cb) + stop.CBPolicy = *cb + ret.FailurePolicy = &retry.FailurePolicy{ + StopPolicy: *stop, + } + + cfc.Timeout[clientName] = timeout + cfc.Circuitbreaker[clientName] = circ + cfc.Retry[clientName] = ret + + cfm[key] = cfc + + v := config.(*parser.ClientFileManager) + *v = cfm + return err } func main() { @@ -68,7 +110,13 @@ func main() { }() // customed by user - opts := &utils.Options{} + params := &parser.ConfigParam{ + Type: INI, + } + opts := &utils.Options{ + CustomParser: &MyParser{}, + CustomParams: params, + } client, err := echo.NewClient( serviceName, diff --git a/example/server/kitex_server.ini b/example/server/kitex_server.ini new file mode 100644 index 0000000..846621b --- /dev/null +++ b/example/server/kitex_server.ini @@ -0,0 +1,3 @@ +[ServiceName] +ConnectionLimit = 300 +QPSLimit = 200 \ No newline at end of file diff --git a/example/server/main.go b/example/server/main.go index f96741e..711dfaa 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -28,12 +28,13 @@ import ( "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" "github.com/kitex-contrib/config-file/utils" + "gopkg.in/ini.v1" ) var _ api.Echo = &EchoImpl{} const ( - filepath = "kitex_server.json" + filepath = "kitex_server.ini" key = "ServiceName" serviceName = "ServiceName" INI parser.ConfigType = "ini" @@ -51,8 +52,22 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon // Customed by user type MyParser struct{} +// one example for custom parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { - return fmt.Errorf("my custom parser: %s parser", kind) + cfg, err := ini.Load(data) + if err != nil { + return fmt.Errorf("load config error: %v", err) + } + + sfm := make(parser.ServerFileManager, 0) + + sfc := &parser.ServerFileConfig{} + cfg.Section(serviceName).MapTo(sfc) + sfm[key] = sfc + + v := config.(*parser.ServerFileManager) + *v = sfm + return err } func main() { @@ -70,7 +85,14 @@ func main() { defer fw.StopWatching() // customed by user - opts := &utils.Options{} + params := &parser.ConfigParam{ + Type: INI, + } + + opts := &utils.Options{ + CustomParser: &MyParser{}, + CustomParams: params, + } svr := echo.NewServer( new(EchoImpl), diff --git a/parser/client.go b/parser/client.go index 41a7931..7a98800 100644 --- a/parser/client.go +++ b/parser/client.go @@ -22,9 +22,9 @@ import ( // ClientFileConfig is config of a client/service pair type ClientFileConfig struct { - Timeout map[string]*rpctimeout.RPCTimeout `mapstructure:"timeout"` // key: method, "*" for default - Retry map[string]*retry.Policy `mapstructure:"retry"` // key: method, "*" for default - Circuitbreaker map[string]*circuitbreak.CBConfig `mapstructure:"circuitbreaker"` // key: method + Timeout map[string]*rpctimeout.RPCTimeout `mapstructure:"timeout" ini:"timeout"` // key: method, "*" for default + Retry map[string]*retry.Policy `mapstructure:"retry" ini:"retry"` // key: method, "*" for default + Circuitbreaker map[string]*circuitbreak.CBConfig `mapstructure:"circuitbreaker" ini:"circuitbreaker"` // key: method } // ClientFileManager is a map of client/service pairs to ClientFileConfig diff --git a/parser/server.go b/parser/server.go index ea6350c..0acf360 100644 --- a/parser/server.go +++ b/parser/server.go @@ -18,7 +18,7 @@ import "github.com/cloudwego/kitex/pkg/limiter" // ServerFileConfig is config of a service type ServerFileConfig struct { - Limit limiter.LimiterConfig `mapstructure:"limit" ini:"limit"` + Limit limiter.LimiterConfig `mapstructure:"limit" ini:"ServiceName"` } // ServerFileManager is a map of service names to ServerFileConfig From 6ce195b03df71cd2acdbf4da3b0b202de02b53df Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Sun, 21 Jan 2024 20:25:12 +0800 Subject: [PATCH 07/15] chore: modify ini and license --- client/circuit_breaker.go | 2 +- client/client.go | 2 +- client/retry.go | 2 +- client/rpc_timeout.go | 2 +- client/suite.go | 2 +- example/client/kitex_client.ini | 14 +++++++++----- example/client/main.go | 13 +++++++------ example/server/kitex_server.ini | 2 +- example/server/main.go | 5 +++-- filewatcher/filewatcher.go | 2 +- mock/filewatcher_mock.go | 2 +- monitor/monitor.go | 2 +- monitor/monitor_test.go | 2 +- parser/client.go | 2 +- parser/parser.go | 2 +- parser/server.go | 4 ++-- server/limit.go | 2 +- server/server.go | 2 +- server/suite.go | 2 +- utils/set.go | 2 +- utils/set_test.go | 2 +- utils/utils.go | 2 +- 22 files changed, 39 insertions(+), 33 deletions(-) diff --git a/client/circuit_breaker.go b/client/circuit_breaker.go index 653ec5d..541993c 100644 --- a/client/circuit_breaker.go +++ b/client/circuit_breaker.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/client.go b/client/client.go index 674d3e1..3cc1a0c 100644 --- a/client/client.go +++ b/client/client.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/retry.go b/client/retry.go index 370b856..7b6b448 100644 --- a/client/retry.go +++ b/client/retry.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/rpc_timeout.go b/client/rpc_timeout.go index b9a59d7..bd536fe 100644 --- a/client/rpc_timeout.go +++ b/client/rpc_timeout.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/client/suite.go b/client/suite.go index dfc2fac..8b851b3 100644 --- a/client/suite.go +++ b/client/suite.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/example/client/kitex_client.ini b/example/client/kitex_client.ini index f854243..1f93105 100644 --- a/example/client/kitex_client.ini +++ b/example/client/kitex_client.ini @@ -1,19 +1,23 @@ -[Timeout] +[ClientName/ServiceName] RPCTimeoutMS = 100 ConnTimeoutMS = 2000 -[Circuitbreaker] +[ClientName/ServiceName.Circuitbreaker.Echo] Enable = true ErrRate = 0.3 MinSample = 100 -[Retry] +[ClientName/ServiceName.Retry.*] Enable = true Type = 0 -[StopPolicy] +[ClientName/ServiceName.Retry.Echo] +Enable = true +Type = 1 + +[ClientName/ServiceName.Retry.*.FailurePolicy.StopPolicy] MaxRetryTimes = 2 MaxDurationMS = 1000 -[CBPolicy] +[ClientName/ServiceName.Retry.*.CBPolicy] ErrorRate = 0.2 \ No newline at end of file diff --git a/example/client/main.go b/example/client/main.go index 6044fc3..f2c9560 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -48,6 +48,7 @@ const ( type MyParser struct{} // one example for custom parser +// if the type of client config is json or yaml,just using default parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { cfg, err := ini.Load(data) if err != nil { @@ -67,11 +68,11 @@ func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{ stop := &retry.StopPolicy{} cb := &retry.CBPolicy{} - cfg.Section("Timeout").MapTo(timeout) - cfg.Section("Circuitbreaker").MapTo(circ) - cfg.Section("Retry").MapTo(ret) - cfg.Section("StopPolicy").MapTo(stop) - cfg.Section("CBPolicy").MapTo(cb) + cfg.Section(key).MapTo(timeout) + cfg.Section("ClientName/ServiceName.Circuitbreaker.Echo").MapTo(circ) + cfg.Section("ClientName/ServiceName.Retry.*").MapTo(ret) + cfg.Section("ClientName/ServiceName.Retry.*.FailurePolicy.StopPolicy").MapTo(stop) + cfg.Section("ClientName/ServiceName.Retry.*.CBPolicy").MapTo(cb) stop.CBPolicy = *cb ret.FailurePolicy = &retry.FailurePolicy{ StopPolicy: *stop, diff --git a/example/server/kitex_server.ini b/example/server/kitex_server.ini index 846621b..6ecb48b 100644 --- a/example/server/kitex_server.ini +++ b/example/server/kitex_server.ini @@ -1,3 +1,3 @@ -[ServiceName] +[ServiceName.Limit] ConnectionLimit = 300 QPSLimit = 200 \ No newline at end of file diff --git a/example/server/main.go b/example/server/main.go index 711dfaa..6cfaa1b 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -53,6 +53,7 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon type MyParser struct{} // one example for custom parser +// if the type of client config is json or yaml,just using default parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { cfg, err := ini.Load(data) if err != nil { @@ -62,7 +63,7 @@ func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{ sfm := make(parser.ServerFileManager, 0) sfc := &parser.ServerFileConfig{} - cfg.Section(serviceName).MapTo(sfc) + cfg.MapTo(sfc) sfm[key] = sfc v := config.(*parser.ServerFileManager) diff --git a/filewatcher/filewatcher.go b/filewatcher/filewatcher.go index 69818b9..dadf6f8 100644 --- a/filewatcher/filewatcher.go +++ b/filewatcher/filewatcher.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/mock/filewatcher_mock.go b/mock/filewatcher_mock.go index 35f57d5..8ea0c12 100644 --- a/mock/filewatcher_mock.go +++ b/mock/filewatcher_mock.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/monitor/monitor.go b/monitor/monitor.go index 09df905..04c6c1c 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index 9105b9d..9f936ce 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/parser/client.go b/parser/client.go index 7a98800..a9e6c48 100644 --- a/parser/client.go +++ b/parser/client.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/parser/parser.go b/parser/parser.go index 305dae0..2b30b2d 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/parser/server.go b/parser/server.go index 0acf360..3d0dedf 100644 --- a/parser/server.go +++ b/parser/server.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ import "github.com/cloudwego/kitex/pkg/limiter" // ServerFileConfig is config of a service type ServerFileConfig struct { - Limit limiter.LimiterConfig `mapstructure:"limit" ini:"ServiceName"` + Limit limiter.LimiterConfig `mapstructure:"limit" ini:"ServiceName.Limit"` } // ServerFileManager is a map of service names to ServerFileConfig diff --git a/server/limit.go b/server/limit.go index 468121a..92d81e3 100644 --- a/server/limit.go +++ b/server/limit.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/server.go b/server/server.go index 673e637..cdf9f02 100644 --- a/server/server.go +++ b/server/server.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/server/suite.go b/server/suite.go index e4574ed..4732dde 100644 --- a/server/suite.go +++ b/server/suite.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/utils/set.go b/utils/set.go index 597f225..7b7cb3c 100644 --- a/utils/set.go +++ b/utils/set.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/utils/set_test.go b/utils/set_test.go index 1013b79..94ec404 100644 --- a/utils/set_test.go +++ b/utils/set_test.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/utils/utils.go b/utils/utils.go index 0eacd61..014c064 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -1,4 +1,4 @@ -// Copyright 2023 CloudWeGo Authors +// Copyright 2024 CloudWeGo Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. From a3e42be3d2fc49c461a1b19210d9cef108ebaf9b Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Sun, 21 Jan 2024 20:43:41 +0800 Subject: [PATCH 08/15] chore: delete ini config file --- example/client/kitex_client.ini | 23 ------------- example/client/main.go | 57 ++++----------------------------- example/server/kitex_server.ini | 3 -- example/server/main.go | 30 ++++------------- parser/client.go | 6 ++-- parser/server.go | 2 +- 6 files changed, 17 insertions(+), 104 deletions(-) delete mode 100644 example/client/kitex_client.ini delete mode 100644 example/server/kitex_server.ini diff --git a/example/client/kitex_client.ini b/example/client/kitex_client.ini deleted file mode 100644 index 1f93105..0000000 --- a/example/client/kitex_client.ini +++ /dev/null @@ -1,23 +0,0 @@ -[ClientName/ServiceName] -RPCTimeoutMS = 100 -ConnTimeoutMS = 2000 - -[ClientName/ServiceName.Circuitbreaker.Echo] -Enable = true -ErrRate = 0.3 -MinSample = 100 - -[ClientName/ServiceName.Retry.*] -Enable = true -Type = 0 - -[ClientName/ServiceName.Retry.Echo] -Enable = true -Type = 1 - -[ClientName/ServiceName.Retry.*.FailurePolicy.StopPolicy] -MaxRetryTimes = 2 -MaxDurationMS = 1000 - -[ClientName/ServiceName.Retry.*.CBPolicy] -ErrorRate = 0.2 \ No newline at end of file diff --git a/example/client/main.go b/example/client/main.go index f2c9560..b3c80d9 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -16,7 +16,7 @@ package main import ( "context" - "fmt" + "encoding/json" "log" "os" "os/signal" @@ -25,23 +25,18 @@ import ( "github.com/cloudwego/kitex-examples/kitex_gen/api" "github.com/cloudwego/kitex-examples/kitex_gen/api/echo" kitexclient "github.com/cloudwego/kitex/client" - "github.com/cloudwego/kitex/pkg/circuitbreak" "github.com/cloudwego/kitex/pkg/klog" - "github.com/cloudwego/kitex/pkg/retry" - "github.com/cloudwego/kitex/pkg/rpctimeout" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" "github.com/kitex-contrib/config-file/utils" - "gopkg.in/ini.v1" ) const ( - filepath = "kitex_client.ini" - key = "ClientName/ServiceName" - serviceName = "ServiceName" - clientName = "echo" - INI parser.ConfigType = "ini" + filepath = "kitex_client.json" + key = "ClientName/ServiceName" + serviceName = "ServiceName" + clientName = "echo" ) // Customed by user @@ -50,43 +45,7 @@ type MyParser struct{} // one example for custom parser // if the type of client config is json or yaml,just using default parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { - cfg, err := ini.Load(data) - if err != nil { - return fmt.Errorf("load config error: %v", err) - } - - cfm := make(parser.ClientFileManager, 0) - cfc := &parser.ClientFileConfig{ - Timeout: make(map[string]*rpctimeout.RPCTimeout, 0), - Retry: make(map[string]*retry.Policy, 0), - Circuitbreaker: make(map[string]*circuitbreak.CBConfig, 0), - } - - timeout := &rpctimeout.RPCTimeout{} - circ := &circuitbreak.CBConfig{} - ret := &retry.Policy{} - stop := &retry.StopPolicy{} - cb := &retry.CBPolicy{} - - cfg.Section(key).MapTo(timeout) - cfg.Section("ClientName/ServiceName.Circuitbreaker.Echo").MapTo(circ) - cfg.Section("ClientName/ServiceName.Retry.*").MapTo(ret) - cfg.Section("ClientName/ServiceName.Retry.*.FailurePolicy.StopPolicy").MapTo(stop) - cfg.Section("ClientName/ServiceName.Retry.*.CBPolicy").MapTo(cb) - stop.CBPolicy = *cb - ret.FailurePolicy = &retry.FailurePolicy{ - StopPolicy: *stop, - } - - cfc.Timeout[clientName] = timeout - cfc.Circuitbreaker[clientName] = circ - cfc.Retry[clientName] = ret - - cfm[key] = cfc - - v := config.(*parser.ClientFileManager) - *v = cfm - return err + return json.Unmarshal(data, config) } func main() { @@ -111,9 +70,7 @@ func main() { }() // customed by user - params := &parser.ConfigParam{ - Type: INI, - } + params := &parser.ConfigParam{} opts := &utils.Options{ CustomParser: &MyParser{}, CustomParams: params, diff --git a/example/server/kitex_server.ini b/example/server/kitex_server.ini deleted file mode 100644 index 6ecb48b..0000000 --- a/example/server/kitex_server.ini +++ /dev/null @@ -1,3 +0,0 @@ -[ServiceName.Limit] -ConnectionLimit = 300 -QPSLimit = 200 \ No newline at end of file diff --git a/example/server/main.go b/example/server/main.go index 6cfaa1b..c502aed 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -16,7 +16,7 @@ package main import ( "context" - "fmt" + "encoding/json" "log" "github.com/cloudwego/kitex-examples/kitex_gen/api" @@ -28,16 +28,14 @@ import ( "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" "github.com/kitex-contrib/config-file/utils" - "gopkg.in/ini.v1" ) var _ api.Echo = &EchoImpl{} const ( - filepath = "kitex_server.ini" - key = "ServiceName" - serviceName = "ServiceName" - INI parser.ConfigType = "ini" + filepath = "kitex_server.json" + key = "ServiceName" + serviceName = "ServiceName" ) // EchoImpl implements the last service interface defined in the IDL. @@ -55,20 +53,7 @@ type MyParser struct{} // one example for custom parser // if the type of client config is json or yaml,just using default parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { - cfg, err := ini.Load(data) - if err != nil { - return fmt.Errorf("load config error: %v", err) - } - - sfm := make(parser.ServerFileManager, 0) - - sfc := &parser.ServerFileConfig{} - cfg.MapTo(sfc) - sfm[key] = sfc - - v := config.(*parser.ServerFileManager) - *v = sfm - return err + return json.Unmarshal(data, config) } func main() { @@ -86,10 +71,7 @@ func main() { defer fw.StopWatching() // customed by user - params := &parser.ConfigParam{ - Type: INI, - } - + params := &parser.ConfigParam{} opts := &utils.Options{ CustomParser: &MyParser{}, CustomParams: params, diff --git a/parser/client.go b/parser/client.go index a9e6c48..7b472bb 100644 --- a/parser/client.go +++ b/parser/client.go @@ -22,9 +22,9 @@ import ( // ClientFileConfig is config of a client/service pair type ClientFileConfig struct { - Timeout map[string]*rpctimeout.RPCTimeout `mapstructure:"timeout" ini:"timeout"` // key: method, "*" for default - Retry map[string]*retry.Policy `mapstructure:"retry" ini:"retry"` // key: method, "*" for default - Circuitbreaker map[string]*circuitbreak.CBConfig `mapstructure:"circuitbreaker" ini:"circuitbreaker"` // key: method + Timeout map[string]*rpctimeout.RPCTimeout `mapstructure:"timeout"` // key: method, "*" for default + Retry map[string]*retry.Policy `mapstructure:"retry"` // key: method, "*" for default + Circuitbreaker map[string]*circuitbreak.CBConfig `mapstructure:"circuitbreaker"` // key: method } // ClientFileManager is a map of client/service pairs to ClientFileConfig diff --git a/parser/server.go b/parser/server.go index 3d0dedf..6b1dc35 100644 --- a/parser/server.go +++ b/parser/server.go @@ -18,7 +18,7 @@ import "github.com/cloudwego/kitex/pkg/limiter" // ServerFileConfig is config of a service type ServerFileConfig struct { - Limit limiter.LimiterConfig `mapstructure:"limit" ini:"ServiceName.Limit"` + Limit limiter.LimiterConfig `mapstructure:"limit"` } // ServerFileManager is a map of service names to ServerFileConfig From 07a49e99e7fbb011aa7e5304836b9d51ab94af92 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Mon, 22 Jan 2024 01:16:28 +0800 Subject: [PATCH 09/15] docs: update README.md and README_CN.md --- README.md | 55 ++++++++++++++++++++++++++++++++++++++--- README_CN.md | 56 +++++++++++++++++++++++++++++++++++++++--- example/client/main.go | 2 +- example/server/main.go | 4 +-- 4 files changed, 107 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index a7ba93a..efd9c42 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ package main import ( "context" + "encoding/json" "log" "github.com/cloudwego/kitex-examples/kitex_gen/api" @@ -29,7 +30,17 @@ import ( "github.com/cloudwego/kitex/pkg/rpcinfo" kitexserver "github.com/cloudwego/kitex/server" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" + "github.com/kitex-contrib/config-file/utils" +) + +var _ api.Echo = &EchoImpl{} + +const ( + filepath = "kitex_server.json" + key = "ServiceName" + serviceName = "ServiceName" ) var _ api.Echo = &EchoImpl{} @@ -49,6 +60,15 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon return &api.Response{Message: req.Message}, nil } +// customed by user +type MyParser struct{} + +// one example for custom parser +// if the type of server config is json or yaml,just using default parser +func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { + return json.Unmarshal(data, config) +} + func main() { klog.SetLevel(klog.LevelDebug) @@ -63,10 +83,17 @@ func main() { } defer fw.StopWatching() + // customed by user + params := &parser.ConfigParam{} + opts := &utils.Options{ + CustomParser: &MyParser{}, + CustomParams: params, + } + svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw, opts)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) @@ -83,6 +110,7 @@ package main import ( "context" + "encoding/json" "log" "os" "os/signal" @@ -94,6 +122,8 @@ import ( "github.com/cloudwego/kitex/pkg/klog" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) const ( @@ -103,6 +133,15 @@ const ( clientName = "ClientName" ) +// customed by user +type MyParser struct{} + +// one example for custom parser +// if the type of client config is json or yaml,just using default parser +func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { + return json.Unmarshal(data, config) +} + func main() { klog.SetLevel(klog.LevelDebug) @@ -124,10 +163,17 @@ func main() { os.Exit(1) }() + // customed by user + params := &parser.ConfigParam{} + opts := &utils.Options{ + CustomParser: &MyParser{}, + CustomParams: params, + } + client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, opts)), ) if err != nil { log.Fatal(err) @@ -144,9 +190,12 @@ func main() { time.Sleep(time.Second * 10) } } - ``` +#### File Configuration Format + +The configuration format supports `json` and `yaml` by default. You can implement a custom parser by implementing the `ConfigParser` interface, and pass in the custom parser and custom parameters through `utils.Options` when `NewSuite` + #### Governance Policy > The service name is `ServiceName` and the client name is `ClientName`. diff --git a/README_CN.md b/README_CN.md index 1eced8b..fe70cfa 100644 --- a/README_CN.md +++ b/README_CN.md @@ -21,6 +21,7 @@ package main import ( "context" + "encoding/json" "log" "github.com/cloudwego/kitex-examples/kitex_gen/api" @@ -29,7 +30,17 @@ import ( "github.com/cloudwego/kitex/pkg/rpcinfo" kitexserver "github.com/cloudwego/kitex/server" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" + "github.com/kitex-contrib/config-file/utils" +) + +var _ api.Echo = &EchoImpl{} + +const ( + filepath = "kitex_server.json" + key = "ServiceName" + serviceName = "ServiceName" ) var _ api.Echo = &EchoImpl{} @@ -49,6 +60,15 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon return &api.Response{Message: req.Message}, nil } +// customed by user +type MyParser struct{} + +// one example for custom parser +// if the type of server config is json or yaml,just using default parser +func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { + return json.Unmarshal(data, config) +} + func main() { klog.SetLevel(klog.LevelDebug) @@ -63,10 +83,17 @@ func main() { } defer fw.StopWatching() + // customed by user + params := &parser.ConfigParam{} + opts := &utils.Options{ + CustomParser: &MyParser{}, + CustomParams: params, + } + svr := echo.NewServer( new(EchoImpl), - server.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - server.WithSuite(fileserver.NewSuite(key, fw)), // add watcher + kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), + kitexserver.WithSuite(fileserver.NewSuite(key, fw, opts)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) @@ -83,6 +110,7 @@ package main import ( "context" + "encoding/json" "log" "os" "os/signal" @@ -94,6 +122,8 @@ import ( "github.com/cloudwego/kitex/pkg/klog" fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" + "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) const ( @@ -103,6 +133,15 @@ const ( clientName = "ClientName" ) +// customed by user +type MyParser struct{} + +// one example for custom parser +// if the type of client config is json or yaml,just using default parser +func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { + return json.Unmarshal(data, config) +} + func main() { klog.SetLevel(klog.LevelDebug) @@ -124,10 +163,17 @@ func main() { os.Exit(1) }() + // customed by user + params := &parser.ConfigParam{} + opts := &utils.Options{ + CustomParser: &MyParser{}, + CustomParams: params, + } + client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, opts)), ) if err != nil { log.Fatal(err) @@ -144,9 +190,11 @@ func main() { time.Sleep(time.Second * 10) } } - ``` +#### File配置格式 +配置格式默认支持`json`和`yaml`,可以通过实现`ConfigParser`接口实现自定义解析器,并在`NewSuite`的时候通过`utils.Options`传入自定义解析器以及自定义参数 + #### 治理策略 > 服务名称为 ServiceName,客户端名称为 ClientName diff --git a/example/client/main.go b/example/client/main.go index b3c80d9..1955789 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -39,7 +39,7 @@ const ( clientName = "echo" ) -// Customed by user +// customed by user type MyParser struct{} // one example for custom parser diff --git a/example/server/main.go b/example/server/main.go index c502aed..ee4f060 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -47,11 +47,11 @@ func (s *EchoImpl) Echo(ctx context.Context, req *api.Request) (resp *api.Respon return &api.Response{Message: req.Message}, nil } -// Customed by user +// customed by user type MyParser struct{} // one example for custom parser -// if the type of client config is json or yaml,just using default parser +// if the type of server config is json or yaml,just using default parser func (p *MyParser) Decode(kind parser.ConfigType, data []byte, config interface{}) error { return json.Unmarshal(data, config) } From a544617513f6010e11a04af6239b45b239fa8b16 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 23 Jan 2024 11:36:29 +0800 Subject: [PATCH 10/15] fix: options usage --- client/suite.go | 19 +++++++++---------- example/client/main.go | 10 +--------- example/server/main.go | 10 +--------- monitor/monitor.go | 7 ++++--- server/suite.go | 21 +++++++++++---------- utils/utils.go | 8 +++++--- 6 files changed, 31 insertions(+), 44 deletions(-) diff --git a/client/suite.go b/client/suite.go index 8b851b3..fba14ea 100644 --- a/client/suite.go +++ b/client/suite.go @@ -28,19 +28,18 @@ type FileConfigClientSuite struct { } // NewSuite service is the destination service. -func NewSuite(service, key string, watcher filewatcher.FileWatcher, opts *utils.Options) *FileConfigClientSuite { - cm, err := monitor.NewConfigMonitor(key, watcher) - if err != nil { - panic(err) +func NewSuite(service, key string, watcher filewatcher.FileWatcher, opts ...utils.Options) *FileConfigClientSuite { + parserOption := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), } - - // use custom parser - if opts.CustomParser != nil { - cm.SetParser(opts.CustomParser) + for _, option := range opts { + option(parserOption) } - if opts.CustomParams != nil { - cm.SetParams(opts.CustomParams) + cm, err := monitor.NewConfigMonitor(key, watcher, parserOption) + if err != nil { + panic(err) } return &FileConfigClientSuite{ diff --git a/example/client/main.go b/example/client/main.go index 1955789..a913cf5 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -29,7 +29,6 @@ import ( fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" - "github.com/kitex-contrib/config-file/utils" ) const ( @@ -69,17 +68,10 @@ func main() { os.Exit(1) }() - // customed by user - params := &parser.ConfigParam{} - opts := &utils.Options{ - CustomParser: &MyParser{}, - CustomParams: params, - } - client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, opts)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), ) if err != nil { log.Fatal(err) diff --git a/example/server/main.go b/example/server/main.go index ee4f060..b7be1be 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -27,7 +27,6 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" - "github.com/kitex-contrib/config-file/utils" ) var _ api.Echo = &EchoImpl{} @@ -70,17 +69,10 @@ func main() { } defer fw.StopWatching() - // customed by user - params := &parser.ConfigParam{} - opts := &utils.Options{ - CustomParser: &MyParser{}, - CustomParams: params, - } - svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw, opts)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) diff --git a/monitor/monitor.go b/monitor/monitor.go index 04c6c1c..7dadb71 100644 --- a/monitor/monitor.go +++ b/monitor/monitor.go @@ -22,6 +22,7 @@ import ( "github.com/cloudwego/kitex/pkg/klog" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) type ConfigMonitor interface { @@ -54,7 +55,7 @@ type configMonitor struct { } // NewConfigMonitor init a monitor for the config file -func NewConfigMonitor(key string, watcher filewatcher.FileWatcher) (ConfigMonitor, error) { +func NewConfigMonitor(key string, watcher filewatcher.FileWatcher, opt *utils.Option) (ConfigMonitor, error) { if key == "" { return nil, errors.New("empty config key") } @@ -66,8 +67,8 @@ func NewConfigMonitor(key string, watcher filewatcher.FileWatcher) (ConfigMonito fileWatcher: watcher, key: key, callbacks: make(map[int64]func(), 0), - parser: parser.DefaultConfigParser(), - params: parser.DefaultConfigParam(), + parser: opt.Parser, + params: opt.Params, }, nil } diff --git a/server/suite.go b/server/suite.go index 4732dde..b39268c 100644 --- a/server/suite.go +++ b/server/suite.go @@ -27,18 +27,19 @@ type FileConfigServerSuite struct { } // NewSuite service is the destination service. -func NewSuite(key string, watcher filewatcher.FileWatcher, opts *utils.Options) *FileConfigServerSuite { - cm, err := monitor.NewConfigMonitor(key, watcher) - if err != nil { - panic(err) - } - +func NewSuite(key string, watcher filewatcher.FileWatcher, opts ...utils.Options) *FileConfigServerSuite { // use custom parser - if opts.CustomParser != nil { - cm.SetParser(opts.CustomParser) + parserOption := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), } - if opts.CustomParams != nil { - cm.SetParams(opts.CustomParams) + for _, option := range opts { + option(parserOption) + } + + cm, err := monitor.NewConfigMonitor(key, watcher, parserOption) + if err != nil { + panic(err) } return &FileConfigServerSuite{ diff --git a/utils/utils.go b/utils/utils.go index 014c064..3bca97c 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -22,11 +22,13 @@ import ( "github.com/kitex-contrib/config-file/parser" ) -type Options struct { - CustomParser parser.ConfigParser - CustomParams *parser.ConfigParam +type Option struct { + Parser parser.ConfigParser + Params *parser.ConfigParam } +type Options func(o *Option) + // PathExists check whether the file or directory exists func PathExists(path string) (bool, error) { _, err := os.Stat(path) From 44028b18e2181c975f01565aac5a920bef3d0ef4 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 23 Jan 2024 11:37:27 +0800 Subject: [PATCH 11/15] fix: testProgress() fail --- monitor/monitor_test.go | 87 +++++++++++++++++++++++++++++++++++------ 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index 9f936ce..4c4b10a 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -20,6 +20,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/mock" "github.com/kitex-contrib/config-file/parser" + "github.com/kitex-contrib/config-file/utils" ) const ( @@ -28,24 +29,39 @@ const ( func TestNewConfigMonitor(t *testing.T) { m := mock.NewMockFileWatcher() - if _, err := NewConfigMonitor("test", m); err != nil { + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + if _, err := NewConfigMonitor("test", m, opt); err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } } func TestNewConfigMonitorFailed(t *testing.T) { m := mock.NewMockFileWatcher() - if _, err := NewConfigMonitor("", m); err == nil { + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + if _, err := NewConfigMonitor("", m, opt); err == nil { t.Errorf("NewConfigMonitor() error = %v", err) } - if _, err := NewConfigMonitor("test", nil); err == nil { + if _, err := NewConfigMonitor("test", nil, nil); err == nil { t.Errorf("NewConfigMonitor() error = %v", err) } } func TestKey(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -56,7 +72,12 @@ func TestKey(t *testing.T) { func TestSetManager(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -65,7 +86,12 @@ func TestSetManager(t *testing.T) { func TestSetParser(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -83,7 +109,12 @@ func TestSetParser(t *testing.T) { func TestSetParams(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -93,7 +124,12 @@ func TestSetParams(t *testing.T) { func TestRegisterCallback(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -102,7 +138,12 @@ func TestRegisterCallback(t *testing.T) { func TestDeregisterCallback(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -111,7 +152,12 @@ func TestDeregisterCallback(t *testing.T) { func TestStartFailed(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -122,7 +168,12 @@ func TestStartFailed(t *testing.T) { func TestStartSuccess(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -134,7 +185,12 @@ func TestStartSuccess(t *testing.T) { func TestStop(t *testing.T) { m := mock.NewMockFileWatcher() - cm, err := NewConfigMonitor("test", m) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", m, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } @@ -155,7 +211,12 @@ func TestEntireProcessWithSameKey(t *testing.T) { func createConfigManager(fw filewatcher.FileWatcher, key string, t *testing.T) ConfigMonitor { // create a config monitor object - cm, err := NewConfigMonitor(key, fw) + opt := &utils.Option{ + Parser: parser.DefaultConfigParser(), + Params: parser.DefaultConfigParam(), + } + + cm, err := NewConfigMonitor("test", fw, opt) if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } From 570c9cc1d4edf126821984d7209bf49372d00a7a Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 23 Jan 2024 11:38:09 +0800 Subject: [PATCH 12/15] docs: update README.md and READ_CN.md --- README.md | 57 ++++++++++++++++++++++++++------------------------- README_CN.md | 58 +++++++++++++++++++++++++++------------------------- 2 files changed, 59 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index efd9c42..2d420e3 100644 --- a/README.md +++ b/README.md @@ -32,15 +32,6 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" - "github.com/kitex-contrib/config-file/utils" -) - -var _ api.Echo = &EchoImpl{} - -const ( - filepath = "kitex_server.json" - key = "ServiceName" - serviceName = "ServiceName" ) var _ api.Echo = &EchoImpl{} @@ -83,17 +74,10 @@ func main() { } defer fw.StopWatching() - // customed by user - params := &parser.ConfigParam{} - opts := &utils.Options{ - CustomParser: &MyParser{}, - CustomParams: params, - } - svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw, opts)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) @@ -123,7 +107,6 @@ import ( fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" - "github.com/kitex-contrib/config-file/utils" ) const ( @@ -163,17 +146,10 @@ func main() { os.Exit(1) }() - // customed by user - params := &parser.ConfigParam{} - opts := &utils.Options{ - CustomParser: &MyParser{}, - CustomParams: params, - } - client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, opts)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), ) if err != nil { log.Fatal(err) @@ -192,9 +168,34 @@ func main() { } ``` -#### File Configuration Format +#### File Configuration -The configuration format supports `json` and `yaml` by default. You can implement a custom parser by implementing the `ConfigParser` interface, and pass in the custom parser and custom parameters through `utils.Options` when `NewSuite` +##### Custom Parser +The configuration format supports `json` and `yaml` by default, which can be implemented by +The `ConfigParser` interface implements a custom parser and passes in the custom function through `utils.Options` during `NewSuite` + +Interface definition: +``` +type ConfigParser interface { +Decode(kind ConfigType, data []byte, config interface{}) error +} +``` + +Sample code: +Custom function +``` +func customParser(parser parser.ConfigParser) utils.Options { + return func(o *utils.Option) { + o.Parser = parser + } +} + +func customConfigParams(pararm *parser.ConfigParam) utils.Options { + return func(o *utils.Option) { + o.Params = pararm + } +} +``` #### Governance Policy > The service name is `ServiceName` and the client name is `ClientName`. diff --git a/README_CN.md b/README_CN.md index fe70cfa..9f3ed95 100644 --- a/README_CN.md +++ b/README_CN.md @@ -32,15 +32,6 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" - "github.com/kitex-contrib/config-file/utils" -) - -var _ api.Echo = &EchoImpl{} - -const ( - filepath = "kitex_server.json" - key = "ServiceName" - serviceName = "ServiceName" ) var _ api.Echo = &EchoImpl{} @@ -83,17 +74,10 @@ func main() { } defer fw.StopWatching() - // customed by user - params := &parser.ConfigParam{} - opts := &utils.Options{ - CustomParser: &MyParser{}, - CustomParams: params, - } - svr := echo.NewServer( new(EchoImpl), kitexserver.WithServerBasicInfo(&rpcinfo.EndpointBasicInfo{ServiceName: serviceName}), - kitexserver.WithSuite(fileserver.NewSuite(key, fw, opts)), // add watcher + kitexserver.WithSuite(fileserver.NewSuite(key, fw)), // add watcher ) if err := svr.Run(); err != nil { log.Println("server stopped with error:", err) @@ -123,7 +107,6 @@ import ( fileclient "github.com/kitex-contrib/config-file/client" "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" - "github.com/kitex-contrib/config-file/utils" ) const ( @@ -163,17 +146,10 @@ func main() { os.Exit(1) }() - // customed by user - params := &parser.ConfigParam{} - opts := &utils.Options{ - CustomParser: &MyParser{}, - CustomParams: params, - } - client, err := echo.NewClient( serviceName, kitexclient.WithHostPorts("0.0.0.0:8888"), - kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw, opts)), + kitexclient.WithSuite(fileclient.NewSuite(serviceName, key, fw)), ) if err != nil { log.Fatal(err) @@ -192,8 +168,34 @@ func main() { } ``` -#### File配置格式 -配置格式默认支持`json`和`yaml`,可以通过实现`ConfigParser`接口实现自定义解析器,并在`NewSuite`的时候通过`utils.Options`传入自定义解析器以及自定义参数 +#### File配置 + +##### 自定义解析器 +配置格式默认支持`json`和`yaml`,可以通过实现 +`ConfigParser`接口实现自定义解析器,并在`NewSuite`的时候通过`utils.Options`传入自定义函数 + +接口定义: +``` +type ConfigParser interface { + Decode(kind ConfigType, data []byte, config interface{}) error +} +``` + +示例代码: +自定义函数 +``` +func customParser(parser parser.ConfigParser) utils.Options { + return func(o *utils.Option) { + o.Parser = parser + } +} + +func customConfigParams(pararm *parser.ConfigParam) utils.Options { + return func(o *utils.Option) { + o.Params = pararm + } +} +``` #### 治理策略 > 服务名称为 ServiceName,客户端名称为 ClientName From 165ea525109bab51abceabac2b06064c62302dcf Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 23 Jan 2024 14:37:11 +0800 Subject: [PATCH 13/15] docs: update README.md and README_CN.md --- README.md | 1 + README_CN.md | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 2d420e3..3ded68f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" + ) var _ api.Echo = &EchoImpl{} diff --git a/README_CN.md b/README_CN.md index 9f3ed95..7765e0a 100644 --- a/README_CN.md +++ b/README_CN.md @@ -32,6 +32,7 @@ import ( "github.com/kitex-contrib/config-file/filewatcher" "github.com/kitex-contrib/config-file/parser" fileserver "github.com/kitex-contrib/config-file/server" + ) var _ api.Echo = &EchoImpl{} From 5291e980990a4fcba715a580c358061fbebaf5a7 Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 23 Jan 2024 14:37:33 +0800 Subject: [PATCH 14/15] test: TestProgress() failed --- monitor/monitor_test.go | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/monitor/monitor_test.go b/monitor/monitor_test.go index 4c4b10a..0f7fc0c 100644 --- a/monitor/monitor_test.go +++ b/monitor/monitor_test.go @@ -84,7 +84,7 @@ func TestSetManager(t *testing.T) { cm.SetManager(&parser.ServerFileManager{}) } -func TestSetParser(t *testing.T) { +func TestConfigParse(t *testing.T) { m := mock.NewMockFileWatcher() opt := &utils.Option{ Parser: parser.DefaultConfigParser(), @@ -95,8 +95,6 @@ func TestSetParser(t *testing.T) { if err != nil { t.Errorf("NewConfigMonitor() error = %v", err) } - cm.SetParser(&parser.Parser{}) - // use json format test ConfigParse kind := parser.JSON jsonData := []byte(`{"key": "value"}`) @@ -107,21 +105,6 @@ func TestSetParser(t *testing.T) { } } -func TestSetParams(t *testing.T) { - m := mock.NewMockFileWatcher() - opt := &utils.Option{ - Parser: parser.DefaultConfigParser(), - Params: parser.DefaultConfigParam(), - } - - cm, err := NewConfigMonitor("test", m, opt) - if err != nil { - t.Errorf("NewConfigMonitor() error = %v", err) - } - - cm.SetParams(&parser.ConfigParam{}) -} - func TestRegisterCallback(t *testing.T) { m := mock.NewMockFileWatcher() opt := &utils.Option{ From a233fd546ff19d8ef732ab7801b8c242d46eb0de Mon Sep 17 00:00:00 2001 From: notacommonperson <1932049002@qq.com> Date: Tue, 23 Jan 2024 14:46:58 +0800 Subject: [PATCH 15/15] docs: update README.md and README_CN.md --- README.md | 4 ++-- README_CN.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3ded68f..a7b1b86 100644 --- a/README.md +++ b/README.md @@ -191,9 +191,9 @@ func customParser(parser parser.ConfigParser) utils.Options { } } -func customConfigParams(pararm *parser.ConfigParam) utils.Options { +func customConfigParams(param *parser.ConfigParam) utils.Options { return func(o *utils.Option) { - o.Params = pararm + o.Params = param } } ``` diff --git a/README_CN.md b/README_CN.md index 7765e0a..3bd5fc5 100644 --- a/README_CN.md +++ b/README_CN.md @@ -191,9 +191,9 @@ func customParser(parser parser.ConfigParser) utils.Options { } } -func customConfigParams(pararm *parser.ConfigParam) utils.Options { +func customConfigParams(param *parser.ConfigParam) utils.Options { return func(o *utils.Option) { - o.Params = pararm + o.Params = param } } ```