Files
jiacrontab/pkg/rpc/client.go
jiazhizhong 1279635d7f fix
2022-03-10 17:09:03 +08:00

112 lines
2.1 KiB
Go

package rpc
import (
"context"
"errors"
"jiacrontab/pkg/proto"
"net"
"net/rpc"
"time"
"github.com/iwannay/log"
)
const (
diaTimeout = 5 * time.Second
callTimeout = 1 * time.Minute
pingDuration = 3 * time.Second
)
var (
ErrRpc = errors.New("rpc is not available")
ErrRpcTimeout = errors.New("rpc call timeout")
ErrRpcCancel = errors.New("rpc call cancel")
ErrShutdown = rpc.ErrShutdown
)
type ClientOptions struct {
Network string
Addr string
}
type Client struct {
*rpc.Client
options ClientOptions
quit chan struct{}
err error
}
func Dial(options ClientOptions) (c *Client) {
c = &Client{}
c.options = options
c.dial()
c.quit = make(chan struct{}, 100)
return c
}
func (c *Client) dial() (err error) {
conn, err := net.DialTimeout(c.options.Network, c.options.Addr, diaTimeout)
if err != nil {
return err
}
c.Client = rpc.NewClient(conn)
return nil
}
func (c *Client) Call(serviceMethod string, ctx context.Context, args interface{}, reply interface{}) error {
if serviceMethod != PingService && serviceMethod != RegisterService {
log.Info("rpc call", c.options.Addr, serviceMethod)
}
if c.Client == nil {
return ErrRpc
}
select {
case <-ctx.Done():
return ErrRpcCancel
case call := <-c.Client.Go(serviceMethod, args, reply, make(chan *rpc.Call, 1)).Done:
return call.Error
case <-time.After(callTimeout):
return ErrRpcTimeout
}
}
func (c *Client) Error() error {
return c.err
}
func (c *Client) Close() {
c.quit <- struct{}{}
}
func (c *Client) Ping(serviceMethod string) {
var (
err error
)
for {
select {
case <-c.quit:
goto closed
default:
}
if c.Client != nil && c.err == nil {
if err = c.Call(serviceMethod, context.TODO(), &proto.EmptyArgs{}, &proto.EmptyReply{}); err != nil {
c.err = err
c.Client.Close()
log.Infof("client.Call(%s, args, reply) error (%v) \n", serviceMethod, err)
}
} else {
if err = c.dial(); err == nil {
c.err = nil
log.Info("client reconnet ", c.options.Addr)
}
}
time.Sleep(pingDuration)
}
closed:
log.Info("rpc quited", c.options.Addr)
if c.Client != nil {
c.Client.Close()
}
}