trpc.group/trpc-go/trpc-go@v1.0.3/docs/developer_guide/develop_plugins/config.md (about) 1 English | [中文](config.zh_CN.md) 2 3 # How to develop a config type plugin 4 5 This guide will introduce how to develop a config type plugin that relies on configuration for loading. 6 7 The `config` package provides two sets of different configuration interfaces, `config.DataProvider` and `config.KVConfig`. 8 This guide uses the development of the `KVConfig` type configuration as an example, and the development of the `DataProvider` type configuration is similar. 9 10 Developing this plugin requires implementing the following two sub-functions: 11 12 - Implement loading the plugin by relying on configuration. For details, please refer to [plugin](/plugin/README.md). 13 - Implement the `config.KVConfi`g interface and register the implementation with the `config` package. 14 15 The following steps will introduce the relevant development steps using [trpc-config-etcd](https://github.com/trpc-ecosystem/go-config-etcd) as an example. 16 17 ## Implement loading the plugin by relying on configuration 18 19 ### 1. Determine the plugin configuration 20 21 The following is an example of setting the "Endpoint" and "Dialtimeout" configurations in the "trpc_go.yaml" configuration file: 22 23 ```yaml 24 plugins: 25 config: 26 etcd: 27 endpoints: 28 - localhost:2379 29 dialtimeout: 5s 30 ``` 31 32 The plugin is encapsulated based on [etcd-client](https://github.com/etcd-io/etcd/tree/main/client/v3), so the complete configuration is in [Config](https://github.com/etcd-io/etcd/blob/client/v3.5.9/client/v3/config.go#L26). 33 34 ### 2. Implement the plugin.Factory interface 35 36 ```go 37 // etcdPlugin etcd Configuration center plugin. 38 type etcdPlugin struct{} 39 40 // Type implements plugin.Factory. 41 func (p *etcdPlugin) Type() string { 42 return pluginType 43 } 44 45 // Setup implements plugin.Factory. 46 func (p *etcdPlugin) Setup(name string, decoder plugin.Decoder) error { 47 cfg := clientv3.Config{} 48 err := decoder.Decode(&cfg) 49 if err != nil { 50 return err 51 } 52 c, err := New(cfg) 53 if err != nil { 54 return err 55 } 56 config.SetGlobalKV(c) 57 config.Register(c) 58 return nil 59 } 60 ``` 61 62 ### 3. Call plugin.Register to register the plugin with the plugin package 63 64 ```go 65 func init() { 66 plugin.Register(pluginName, NewPlugin()) 67 } 68 ``` 69 70 ## Implement the `config.KVConfi`g interface and register the implementation with the `config` package. 71 72 ### 1. Implement the `config.KVConfig` interface 73 74 The plugin currently only supports Watch and Get read operations and does not support Put and Del write operations. 75 76 ```go 77 // Client etcd client. 78 type Client struct { 79 cli *clientv3.Client 80 } 81 82 // Name returns plugin name. 83 func (c *Client) Name() string { 84 return pluginName 85 } 86 87 // Get Obtains the configuration content value according to the key, and implement the config.KV interface. 88 func (c *Client) Get(ctx context.Context, key string, _ ...config.Option) (config.Response, error) { 89 result, err := c.cli.Get(ctx, key) 90 if err != nil { 91 return nil, err 92 } 93 rsp := &getResponse{ 94 md: make(map[string]string), 95 } 96 97 if result.Count > 1 { 98 // TODO: support multi keyvalues 99 return nil, ErrNotImplemented 100 } 101 102 for _, v := range result.Kvs { 103 rsp.val = string(v.Value) 104 } 105 return rsp, nil 106 } 107 108 // Watch monitors configuration changes and implements the config.Watcher interface. 109 func (c *Client) Watch(ctx context.Context, key string, opts ...config.Option) (<-chan config.Response, error) { 110 rspCh := make(chan config.Response, 1) 111 go c.watch(ctx, key, rspCh) 112 return rspCh, nil 113 } 114 115 // watch adds watcher for etcd changes. 116 func (c *Client) watch(ctx context.Context, key string, rspCh chan config.Response) { 117 rch := c.cli.Watch(ctx, key) 118 for r := range rch { 119 for _, ev := range r.Events { 120 rsp := &watchResponse{ 121 val: string(ev.Kv.Value), 122 md: make(map[string]string), 123 eventType: config.EventTypeNull, 124 } 125 switch ev.Type { 126 case clientv3.EventTypePut: 127 rsp.eventType = config.EventTypePut 128 case clientv3.EventTypeDelete: 129 rsp.eventType = config.EventTypeDel 130 default: 131 } 132 rspCh <- rsp 133 } 134 } 135 } 136 137 // ErrNotImplemented not implemented error 138 var ErrNotImplemented = errors.New("not implemented") 139 140 // Put creates or updates the configuration content value to implement the config.KV interface. 141 func (c *Client) Put(ctx context.Context, key, val string, opts ...config.Option) error { 142 return ErrNotImplemented 143 } 144 145 // Del deletes the configuration item key and implement the config.KV interface. 146 func (c *Client) Del(ctx context.Context, key string, opts ...config.Option) error { 147 return ErrNotImplemented 148 } 149 ``` 150 151 ### 2. Register the implementation of `config.KVConfig` with the config package 152 153 The `*etcdPlugin.Setup` function has already called `config.Register` and `config.SetGlobalKV`. 154 155 ```go 156 config.SetGlobalKV(c) 157 config.Register(c) 158 ```