Change receiver to handler, breaking change, grrr

This commit is contained in:
Asim 2015-06-03 01:25:37 +01:00
parent 8cdc2b5f82
commit cdf2f2cbcd
13 changed files with 325 additions and 144 deletions

View File

@ -107,8 +107,8 @@ func main() {
) )
// Register Handlers // Register Handlers
server.Register( server.Handle(
server.NewReceiver( server.NewHandler(
new(handler.Example), new(handler.Example),
), ),
) )

View File

@ -17,8 +17,8 @@ func main() {
) )
// Register Handlers // Register Handlers
server.Register( server.Handle(
server.NewReceiver( server.NewHandler(
new(handler.Example), new(handler.Example),
), ),
) )

View File

@ -12,19 +12,6 @@ type Watcher interface {
Stop() Stop()
} }
type Service struct {
Name string
Metadata map[string]string
Nodes []*Node
}
type Node struct {
Id string
Address string
Port int
Metadata map[string]string
}
type options struct{} type options struct{}
type Option func(*options) type Option func(*options)

28
registry/service.go Normal file
View File

@ -0,0 +1,28 @@
package registry
type Service struct {
Name string
Version string
Metadata map[string]string
Endpoints []*Endpoint
Nodes []*Node
}
type Node struct {
Id string
Address string
Port int
Metadata map[string]string
}
type Endpoint struct {
Name string
Request *Value
Response *Value
}
type Value struct {
Name string
Type string
Values []*Value
}

66
server/extractor.go Normal file
View File

@ -0,0 +1,66 @@
package server
import (
"reflect"
"github.com/myodc/go-micro/registry"
)
func extractValue(v reflect.Type) *registry.Value {
if v == nil {
return nil
}
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
arg := &registry.Value{
Name: v.Name(),
Type: v.Name(),
}
if v.Kind() == reflect.Struct {
for i := 0; i < v.NumField(); i++ {
val := extractValue(v.Field(i).Type)
val.Name = v.Field(i).Name
arg.Values = append(arg.Values, val)
}
}
return arg
}
func extractEndpoint(method reflect.Method) *registry.Endpoint {
if method.PkgPath != "" {
return nil
}
var rspType, reqType reflect.Type
// var stream bool
mt := method.Type
switch mt.NumIn() {
case 3:
reqType = mt.In(1)
rspType = mt.In(2)
case 4:
reqType = mt.In(2)
rspType = mt.In(3)
default:
return nil
}
// if rspType.Kind() == reflect.Func {
// stream = true
// }
request := extractValue(reqType)
response := extractValue(rspType)
return &registry.Endpoint{
Name: method.Name,
Request: request,
Response: response,
}
}

11
server/handler.go Normal file
View File

@ -0,0 +1,11 @@
package server
import (
"github.com/myodc/go-micro/registry"
)
type Handler interface {
Name() string
Handler() interface{}
Endpoints() []*registry.Endpoint
}

View File

@ -12,6 +12,6 @@ func (d *Debug) Health(ctx context.Context, req *health.Request, rsp *health.Res
return nil return nil
} }
func registerHealthChecker(r Server) { func registerHealthChecker(s Server) {
r.Register(r.NewReceiver(&Debug{})) s.Handle(s.NewHandler(&Debug{}))
} }

View File

