Request timeout

This commit is contained in:
Matthias Fulz 2020-03-26 01:28:15 +01:00
parent a252437585
commit 231f347976
3 changed files with 43 additions and 101 deletions

101
client.go
View File

@ -10,80 +10,6 @@ import (
"time" "time"
) )
//func (client *Client) Call(funcName string, args ...interface{}) (ret []byte, err error) {
//var b bytes.Buffer
//enc := client.ed.NewEncoder(&b)
//for _, a := range args {
//enc.Encode(a)
//}
//payload := b.Bytes()
//req := RPCRequest{funcName, payload}
//client.RLock()
//defer client.RUnlock()
//if err = client.conn.Send(&req); err != nil {
//return nil, err
//}
//var call *RPCCall
//if call, err = client.conn.Receive(); err != nil {
//return nil, err
//}
//var response *RPCResponse
//var ok bool
//if response, ok = call.Payload.(*RPCResponse); !ok {
//return nil, errors.New("srpc - Expected response")
//}
//if response.Status != RPCOK {
//err = errors.New("srpc - Response contained error: '" + response.Error + "'")
//}
//return response.Payload, err
//}
//func (client *Client) Close() {
//client.Lock()
//defer client.Unlock()
//client.conn.Send(new(RPCClose))
//client.running = false
//}
//func (client *Client) NewDecoder(r io.Reader) IDecoder {
//return client.ed.NewDecoder(r)
//}
//func NewClient(conn net.Conn) *Client {
//ret := &Client{sync.RWMutex{}, NewEncoderDecoder(), NewNetConn(conn, NewEncoderDecoder()), true}
//go func() {
//for {
//fmt.Println("heartbeat")
//ret.Lock()
//if ret.running == false {
//ret.Unlock()
//return
//}
//ret.conn.Send(new(RPCHeartbeat))
//if _, err := ret.conn.Receive(); err != nil {
//ret.conn.Send(new(RPCClose))
//ret.Unlock()
//return
//}
//fmt.Println("got heartbeat")
//ret.Unlock()
//time.Sleep(15 * time.Second)
//}
//}()
//return ret
//}
type clientMessage struct { type clientMessage struct {
ID uint64 ID uint64
Data interface{} Data interface{}
@ -95,7 +21,6 @@ type call struct {
Request clientMessage Request clientMessage
Error error Error error
state messageState state messageState
t time.Time
done chan bool done chan bool
sync.RWMutex sync.RWMutex
} }
@ -128,6 +53,7 @@ type RPCClient struct {
ResponseDataHandler ResponseDataHandlerFunc ResponseDataHandler ResponseDataHandlerFunc
DialHandler DialHandlerFunc DialHandler DialHandlerFunc
Ed IEncoderDecoder Ed IEncoderDecoder
RequestTimeout time.Duration
calls []*call calls []*call
callChan chan *call callChan chan *call
nextID uint64 nextID uint64
@ -164,6 +90,10 @@ func (c *RPCClient) Start() (err error) {
return errors.New("srpc - Client needs a DialHandler") return errors.New("srpc - Client needs a DialHandler")
} }
if c.RequestTimeout == 0 {
c.RequestTimeout = DefaultRequestTimeout
}
c.stopWg.Add(1) c.stopWg.Add(1)
go clientHandler(c) go clientHandler(c)
return nil return nil
@ -199,16 +129,25 @@ func (c *RPCClient) Call(request interface{}) (response interface{}, err error)
return nil, errors.New("srpc - Client requests are full") return nil, errors.New("srpc - Client requests are full")
} }
fmt.Printf("Sending request with ID %d\n", requestCall.Request.ID)
fmt.Printf("Request %v\n", requestCall.Request.Data)
c.callChan <- requestCall c.callChan <- requestCall
<-requestCall.done select {
case <-requestCall.done:
fmt.Printf("Finished request with ID %d\n", requestCall.Request.ID)
requestCall.Lock() requestCall.Lock()
response = requestCall.Response.Data response = requestCall.Response.Data
err = requestCall.Error err = requestCall.Error
requestCall.state = FREE requestCall.state = FREE
requestCall.Unlock() requestCall.Unlock()
fmt.Println(response) case <-time.After(c.RequestTimeout):
fmt.Println(err) requestCall.Lock()
response = nil
err = errors.New("srpc - Request timed out")
requestCall.state = FREE
requestCall.Unlock()
}
return response, err return response, err
} }
@ -352,12 +291,9 @@ func clientReader(c *RPCClient, conn io.Reader, done chan<- error) {
} }
} }
fmt.Println(response)
ok := false ok := false
for _, e := range c.calls { for _, e := range c.calls {
fmt.Println(e.Request.ID)
e.Lock() e.Lock()
fmt.Println(e.Request.ID)
if e.Request.ID == response.ID { if e.Request.ID == response.ID {
e.Response = response e.Response = response
if e.Response.Error != "" { if e.Response.Error != "" {
@ -390,11 +326,12 @@ func clientStop(stopChan <-chan struct{}) bool {
} }
} }
func NewUnixClient(addr string, handler ResponseDataHandlerFunc) *RPCClient { func NewUnixClient(addr string, handler ResponseDataHandlerFunc, timeout time.Duration) *RPCClient {
return &RPCClient{ return &RPCClient{
Addr: addr, Addr: addr,
ResponseDataHandler: handler, ResponseDataHandler: handler,
DialHandler: unixDial, DialHandler: unixDial,
Ed: NewEncoderDecoder(), Ed: NewEncoderDecoder(),
RequestTimeout: timeout,
} }
} }

View File

@ -2,6 +2,7 @@ package srpc
import ( import (
"log" "log"
"time"
) )
type LogErrorFunc func(format string, args ...interface{}) type LogErrorFunc func(format string, args ...interface{})
@ -21,4 +22,5 @@ const (
const ( const (
DefaultMaxClientRequests = int(128) DefaultMaxClientRequests = int(128)
DefaultRequestTimeout = 30 * time.Second
) )

View File

@ -176,13 +176,15 @@ func serverHandleConnection(s *RPCServer, conn io.ReadWriteCloser, clientAddr st
} }
var err error var err error
var msg clientMessage
msg.Data = s.RequestDataHandler()
dec := s.Ed.NewDecoder(conn) dec := s.Ed.NewDecoder(conn)
enc := s.Ed.NewEncoder(conn) enc := s.Ed.NewEncoder(conn)
for { for {
//TODO: check for multiple requests per client
var msg clientMessage
msg.Data = s.RequestDataHandler()
if err = dec.Decode(&msg); err != nil { if err = dec.Decode(&msg); err != nil {
if !clientDisconnect(err) && !serverStop(s.stopChan) { if !clientDisconnect(err) && !serverStop(s.stopChan) {
s.LogError("srpc - '%s'=>'%s': Cannot decode request: '%s'\n", clientAddr, s.Addr, err) s.LogError("srpc - '%s'=>'%s': Cannot decode request: '%s'\n", clientAddr, s.Addr, err)
@ -191,13 +193,13 @@ func serverHandleConnection(s *RPCServer, conn io.ReadWriteCloser, clientAddr st
return return
} }
fmt.Println(msg.Data)
go func() {
var response serverMessage var response serverMessage
response.ID = msg.ID response.ID = msg.ID
response.ClientAddr = msg.ClientAddr response.ClientAddr = msg.ClientAddr
response.Data = s.RequestHandler(msg.ClientAddr, msg.Data) response.Data = s.RequestHandler(msg.ClientAddr, msg.Data)
fmt.Println(response.Data)
if err = enc.Encode(response); err != nil { if err = enc.Encode(response); err != nil {
if !clientDisconnect(err) && !serverStop(s.stopChan) { if !clientDisconnect(err) && !serverStop(s.stopChan) {
s.LogError("srpc - '%s'=>'%s': Cannot encode response: '%s'\n", clientAddr, s.Addr, err) s.LogError("srpc - '%s'=>'%s': Cannot encode response: '%s'\n", clientAddr, s.Addr, err)
@ -205,6 +207,7 @@ func serverHandleConnection(s *RPCServer, conn io.ReadWriteCloser, clientAddr st
conn.Close() conn.Close()
return return
} }
}()
} }
} }