Request timeout
This commit is contained in:
parent
a252437585
commit
231f347976
101
client.go
101
client.go
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
11
server.go
11
server.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue