mirror of https://github.com/docker/docs.git
Remove Hub
Signed-off-by: Solomon Hykes <solomon@docker.com>
This commit is contained in:
parent
91c9eec591
commit
56ee97a572
|
@ -1,116 +0,0 @@
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/docker/libswarm/beam"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Hub passes messages to dynamically registered handlers.
|
|
||||||
type Hub struct {
|
|
||||||
handlers *StackSender
|
|
||||||
tasks sync.WaitGroup
|
|
||||||
l sync.RWMutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewHub() *Hub {
|
|
||||||
return &Hub{
|
|
||||||
handlers: NewStackSender(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hub *Hub) Send(msg *beam.Message) (ret beam.Receiver, err error) {
|
|
||||||
if msg.Name == "register" {
|
|
||||||
if msg.Ret == nil {
|
|
||||||
return nil, fmt.Errorf("register: no return channel")
|
|
||||||
}
|
|
||||||
fmt.Printf("[hub] received %v\n", msg)
|
|
||||||
hIn := msg.Ret
|
|
||||||
if hIn == beam.RetPipe {
|
|
||||||
ret, hIn = beam.Pipe()
|
|
||||||
}
|
|
||||||
// This queue guarantees that the first message received by the handler
|
|
||||||
// is the "register" response.
|
|
||||||
hIn = NewQueue(hIn, 1)
|
|
||||||
// Reply to the handler with a "register" call of our own,
|
|
||||||
// passing a reference to the previous handler stack.
|
|
||||||
// This allows the new handler to query previous handlers
|
|
||||||
// without creating loops.
|
|
||||||
hOut, err := hIn.Send(&beam.Message{Name: "register", Ret: beam.RetPipe})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Register the new handler on top of the others,
|
|
||||||
// and get a reference to the previous stack of handlers.
|
|
||||||
prevHandlers := hub.handlers.Add(hIn)
|
|
||||||
go beam.Copy(prevHandlers, hOut)
|
|
||||||
return ret, nil
|
|
||||||
}
|
|
||||||
fmt.Printf("sending %#v to %d handlers\n", msg, hub.handlers.Len())
|
|
||||||
return hub.handlers.Send(msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hub *Hub) RegisterTask(h func(beam.Receiver, beam.Sender) error) error {
|
|
||||||
ret, err := hub.Send(&beam.Message{Name: "register", Ret: beam.RetPipe})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ack, err := ret.Receive(beam.Ret)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if ack.Name == "error" {
|
|
||||||
return fmt.Errorf(strings.Join(ack.Args, ", "))
|
|
||||||
}
|
|
||||||
if ack.Name != "register" {
|
|
||||||
return fmt.Errorf("invalid response: expected verb 'register', got '%v'", ack.Name)
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
h(ret, ack.Ret)
|
|
||||||
ack.Ret.Close()
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type Handler func(msg *beam.Message, out beam.Sender) (pass bool, err error)
|
|
||||||
|
|
||||||
func (hub *Hub) RegisterName(name string, h Handler) error {
|
|
||||||
return hub.RegisterTask(func(in beam.Receiver, out beam.Sender) error {
|
|
||||||
for {
|
|
||||||
msg, err := in.Receive(beam.Ret)
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var pass = true
|
|
||||||
if msg.Name == name || name == "" {
|
|
||||||
pass, err = h(msg, out)
|
|
||||||
if err != nil {
|
|
||||||
if _, err := msg.Ret.Send(&beam.Message{Name: "error", Args: []string{err.Error()}}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if pass {
|
|
||||||
if _, err := out.Send(msg); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg.Ret.Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hub *Hub) Wait() {
|
|
||||||
hub.tasks.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (hub *Hub) Close() error {
|
|
||||||
return hub.handlers.Close()
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package utils
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/docker/libswarm/beam"
|
|
||||||
"github.com/dotcloud/docker/pkg/testutils"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestHubSendEmpty(t *testing.T) {
|
|
||||||
hub := NewHub()
|
|
||||||
// Send to empty hub should silently drop
|
|
||||||
ret, err := hub.Send(&beam.Message{Name: "hello", Args: nil, Ret: beam.RetPipe})
|
|
||||||
// Send must not return an error
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
// We set beam.R, so a valid return pipe must be returned
|
|
||||||
if ret == nil {
|
|
||||||
t.Fatalf("%#v", ret)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type CountSender int
|
|
||||||
|
|
||||||
func (s *CountSender) Send(msg *beam.Message) (beam.Receiver, error) {
|
|
||||||
(*s)++
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHubSendOneHandler(t *testing.T) {
|
|
||||||
hub := NewHub()
|
|
||||||
defer hub.Close()
|
|
||||||
testutils.Timeout(t, func() {
|
|
||||||
handlerIn, err := hub.Send(&beam.Message{Name: "register", Args: nil, Ret: beam.RetPipe})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
ack, err := handlerIn.Receive(beam.Ret)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if ack.Name != "register" {
|
|
||||||
t.Fatalf("%#v", err)
|
|
||||||
}
|
|
||||||
handlerOut := ack.Ret
|
|
||||||
if handlerOut == nil {
|
|
||||||
t.Fatalf("nil handler out")
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
if _, err := hub.Send(&beam.Message{Name: "hello", Args: nil}); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
msg, err := handlerIn.Receive(0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if msg.Name != "hello" {
|
|
||||||
t.Fatalf("%#v", msg)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
Loading…
Reference in New Issue