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  ```