feat: implement server and client
This commit is contained in:
58
request.go
58
request.go
@ -5,14 +5,16 @@ import (
|
||||
"io"
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"krwu.top/krpc.v1/codec"
|
||||
)
|
||||
|
||||
type request struct {
|
||||
h *codec.Header
|
||||
argv reflect.Value
|
||||
replyv reflect.Value
|
||||
h *codec.Header
|
||||
argv, replyv reflect.Value
|
||||
mtype *methodType
|
||||
svc *service
|
||||
}
|
||||
|
||||
func (s *Server) readRequestHeader(cc codec.Codec) (*codec.Header, error) {
|
||||
@ -32,16 +34,52 @@ func (s *Server) readRequest(cc codec.Codec) (*request, error) {
|
||||
return nil, err
|
||||
}
|
||||
req := &request{h: h}
|
||||
req.argv = reflect.New(reflect.TypeOf(""))
|
||||
if err = cc.ReadBody(req.argv.Interface()); err != nil {
|
||||
fmt.Println("rpc server: read argv err: ", err)
|
||||
req.svc, req.mtype, err = s.findService(h.ServiceMethod)
|
||||
if err != nil {
|
||||
return req, err
|
||||
}
|
||||
req.argv = req.mtype.newArgv()
|
||||
req.replyv = req.mtype.newReplyv()
|
||||
argvi := req.argv.Interface()
|
||||
|
||||
if req.argv.Type().Kind() != reflect.Ptr {
|
||||
argvi = req.argv.Addr().Interface()
|
||||
}
|
||||
if err = cc.ReadBody(argvi); err != nil {
|
||||
fmt.Println("rpc: server read body error: ", err)
|
||||
return req, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (s *Server) handleRequest(cc codec.Codec, req *request, sending *sync.Mutex, wg *sync.WaitGroup) {
|
||||
func (s *Server) handleRequest(cc codec.Codec,
|
||||
req *request, sending *sync.Mutex, wg *sync.WaitGroup, timeout time.Duration) {
|
||||
defer wg.Done()
|
||||
fmt.Println("rcp server: ", req.h, req.argv.Elem())
|
||||
req.replyv = reflect.ValueOf(fmt.Sprintf("krpc resp %d", req.h.Seq))
|
||||
s.sendResponse(cc, req.h, req.replyv.Interface(), sending)
|
||||
called := make(chan struct{}, 1)
|
||||
sent := make(chan struct{}, 1)
|
||||
go func() {
|
||||
err := req.svc.call(req.mtype, req.argv, req.replyv)
|
||||
called <- struct{}{}
|
||||
if err != nil {
|
||||
req.h.Error = err.Error()
|
||||
s.sendResponse(cc, req.h, invalidRequest, sending)
|
||||
sent <- struct{}{}
|
||||
return
|
||||
}
|
||||
s.sendResponse(cc, req.h, req.replyv.Interface(), sending)
|
||||
sent <- struct{}{}
|
||||
}()
|
||||
|
||||
if timeout == 0 {
|
||||
<-called
|
||||
<-sent
|
||||
return
|
||||
}
|
||||
select {
|
||||
case <-time.After(timeout):
|
||||
req.h.Error = fmt.Sprintf("prc: server request handle timeout with %s", timeout)
|
||||
s.sendResponse(cc, req.h, invalidRequest, sending)
|
||||
case <-called:
|
||||
<-sent
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user