func (c *PersistentCaller) ResetClient() (err error) {
	c.Lock()
	if c.client != nil {
		_ = c.client.Close()
	}
	c.client = nil
	c.Unlock()
	return
}
ResetClient resets client.
package rpc
import (
	"io"
	"net/rpc"
	"strings"
	"sync"
	"time"
	"github.com/pkg/errors"
	"github.com/SQLess/SQLess/proto"
	"github.com/SQLess/SQLess/route"
)
type PersistentCaller struct {
	pool   NOClientPool
	client Client
	TargetID proto.NodeID
	sync.Mutex
}
func NewPersistentCallerWithPool(pool NOClientPool, target proto.NodeID) *PersistentCaller {
	return &PersistentCaller{
		pool:     pool,
		TargetID: target,
	}
}
func (c *PersistentCaller) initClient(isAnonymous bool) (err error) {
	c.Lock()
	defer c.Unlock()
	if c.client == nil {
		c.client, err = DialToNodeWithPool(c.pool, c.TargetID, isAnonymous)
		if err != nil {
			err = errors.Wrap(err, "dial to node failed")
			return
		}
	}
	return
}
func (c *PersistentCaller) Call(method string, args interface{}, reply interface{}) (err error) {
	startTime := time.Now()
	defer func() {
		recordRPCCost(startTime, method, err)
	}()
	isAnonymous := (method == route.DHTPing.String())
	err = c.initClient(isAnonymous)
	if err != nil {
		err = errors.Wrap(err, "init PersistentCaller client failed")
		return
	}
	err = c.client.Call(method, args, reply)
	if err != nil {
		if err == io.EOF ||
			err == io.ErrUnexpectedEOF ||
			err == io.ErrClosedPipe ||
			err == rpc.ErrShutdown ||
			strings.Contains(strings.ToLower(err.Error()), "shut down") ||
			strings.Contains(strings.ToLower(err.Error()), "broken pipe") {
			_ = c.ResetClient()
			reconnectErr := c.initClient(isAnonymous)
			if reconnectErr != nil {
				err = errors.Wrap(reconnectErr, "reconnect failed")
			}
		}
		err = errors.Wrapf(err, "call %s failed", method)
		return
	}
	return
}