Send Request and Publication types

This commit is contained in:
Asim 2015-12-02 20:56:50 +00:00
parent 4b18b779aa
commit a695e10d21
7 changed files with 103 additions and 21 deletions

View File

@ -10,8 +10,8 @@ import (
)
func logWrapper(fn server.HandlerFunc) server.HandlerFunc {
return func(ctx context.Context, req interface{}, rsp interface{}) error {
log.Infof("[Log Wrapper] Before serving request")
return func(ctx context.Context, req server.Request, rsp interface{}) error {
log.Infof("[Log Wrapper] Before serving request method: %v", req.Method())
err := fn(ctx, req, rsp)
log.Infof("[Log Wrapper] After serving request")
return err
@ -19,8 +19,8 @@ func logWrapper(fn server.HandlerFunc) server.HandlerFunc {
}
func logSubWrapper(fn server.SubscriberFunc) server.SubscriberFunc {
return func(ctx context.Context, req interface{}) error {
log.Infof("[Log Sub Wrapper] Before serving publication")
return func(ctx context.Context, req server.Publication) error {
log.Infof("[Log Sub Wrapper] Before serving publication topic: %v", req.Topic())
err := fn(ctx, req)
log.Infof("[Log Sub Wrapper] After serving publication")
return err

47
server/rpc_request.go Normal file
View File

@ -0,0 +1,47 @@
package server
type rpcRequest struct {
service string
method string
contentType string
request interface{}
stream bool
}
type rpcPublication struct {
topic string
contentType string
message interface{}
}
func (r *rpcRequest) ContentType() string {
return r.contentType
}
func (r *rpcRequest) Service() string {
return r.service
}
func (r *rpcRequest) Method() string {
return r.method
}
func (r *rpcRequest) Request() interface{} {
return r.request
}
func (r *rpcRequest) Stream() bool {
return r.stream
}
func (r *rpcPublication) ContentType() string {
return r.contentType
}
func (r *rpcPublication) Topic() string {
return r.topic
}
func (r *rpcPublication) Message() interface{} {
return r.message
}

View File

@ -32,6 +32,7 @@ func newRpcServer(opts ...Option) Server {
return &rpcServer{
opts: options,
rpc: &server{
name: options.name,
serviceMap: make(map[string]*service),
wrappers: options.wrappers,
},
@ -47,7 +48,8 @@ func (s *rpcServer) accept(sock transport.Socket) {
return
}
cf, err := s.newCodec(msg.Header["Content-Type"])
ct := msg.Header["Content-Type"]
cf, err := s.newCodec(ct)
// TODO: needs better error handling
if err != nil {
sock.Send(&transport.Message{
@ -70,8 +72,9 @@ func (s *rpcServer) accept(sock transport.Socket) {
delete(hdr, "Content-Type")
ctx := c.WithMetadata(context.Background(), hdr)
// TODO: needs better error handling
if err := s.rpc.serveRequest(ctx, codec); err != nil {
if err := s.rpc.serveRequest(ctx, codec, ct); err != nil {
log.Errorf("Unexpected error serving request, closing socket: %v", err)
sock.Close()
}

View File

@ -69,6 +69,7 @@ type response struct {
// server represents an RPC Server.
type server struct {
name string
mu sync.Mutex // protects the serviceMap
serviceMap map[string]*service
reqLock sync.Mutex // protects freeReq
@ -229,16 +230,23 @@ func (server *server) sendResponse(sending *sync.Mutex, req *request, reply inte
return err
}
func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec serverCodec) {
func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex, mtype *methodType, req *request, argv, replyv reflect.Value, codec serverCodec, ct string) {
mtype.Lock()
mtype.numCalls++
mtype.Unlock()
function := mtype.method.Func
var returnValues []reflect.Value
r := &rpcRequest{
service: s.name,
contentType: ct,
method: req.ServiceMethod,
request: argv.Interface(),
}
if !mtype.stream {
fn := func(ctx context.Context, req interface{}, rsp interface{}) error {
returnValues = function.Call([]reflect.Value{s.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(req), reflect.ValueOf(rsp)})
fn := func(ctx context.Context, req Request, rsp interface{}) error {
returnValues = function.Call([]reflect.Value{s.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(req.Request()), reflect.ValueOf(rsp)})
// The return value for the method is an error.
if err := returnValues[0].Interface(); err != nil {
@ -253,11 +261,12 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex,
}
errmsg := ""
err := fn(ctx, argv.Interface(), replyv.Interface())
err := fn(ctx, r, replyv.Interface())
if err != nil {
errmsg = err.Error()
}
server.sendResponse(sending, req, replyv.Interface(), codec, errmsg, true)
server.freeRequest(req)
return
@ -299,8 +308,8 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex,
}
// Invoke the method, providing a new value for the reply.
fn := func(ctx context.Context, req interface{}, rspFn interface{}) error {
returnValues = function.Call([]reflect.Value{s.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(req), reflect.ValueOf(rspFn)})
fn := func(ctx context.Context, req Request, rspFn interface{}) error {
returnValues = function.Call([]reflect.Value{s.rcvr, mtype.prepareContext(ctx), reflect.ValueOf(req.Request()), reflect.ValueOf(rspFn)})
if err := returnValues[0].Interface(); err != nil {
// the function returned an error, we use that
return err.(error)
@ -318,8 +327,11 @@ func (s *service) call(ctx context.Context, server *server, sending *sync.Mutex,
fn = server.wrappers[i-1](fn)
}
// client.Stream request
r.stream = true
errmsg := ""
if err := fn(ctx, argv.Interface(), reflect.ValueOf(sendReply).Interface()); err != nil {
if err := fn(ctx, r, reflect.ValueOf(sendReply).Interface()); err != nil {
errmsg = err.Error()
}
@ -337,7 +349,7 @@ func (m *methodType) prepareContext(ctx context.Context) reflect.Value {
return reflect.Zero(m.ContextType)
}
func (server *server) serveRequest(ctx context.Context, codec serverCodec) error {
func (server *server) serveRequest(ctx context.Context, codec serverCodec, ct string) error {
sending := new(sync.Mutex)
service, mtype, req, argv, replyv, keepReading, err := server.readRequest(codec)
if err != nil {
@ -351,7 +363,7 @@ func (server *server) serveRequest(ctx context.Context, codec serverCodec) error
}
return err
}
service.call(ctx, server, sending, mtype, req, argv, replyv, codec)
service.call(ctx, server, sending, mtype, req, argv, replyv, codec, ct)
return nil
}

View File

@ -31,6 +31,21 @@ type Server interface {
Stop() error
}
type Publication interface {
Topic() string
Message() interface{}
ContentType() string
}
type Request interface {
Service() string
Method() string
ContentType() string
Request() interface{}
Stream() bool
}
type Option func(*options)
var (

View File

@ -4,9 +4,9 @@ import (
"golang.org/x/net/context"
)
type HandlerFunc func(ctx context.Context, req interface{}, rsp interface{}) error
type HandlerFunc func(ctx context.Context, req Request, rsp interface{}) error
type SubscriberFunc func(ctx context.Context, msg interface{}) error
type SubscriberFunc func(ctx context.Context, msg Publication) error
type HandlerWrapper func(HandlerFunc) HandlerFunc

View File

@ -156,7 +156,8 @@ func validateSubscriber(sub Subscriber) error {
func (s *rpcServer) createSubHandler(sb *subscriber, opts options) broker.Handler {
return func(msg *broker.Message) {
cf, err := s.newCodec(msg.Header["Content-Type"])
ct := msg.Header["Content-Type"]
cf, err := s.newCodec(ct)
if err != nil {
return
}
@ -196,7 +197,7 @@ func (s *rpcServer) createSubHandler(sb *subscriber, opts options) broker.Handle
continue
}
fn := func(ctx context.Context, msg interface{}) error {
fn := func(ctx context.Context, msg Publication) error {
var vals []reflect.Value
if sb.typ.Kind() != reflect.Func {
vals = append(vals, sb.rcvr)
@ -205,7 +206,7 @@ func (s *rpcServer) createSubHandler(sb *subscriber, opts options) broker.Handle
vals = append(vals, reflect.ValueOf(ctx))
}
vals = append(vals, reflect.ValueOf(msg))
vals = append(vals, reflect.ValueOf(msg.Message()))
returnValues := handler.method.Call(vals)
if err := returnValues[0].Interface(); err != nil {
@ -218,7 +219,11 @@ func (s *rpcServer) createSubHandler(sb *subscriber, opts options) broker.Handle
fn = opts.subWrappers[i-1](fn)
}
go fn(ctx, req.Interface())
go fn(ctx, &rpcPublication{
topic: sb.topic,
contentType: ct,
message: req.Interface(),
})
}
}
}