mirror of
https://github.com/42wim/matterbridge.git
synced 2024-11-29 14:12:02 -08:00
117 lines
2.9 KiB
Go
117 lines
2.9 KiB
Go
|
package etcd
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"github.com/xordataexchange/crypt/backend"
|
||
|
|
||
|
goetcd "github.com/coreos/etcd/client"
|
||
|
)
|
||
|
|
||
|
type Client struct {
|
||
|
client goetcd.Client
|
||
|
keysAPI goetcd.KeysAPI
|
||
|
waitIndex uint64
|
||
|
}
|
||
|
|
||
|
func New(machines []string) (*Client, error) {
|
||
|
newClient, err := goetcd.New(goetcd.Config{
|
||
|
Endpoints: machines,
|
||
|
})
|
||
|
if err != nil {
|
||
|
return nil, fmt.Errorf("creating new etcd client for crypt.backend.Client: %v", err)
|
||
|
}
|
||
|
keysAPI := goetcd.NewKeysAPI(newClient)
|
||
|
return &Client{client: newClient, keysAPI: keysAPI, waitIndex: 0}, nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) Get(key string) ([]byte, error) {
|
||
|
return c.GetWithContext(context.TODO(), key)
|
||
|
}
|
||
|
|
||
|
func (c *Client) GetWithContext(ctx context.Context, key string) ([]byte, error) {
|
||
|
resp, err := c.keysAPI.Get(ctx, key, nil)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
return []byte(resp.Node.Value), nil
|
||
|
}
|
||
|
|
||
|
func addKVPairs(node *goetcd.Node, list backend.KVPairs) backend.KVPairs {
|
||
|
if node.Dir {
|
||
|
for _, n := range node.Nodes {
|
||
|
list = addKVPairs(n, list)
|
||
|
}
|
||
|
return list
|
||
|
}
|
||
|
return append(list, &backend.KVPair{Key: node.Key, Value: []byte(node.Value)})
|
||
|
}
|
||
|
|
||
|
func (c *Client) List(key string) (backend.KVPairs, error) {
|
||
|
return c.ListWithContext(context.TODO(), key)
|
||
|
}
|
||
|
|
||
|
func (c *Client) ListWithContext(ctx context.Context, key string) (backend.KVPairs, error) {
|
||
|
resp, err := c.keysAPI.Get(ctx, key, nil)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
if !resp.Node.Dir {
|
||
|
return nil, errors.New("key is not a directory")
|
||
|
}
|
||
|
list := addKVPairs(resp.Node, nil)
|
||
|
return list, nil
|
||
|
}
|
||
|
|
||
|
func (c *Client) Set(key string, value []byte) error {
|
||
|
return c.SetWithContext(context.TODO(), key, value)
|
||
|
}
|
||
|
|
||
|
func (c *Client) SetWithContext(ctx context.Context, key string, value []byte) error {
|
||
|
_, err := c.keysAPI.Set(ctx, key, string(value), nil)
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
func (c *Client) Watch(key string, stop chan bool) <-chan *backend.Response {
|
||
|
return c.WatchWithContext(context.Background(), key, stop)
|
||
|
}
|
||
|
|
||
|
func (c *Client) WatchWithContext(ctx context.Context, key string, stop chan bool) <-chan *backend.Response {
|
||
|
respChan := make(chan *backend.Response, 0)
|
||
|
go func() {
|
||
|
watcher := c.keysAPI.Watcher(key, nil)
|
||
|
ctx, cancel := context.WithCancel(ctx)
|
||
|
go func() {
|
||
|
<-stop
|
||
|
cancel()
|
||
|
}()
|
||
|
for {
|
||
|
var resp *goetcd.Response
|
||
|
var err error
|
||
|
// if c.waitIndex == 0 {
|
||
|
// resp, err = c.client.Get(key, false, false)
|
||
|
// if err != nil {
|
||
|
// respChan <- &backend.Response{nil, err}
|
||
|
// time.Sleep(time.Second * 5)
|
||
|
// continue
|
||
|
// }
|
||
|
// c.waitIndex = resp.EtcdIndex
|
||
|
// respChan <- &backend.Response{[]byte(resp.Node.Value), nil}
|
||
|
// }
|
||
|
// resp, err = c.client.Watch(key, c.waitIndex+1, false, nil, stop)
|
||
|
resp, err = watcher.Next(ctx)
|
||
|
if err != nil {
|
||
|
respChan <- &backend.Response{nil, err}
|
||
|
time.Sleep(time.Second * 5)
|
||
|
continue
|
||
|
}
|
||
|
c.waitIndex = resp.Node.ModifiedIndex
|
||
|
respChan <- &backend.Response{[]byte(resp.Node.Value), nil}
|
||
|
}
|
||
|
}()
|
||
|
return respChan
|
||
|
}
|