service-discovery/discovery.go

128 lines
2.5 KiB
Go
Raw Normal View History

2020-10-11 10:35:18 +00:00
package discovery
import (
2022-11-25 11:11:24 +00:00
"context"
"encoding/json"
"github.com/google/uuid"
"go.etcd.io/etcd/client/v3"
"path"
2020-10-11 10:35:18 +00:00
)
type Registry struct {
2022-11-25 11:11:24 +00:00
client *clientv3.Client
path string
2020-10-11 10:35:18 +00:00
}
func New(endpoints []string) (*Registry, error) {
2022-11-25 11:11:24 +00:00
client, err := clientv3.New(clientv3.Config{
Endpoints: endpoints,
})
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err != nil {
return nil, err
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
return &Registry{
client: client,
}, nil
2020-10-11 10:35:18 +00:00
}
func (r *Registry) Register(ctx context.Context, service string, host Host) error {
2022-11-25 11:11:24 +00:00
resp, err := r.client.Grant(context.Background(), 30)
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err != nil {
return err
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if host.UUID == "" {
host.UUID = uuid.New().String()
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
b, err := json.Marshal(host)
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err != nil {
return err
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
key := path.Join(r.path, service, host.UUID)
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
_, err = r.client.Put(context.Background(), key, string(b), clientv3.WithLease(resp.ID))
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err != nil {
return err
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
ch, err := r.client.KeepAlive(ctx, resp.ID)
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err != nil {
return err
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
go func() {
for {
select {
case ka := <-ch:
if ka == nil {
return
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
// Removed
}
}
}()
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
return nil
2020-10-11 10:35:18 +00:00
}
func (r *Registry) Get(service string) ([]Host, error) {
2022-11-25 11:11:24 +00:00
res, err := r.client.Get(context.Background(), path.Join(r.path, service), clientv3.WithPrefix())
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err != nil {
return nil, err
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
var host Host
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
hosts := make([]Host, len(res.Kvs))
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
for i, kv := range res.Kvs {
host = Host{}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
if err = json.Unmarshal(kv.Value, &host); err != nil {
continue
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
hosts[i] = host
}
2020-10-11 10:35:18 +00:00
2022-11-25 11:11:24 +00:00
return hosts, nil
2020-10-11 10:35:18 +00:00
}
func (r *Registry) Watch(service string) (chan Host, chan string) {
2022-11-25 11:11:24 +00:00
ch := r.client.Watch(context.Background(), path.Join(r.path, service), clientv3.WithPrefix())
upChan := make(chan Host)
downChan := make(chan string)
go func() {
for resp := range ch {
for _, e := range resp.Events {
if e.Type == clientv3.EventTypeDelete {
// Removed
downChan <- string(e.Kv.Key)
} else if e.IsCreate() || e.IsModify() {
host := Host{}
if err := json.Unmarshal(e.Kv.Value, &host); err != nil {
continue
}
upChan <- host
}
}
}
}()
return upChan, downChan
2020-10-11 10:35:18 +00:00
}