gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/store/etcd/etcd.go (about)

     1  // Package etcd is an etcd v3 implementation of kv
     2  package etcd
     3  
     4  import (
     5  	"context"
     6  	"log"
     7  
     8  	client "github.com/coreos/etcd/clientv3"
     9  	"github.com/coreos/etcd/mvcc/mvccpb"
    10  	"gitee.com/liuxuezhan/go-micro-v1.18.0/config/options"
    11  	"gitee.com/liuxuezhan/go-micro-v1.18.0/store"
    12  )
    13  
    14  type ekv struct {
    15  	options.Options
    16  	kv client.KV
    17  }
    18  
    19  func (e *ekv) Read(keys ...string) ([]*store.Record, error) {
    20  	//nolint:prealloc
    21  	var values []*mvccpb.KeyValue
    22  
    23  	for _, key := range keys {
    24  		keyval, err := e.kv.Get(context.Background(), key)
    25  		if err != nil {
    26  			return nil, err
    27  		}
    28  
    29  		if keyval == nil || len(keyval.Kvs) == 0 {
    30  			return nil, store.ErrNotFound
    31  		}
    32  
    33  		values = append(values, keyval.Kvs...)
    34  	}
    35  
    36  	records := make([]*store.Record, 0, len(values))
    37  
    38  	for _, kv := range values {
    39  		records = append(records, &store.Record{
    40  			Key:   string(kv.Key),
    41  			Value: kv.Value,
    42  			// TODO: implement expiry
    43  		})
    44  	}
    45  
    46  	return records, nil
    47  }
    48  
    49  func (e *ekv) Delete(keys ...string) error {
    50  	var gerr error
    51  	for _, key := range keys {
    52  		_, err := e.kv.Delete(context.Background(), key)
    53  		if err != nil {
    54  			gerr = err
    55  		}
    56  	}
    57  	return gerr
    58  }
    59  
    60  func (e *ekv) Write(records ...*store.Record) error {
    61  	var gerr error
    62  	for _, record := range records {
    63  		// TODO create lease to expire keys
    64  		_, err := e.kv.Put(context.Background(), record.Key, string(record.Value))
    65  		if err != nil {
    66  			gerr = err
    67  		}
    68  	}
    69  	return gerr
    70  }
    71  
    72  func (e *ekv) List() ([]*store.Record, error) {
    73  	keyval, err := e.kv.Get(context.Background(), "/", client.WithPrefix())
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	if keyval == nil || len(keyval.Kvs) == 0 {
    78  		return nil, nil
    79  	}
    80  	vals := make([]*store.Record, 0, len(keyval.Kvs))
    81  	for _, keyv := range keyval.Kvs {
    82  		vals = append(vals, &store.Record{
    83  			Key:   string(keyv.Key),
    84  			Value: keyv.Value,
    85  		})
    86  	}
    87  	return vals, nil
    88  }
    89  
    90  func (e *ekv) String() string {
    91  	return "etcd"
    92  }
    93  
    94  func NewStore(opts ...options.Option) store.Store {
    95  	options := options.NewOptions(opts...)
    96  
    97  	var endpoints []string
    98  
    99  	if e, ok := options.Values().Get("store.nodes"); ok {
   100  		endpoints = e.([]string)
   101  	}
   102  
   103  	if len(endpoints) == 0 {
   104  		endpoints = []string{"http://127.0.0.1:2379"}
   105  	}
   106  
   107  	// TODO: parse addresses
   108  	c, err := client.New(client.Config{
   109  		Endpoints: endpoints,
   110  	})
   111  	if err != nil {
   112  		log.Fatal(err)
   113  	}
   114  
   115  	return &ekv{
   116  		Options: options,
   117  		kv:      client.NewKV(c),
   118  	}
   119  }