strip down mdns watcher
This commit is contained in:
parent
4e539361fa
commit
cf67d460b7
@ -54,6 +54,17 @@ type mdnsRegistry struct {
|
|||||||
listener chan *mdns.ServiceEntry
|
listener chan *mdns.ServiceEntry
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type mdnsWatcher struct {
|
||||||
|
id string
|
||||||
|
wo WatchOptions
|
||||||
|
ch chan *mdns.ServiceEntry
|
||||||
|
exit chan struct{}
|
||||||
|
// the mdns domain
|
||||||
|
domain string
|
||||||
|
// the registry
|
||||||
|
registry *mdnsRegistry
|
||||||
|
}
|
||||||
|
|
||||||
func encode(txt *mdnsTxt) ([]string, error) {
|
func encode(txt *mdnsTxt) ([]string, error) {
|
||||||
b, err := json.Marshal(txt)
|
b, err := json.Marshal(txt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -534,6 +545,74 @@ func (m *mdnsRegistry) String() string {
|
|||||||
return "mdns"
|
return "mdns"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *mdnsWatcher) Next() (*Result, error) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case e := <-m.ch:
|
||||||
|
txt, err := decode(e.InfoFields)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(txt.Service) == 0 || len(txt.Version) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter watch options
|
||||||
|
// wo.Service: Only keep services we care about
|
||||||
|
if len(m.wo.Service) > 0 && txt.Service != m.wo.Service {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var action string
|
||||||
|
|
||||||
|
if e.TTL == 0 {
|
||||||
|
action = "delete"
|
||||||
|
} else {
|
||||||
|
action = "create"
|
||||||
|
}
|
||||||
|
|
||||||
|
service := &Service{
|
||||||
|
Name: txt.Service,
|
||||||
|
Version: txt.Version,
|
||||||
|
Endpoints: txt.Endpoints,
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip anything without the domain we care about
|
||||||
|
suffix := fmt.Sprintf(".%s.%s.", service.Name, m.domain)
|
||||||
|
if !strings.HasSuffix(e.Name, suffix) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
service.Nodes = append(service.Nodes, &Node{
|
||||||
|
Id: strings.TrimSuffix(e.Name, suffix),
|
||||||
|
Address: fmt.Sprintf("%s:%d", e.AddrV4.String(), e.Port),
|
||||||
|
Metadata: txt.Metadata,
|
||||||
|
})
|
||||||
|
|
||||||
|
return &Result{
|
||||||
|
Action: action,
|
||||||
|
Service: service,
|
||||||
|
}, nil
|
||||||
|
case <-m.exit:
|
||||||
|
return nil, ErrWatcherStopped
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *mdnsWatcher) Stop() {
|
||||||
|
select {
|
||||||
|
case <-m.exit:
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
close(m.exit)
|
||||||
|
// remove self from the registry
|
||||||
|
m.registry.mtx.Lock()
|
||||||
|
delete(m.registry.watchers, m.id)
|
||||||
|
m.registry.mtx.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NewRegistry returns a new default registry which is mdns
|
// NewRegistry returns a new default registry which is mdns
|
||||||
func NewRegistry(opts ...Option) Registry {
|
func NewRegistry(opts ...Option) Registry {
|
||||||
return newRegistry(opts...)
|
return newRegistry(opts...)
|
||||||
|
@ -197,3 +197,145 @@ func TestEncoding(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWatcher(t *testing.T) {
|
||||||
|
if travis := os.Getenv("TRAVIS"); travis == "true" {
|
||||||
|
t.Skip()
|
||||||
|
}
|
||||||
|
|
||||||
|
testData := []*Service{
|
||||||
|
{
|
||||||
|
Name: "test1",
|
||||||
|
Version: "1.0.1",
|
||||||
|
Nodes: []*Node{
|
||||||
|
{
|
||||||
|
Id: "test1-1",
|
||||||
|
Address: "10.0.0.1:10001",
|
||||||
|
Metadata: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "test2",
|
||||||
|
Version: "1.0.2",
|
||||||
|
Nodes: []*Node{
|
||||||
|
{
|
||||||
|
Id: "test2-1",
|
||||||
|
Address: "10.0.0.2:10002",
|
||||||
|
Metadata: map[string]string{
|
||||||
|
"foo2": "bar2",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "test3",
|
||||||
|
Version: "1.0.3",
|
||||||
|
Nodes: []*Node{
|
||||||
|
{
|
||||||
|
Id: "test3-1",
|
||||||
|
Address: "10.0.0.3:10003",
|
||||||
|
Metadata: map[string]string{
|
||||||
|
"foo3": "bar3",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
testFn := func(service, s *Service) {
|
||||||
|
if s == nil {
|
||||||
|
t.Fatalf("Expected one result for %s got nil", service.Name)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Name != service.Name {
|
||||||
|
t.Fatalf("Expected name %s got %s", service.Name, s.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Version != service.Version {
|
||||||
|
t.Fatalf("Expected version %s got %s", service.Version, s.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.Nodes) != 1 {
|
||||||
|
t.Fatalf("Expected 1 node, got %d", len(s.Nodes))
|
||||||
|
}
|
||||||
|
|
||||||
|
node := s.Nodes[0]
|
||||||
|
|
||||||
|
if node.Id != service.Nodes[0].Id {
|
||||||
|
t.Fatalf("Expected node id %s got %s", service.Nodes[0].Id, node.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if node.Address != service.Nodes[0].Address {
|
||||||
|
t.Fatalf("Expected node address %s got %s", service.Nodes[0].Address, node.Address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
travis := os.Getenv("TRAVIS")
|
||||||
|
|
||||||
|
var opts []Option
|
||||||
|
|
||||||
|
if travis == "true" {
|
||||||
|
opts = append(opts, Timeout(time.Millisecond*100))
|
||||||
|
}
|
||||||
|
|
||||||
|
// new registry
|
||||||
|
r := NewRegistry(opts...)
|
||||||
|
|
||||||
|
w, err := r.Watch()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer w.Stop()
|
||||||
|
|
||||||
|
for _, service := range testData {
|
||||||
|
// register service
|
||||||
|
if err := r.Register(service); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
res, err := w.Next()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Service.Name != service.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Action != "create" {
|
||||||
|
t.Fatalf("Expected create event got %s for %s", res.Action, res.Service.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
testFn(service, res.Service)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// deregister
|
||||||
|
if err := r.Deregister(service); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
res, err := w.Next()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Service.Name != service.Name {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if res.Action != "delete" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
testFn(service, res.Service)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,87 +0,0 @@
|
|||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/micro/go-micro/v2/util/mdns"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mdnsWatcher struct {
|
|
||||||
id string
|
|
||||||
wo WatchOptions
|
|
||||||
ch chan *mdns.ServiceEntry
|
|
||||||
exit chan struct{}
|
|
||||||
// the mdns domain
|
|
||||||
domain string
|
|
||||||
// the registry
|
|
||||||
registry *mdnsRegistry
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mdnsWatcher) Next() (*Result, error) {
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case e := <-m.ch:
|
|
||||||
txt, err := decode(e.InfoFields)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(txt.Service) == 0 || len(txt.Version) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter watch options
|
|
||||||
// wo.Service: Only keep services we care about
|
|
||||||
if len(m.wo.Service) > 0 && txt.Service != m.wo.Service {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var action string
|
|
||||||
|
|
||||||
if e.TTL == 0 {
|
|
||||||
action = "delete"
|
|
||||||
} else {
|
|
||||||
action = "create"
|
|
||||||
}
|
|
||||||
|
|
||||||
service := &Service{
|
|
||||||
Name: txt.Service,
|
|
||||||
Version: txt.Version,
|
|
||||||
Endpoints: txt.Endpoints,
|
|
||||||
}
|
|
||||||
|
|
||||||
// skip anything without the domain we care about
|
|
||||||
suffix := fmt.Sprintf(".%s.%s.", service.Name, m.domain)
|
|
||||||
if !strings.HasSuffix(e.Name, suffix) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
service.Nodes = append(service.Nodes, &Node{
|
|
||||||
Id: strings.TrimSuffix(e.Name, suffix),
|
|
||||||
Address: fmt.Sprintf("%s:%d", e.AddrV4.String(), e.Port),
|
|
||||||
Metadata: txt.Metadata,
|
|
||||||
})
|
|
||||||
|
|
||||||
return &Result{
|
|
||||||
Action: action,
|
|
||||||
Service: service,
|
|
||||||
}, nil
|
|
||||||
case <-m.exit:
|
|
||||||
return nil, ErrWatcherStopped
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mdnsWatcher) Stop() {
|
|
||||||
select {
|
|
||||||
case <-m.exit:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
close(m.exit)
|
|
||||||
// remove self from the registry
|
|
||||||
m.registry.mtx.Lock()
|
|
||||||
delete(m.registry.watchers, m.id)
|
|
||||||
m.registry.mtx.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,149 +0,0 @@
|
|||||||
package registry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestWatcher(t *testing.T) {
|
|
||||||
if travis := os.Getenv("TRAVIS"); travis == "true" {
|
|
||||||
t.Skip()
|
|
||||||
}
|
|
||||||
|
|
||||||
testData := []*Service{
|
|
||||||
{
|
|
||||||
Name: "test1",
|
|
||||||
Version: "1.0.1",
|
|
||||||
Nodes: []*Node{
|
|
||||||
{
|
|
||||||
Id: "test1-1",
|
|
||||||
Address: "10.0.0.1:10001",
|
|
||||||
Metadata: map[string]string{
|
|
||||||
"foo": "bar",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "test2",
|
|
||||||
Version: "1.0.2",
|
|
||||||
Nodes: []*Node{
|
|
||||||
{
|
|
||||||
Id: "test2-1",
|
|
||||||
Address: "10.0.0.2:10002",
|
|
||||||
Metadata: map[string]string{
|
|
||||||
"foo2": "bar2",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Name: "test3",
|
|
||||||
Version: "1.0.3",
|
|
||||||
Nodes: []*Node{
|
|
||||||
{
|
|
||||||
Id: "test3-1",
|
|
||||||
Address: "10.0.0.3:10003",
|
|
||||||
Metadata: map[string]string{
|
|
||||||
"foo3": "bar3",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
testFn := func(service, s *Service) {
|
|
||||||
if s == nil {
|
|
||||||
t.Fatalf("Expected one result for %s got nil", service.Name)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Name != service.Name {
|
|
||||||
t.Fatalf("Expected name %s got %s", service.Name, s.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Version != service.Version {
|
|
||||||
t.Fatalf("Expected version %s got %s", service.Version, s.Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(s.Nodes) != 1 {
|
|
||||||
t.Fatalf("Expected 1 node, got %d", len(s.Nodes))
|
|
||||||
}
|
|
||||||
|
|
||||||
node := s.Nodes[0]
|
|
||||||
|
|
||||||
if node.Id != service.Nodes[0].Id {
|
|
||||||
t.Fatalf("Expected node id %s got %s", service.Nodes[0].Id, node.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if node.Address != service.Nodes[0].Address {
|
|
||||||
t.Fatalf("Expected node address %s got %s", service.Nodes[0].Address, node.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
travis := os.Getenv("TRAVIS")
|
|
||||||
|
|
||||||
var opts []Option
|
|
||||||
|
|
||||||
if travis == "true" {
|
|
||||||
opts = append(opts, Timeout(time.Millisecond*100))
|
|
||||||
}
|
|
||||||
|
|
||||||
// new registry
|
|
||||||
r := NewRegistry(opts...)
|
|
||||||
|
|
||||||
w, err := r.Watch()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer w.Stop()
|
|
||||||
|
|
||||||
for _, service := range testData {
|
|
||||||
// register service
|
|
||||||
if err := r.Register(service); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
res, err := w.Next()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Service.Name != service.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Action != "create" {
|
|
||||||
t.Fatalf("Expected create event got %s for %s", res.Action, res.Service.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
testFn(service, res.Service)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// deregister
|
|
||||||
if err := r.Deregister(service); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
res, err := w.Next()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Service.Name != service.Name {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.Action != "delete" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
testFn(service, res.Service)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user