@ -12,6 +12,7 @@ type options struct {
name string name string
address string address string
id string id string
version string
} }
func newOptions(opt ...Option) options { func newOptions(opt ...Option) options {
@ -41,6 +42,10 @@ func newOptions(opt ...Option) options {
opts.id = DefaultId opts.id = DefaultId
} }
if len(opts.version) == 0 {
opts.version = DefaultVersion
}
return opts return opts
} }
@ -52,6 +57,10 @@ func (o options) Id() string {
return o.name + "-" + o.id return o.name + "-" + o.id
} }
func (o options) Version() string {
return o.version
}
func (o options) Address() string { func (o options) Address() string {
return o.address return o.address
} }
@ -59,3 +68,45 @@ func (o options) Address() string {
func (o options) Metadata() map[string]string { func (o options) Metadata() map[string]string {
return o.metadata return o.metadata
} }
func Name(n string) Option {
return func(o *options) {
o.name = n
}
}
func Id(id string) Option {
return func(o *options) {
o.id = id
}
}
func Version(v string) Option {
return func(o *options) {
o.version = v
}
}
func Address(a string) Option {
return func(o *options) {
o.address = a
}
}
func Registry(r registry.Registry) Option {
return func(o *options) {
o.registry = r
}
}
func Transport(t transport.Transport) Option {
return func(o *options) {
o.transport = t
}
}
func Metadata(md map[string]string) Option {
return func(o *options) {
o.metadata = md
}
}

View File

@ -1,6 +0,0 @@
package server
type Receiver interface {
Name() string
Handler() interface{}
}

45
server/rpc_handler.go Normal file
View File

@ -0,0 +1,45 @@
package server
import (
"reflect"
"github.com/myodc/go-micro/registry"
)
type rpcHandler struct {
name string
handler interface{}
endpoints []*registry.Endpoint
}
func newRpcHandler(handler interface{}) Handler {
typ := reflect.TypeOf(handler)
hdlr := reflect.ValueOf(handler)
name := reflect.Indirect(hdlr).Type().Name()
var endpoints []*registry.Endpoint
for m := 0; m < typ.NumMethod(); m++ {
if e := extractEndpoint(typ.Method(m)); e != nil {
endpoints = append(endpoints, e)
}
}
return &rpcHandler{
name: name,
handler: handler,
endpoints: endpoints,
}
}
func (r *rpcHandler) Name() string {
return r.name
}
func (r *rpcHandler) Handler() interface{} {
return r.handler
}
func (r *rpcHandler) Endpoints() []*registry.Endpoint {
return r.endpoints
}

View File

@ -1,21 +0,0 @@
package server
type rpcReceiver struct {
name string
handler interface{}
}
func newRpcReceiver(name string, handler interface{}) Receiver {
return &rpcReceiver{
name: name,
handler: handler,
}
}
func (r *rpcReceiver) Name() string {
return r.name
}
func (r *rpcReceiver) Handler() interface{} {
return r.handler
}

View File

@ -1,7 +1,12 @@
package server package server
import ( import (
"strconv"
"strings"
"sync"
c "github.com/myodc/go-micro/context" c "github.com/myodc/go-micro/context"
"github.com/myodc/go-micro/registry"
"github.com/myodc/go-micro/transport" "github.com/myodc/go-micro/transport"
log "github.com/golang/glog" log "github.com/golang/glog"
@ -11,15 +16,19 @@ import (
) )
type rpcServer struct { type rpcServer struct {
opts options
rpc *rpc.Server rpc *rpc.Server
exit chan chan error exit chan chan error
sync.RWMutex
opts options
handlers map[string]Handler
} }
func newRpcServer(opts ...Option) Server { func newRpcServer(opts ...Option) Server {
return &rpcServer{ return &rpcServer{
opts: newOptions(opts...), opts: newOptions(opts...),
rpc: rpc.NewServer(), rpc: rpc.NewServer(),
handlers: make(map[string]Handler),
exit: make(chan chan error), exit: make(chan chan error),
} }
} }
@ -44,47 +53,116 @@ func (s *rpcServer) accept(sock transport.Socket) {
} }
func (s *rpcServer) Config() options { func (s *rpcServer) Config() options {
return s.opts s.RLock()
opts := s.opts
s.RUnlock()
return opts
} }
func (s *rpcServer) Init(opts ...Option) { func (s *rpcServer) Init(opts ...Option) {
s.Lock()
for _, opt := range opts { for _, opt := range opts {
opt(&s.opts) opt(&s.opts)
} }
if len(s.opts.id) == 0 { if len(s.opts.id) == 0 {
s.opts.id = s.opts.name + "-" + DefaultId s.opts.id = s.opts.name + "-" + DefaultId
} }
s.Unlock()
} }
func (s *rpcServer) NewReceiver(handler interface{}) Receiver { func (s *rpcServer) NewHandler(h interface{}) Handler {
return newRpcReceiver("", handler) return newRpcHandler(h)
} }
func (s *rpcServer) NewNamedReceiver(name string, handler interface{}) Receiver { func (s *rpcServer) Handle(h Handler) error {
return newRpcReceiver(name, handler) if err := s.rpc.Register(h.Handler()); err != nil {
} return err
}
func (s *rpcServer) Register(r Receiver) error { s.Lock()
if len(r.Name()) > 0 { s.handlers[h.Name()] = h
s.rpc.RegisterName(r.Name(), r.Handler()) s.Unlock()
return nil return nil
}
func (s *rpcServer) Register() error {
// parse address for host, port
config := s.Config()
var host string
var port int
parts := strings.Split(config.Address(), ":")
if len(parts) > 1 {
host = strings.Join(parts[:len(parts)-1], ":")
port, _ = strconv.Atoi(parts[len(parts)-1])
} else {
host = parts[0]
} }
s.rpc.Register(r.Handler()) // register service
return nil node := &registry.Node{
Id: config.Id(),
Address: host,
Port: port,
Metadata: config.Metadata(),
}
s.RLock()
var endpoints []*registry.Endpoint
for _, e := range s.handlers {
endpoints = append(endpoints, e.Endpoints()...)
}
s.RUnlock()
service := &registry.Service{
Name: config.Name(),
Version: config.Version(),
Nodes: []*registry.Node{node},
Endpoints: endpoints,
}
log.Infof("Registering node: %s", node.Id)
return config.registry.Register(service)
}
func (s *rpcServer) Deregister() error {
config := s.Config()
var host string
var port int
parts := strings.Split(config.Address(), ":")
if len(parts) > 1 {
host = strings.Join(parts[:len(parts)-1], ":")
port, _ = strconv.Atoi(parts[len(parts)-1])
} else {
host = parts[0]
}
node := &registry.Node{
Id: config.Id(),
Address: host,
Port: port,
}
service := &registry.Service{
Name: config.Name(),
Version: config.Version(),
Nodes: []*registry.Node{node},
}
return config.registry.Deregister(service)
} }
func (s *rpcServer) Start() error { func (s *rpcServer) Start() error {
registerHealthChecker(s) registerHealthChecker(s)
config := s.Config()
ts, err := s.opts.transport.Listen(s.opts.address) ts, err := config.transport.Listen(s.opts.address)
if err != nil { if err != nil {
return err return err
} }
log.Infof("Listening on %s", ts.Addr()) log.Infof("Listening on %s", ts.Addr())
s.Lock()
s.opts.address = ts.Addr() s.opts.address = ts.Addr()
s.Unlock()
go ts.Accept(s.accept) go ts.Accept(s.accept)

View File

@ -3,22 +3,19 @@ package server
import ( import (
"os" "os"
"os/signal" "os/signal"
"strconv"
"strings"
"syscall" "syscall"
"code.google.com/p/go-uuid/uuid" "code.google.com/p/go-uuid/uuid"
log "github.com/golang/glog" log "github.com/golang/glog"
"github.com/myodc/go-micro/registry"
"github.com/myodc/go-micro/transport"
) )
type Server interface { type Server interface {
Config() options Config() options
Init(...Option) Init(...Option)
NewReceiver(interface{}) Receiver Handle(Handler) error
NewNamedReceiver(string, interface{}) Receiver NewHandler(interface{}) Handler
Register(Receiver) error Register() error
Deregister() error
Start() error Start() error
Stop() error Stop() error
} }
@ -28,46 +25,11 @@ type Option func(*options)
var ( var (
DefaultAddress = ":0" DefaultAddress = ":0"
DefaultName = "go-server" DefaultName = "go-server"
DefaultVersion = "1.0.0"
DefaultId = uuid.NewUUID().String() DefaultId = uuid.NewUUID().String()
DefaultServer Server = newRpcServer() DefaultServer Server = newRpcServer()
) )
func Name(n string) Option {
return func(o *options) {
o.name = n
}
}
func Id(id string) Option {
return func(o *options) {
o.id = id
}
}
func Address(a string) Option {
return func(o *options) {
o.address = a
}
}
func Registry(r registry.Registry) Option {
return func(o *options) {
o.registry = r
}
}
func Transport(t transport.Transport) Option {
return func(o *options) {
o.transport = t
}
}
func Metadata(md map[string]string) Option {
return func(o *options) {
o.metadata = md
}
}
func Config() options { func Config() options {
return DefaultServer.Config() return DefaultServer.Config()
} }
@ -83,16 +45,20 @@ func NewServer(opt ...Option) Server {
return newRpcServer(opt...) return newRpcServer(opt...)
} }
func NewReceiver(handler interface{}) Receiver { func NewHandler(h interface{}) Handler {
return DefaultServer.NewReceiver(handler) return DefaultServer.NewHandler(h)
} }
func NewNamedReceiver(path string, handler interface{}) Receiver { func Handle(h Handler) error {
return DefaultServer.NewNamedReceiver(path, handler) return DefaultServer.Handle(h)
} }
func Register(r Receiver) error { func Register() error {
return DefaultServer.Register(r) return DefaultServer.Register()
}
func Deregister() error {
return DefaultServer.Deregister()
} }
func Run() error { func Run() error {
@ -100,44 +66,20 @@ func Run() error {
return err return err
} }
// parse address for host, port if err := DefaultServer.Register(); err != nil {
config := DefaultServer.Config() return err
var host string
var port int
parts := strings.Split(config.Address(), ":")
if len(parts) > 1 {
host = strings.Join(parts[:len(parts)-1], ":")
port, _ = strconv.Atoi(parts[len(parts)-1])
} else {
host = parts[0]
}
// register service
node := &registry.Node{
Id: config.Id(),
Address: host,
Port: port,
Metadata: config.Metadata(),
}
service := &registry.Service{
Name: config.Name(),
Nodes: []*registry.Node{node},
}
log.Infof("Registering node: %s", node.Id)
err := config.registry.Register(service)
if err != nil {
log.Fatalf("Failed to register: %v", err)
} }
ch := make(chan os.Signal, 1) ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL) signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
log.Infof("Received signal %s", <-ch) log.Infof("Received signal %s", <-ch)
log.Infof("Deregistering %s", node.Id) if err := DefaultServer.Deregister(); err != nil {
config.registry.Deregister(service) return err
}
log.Infof("Deregistering %s", DefaultServer.Config().Id())
DefaultServer.Deregister()
return Stop() return Stop()
} }