118 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package etcd is an etcd v3 implementation of kv
 | |
| package etcd
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"log"
 | |
| 
 | |
| 	client "github.com/coreos/etcd/clientv3"
 | |
| 	"github.com/micro/go-micro/store"
 | |
| )
 | |
| 
 | |
| type ekv struct {
 | |
| 	options store.Options
 | |
| 	kv      client.KV
 | |
| }
 | |
| 
 | |
| func (e *ekv) Init(opts ...store.Option) error {
 | |
| 	for _, o := range opts {
 | |
| 		o(&e.options)
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func (e *ekv) Read(key string, opts ...store.ReadOption) ([]*store.Record, error) {
 | |
| 	var options store.ReadOptions
 | |
| 	for _, o := range opts {
 | |
| 		o(&options)
 | |
| 	}
 | |
| 
 | |
| 	var etcdOpts []client.OpOption
 | |
| 
 | |
| 	// set options prefix
 | |
| 	if options.Prefix {
 | |
| 		etcdOpts = append(etcdOpts, client.WithPrefix())
 | |
| 	}
 | |
| 
 | |
| 	keyval, err := e.kv.Get(context.Background(), key, etcdOpts...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	if keyval == nil || len(keyval.Kvs) == 0 {
 | |
| 		return nil, store.ErrNotFound
 | |
| 	}
 | |
| 
 | |
| 	records := make([]*store.Record, 0, len(keyval.Kvs))
 | |
| 
 | |
| 	for _, kv := range keyval.Kvs {
 | |
| 		records = append(records, &store.Record{
 | |
| 			Key:   string(kv.Key),
 | |
| 			Value: kv.Value,
 | |
| 			// TODO: implement expiry
 | |
| 		})
 | |
| 	}
 | |
| 
 | |
| 	return records, nil
 | |
| }
 | |
| 
 | |
| func (e *ekv) Delete(key string) error {
 | |
| 	_, err := e.kv.Delete(context.Background(), key)
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| func (e *ekv) Write(record *store.Record) error {
 | |
| 	// TODO create lease to expire keys
 | |
| 	_, err := e.kv.Put(context.Background(), record.Key, string(record.Value))
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| func (e *ekv) List() ([]*store.Record, error) {
 | |
| 	keyval, err := e.kv.Get(context.Background(), "/", client.WithPrefix())
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 	if keyval == nil || len(keyval.Kvs) == 0 {
 | |
| 		return nil, nil
 | |
| 	}
 | |
| 	vals := make([]*store.Record, 0, len(keyval.Kvs))
 | |
| 	for _, keyv := range keyval.Kvs {
 | |
| 		vals = append(vals, &store.Record{
 | |
| 			Key:   string(keyv.Key),
 | |
| 			Value: keyv.Value,
 | |
| 		})
 | |
| 	}
 | |
| 	return vals, nil
 | |
| }
 | |
| 
 | |
| func (e *ekv) String() string {
 | |
| 	return "etcd"
 | |
| }
 | |
| 
 | |
| func NewStore(opts ...store.Option) store.Store {
 | |
| 	var options store.Options
 | |
| 	for _, o := range opts {
 | |
| 		o(&options)
 | |
| 	}
 | |
| 
 | |
| 	// get the endpoints
 | |
| 	endpoints := options.Nodes
 | |
| 
 | |
| 	if len(endpoints) == 0 {
 | |
| 		endpoints = []string{"http://127.0.0.1:2379"}
 | |
| 	}
 | |
| 
 | |
| 	// TODO: parse addresses
 | |
| 	c, err := client.New(client.Config{
 | |
| 		Endpoints: endpoints,
 | |
| 	})
 | |
| 	if err != nil {
 | |
| 		log.Fatal(err)
 | |
| 	}
 | |
| 
 | |
| 	return &ekv{
 | |
| 		options: options,
 | |
| 		kv:      client.NewKV(c),
 | |
| 	}
 | |
| }
 |