retry.go
package clientv3
import (
"github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
)
type rpcFunc func(ctx context.Context) error
type retryRpcFunc func(context.Context, rpcFunc) error
func (c *Client) newRetryWrapper() retryRpcFunc {
return func(rpcCtx context.Context, f rpcFunc) error {
for {
err := f(rpcCtx)
if err == nil {
return nil
}
// only retry if unavailable
if grpc.Code(err) != codes.Unavailable {
return err
}
// always stop retry on etcd errors
eErr := rpctypes.Error(err)
if _, ok := eErr.(rpctypes.EtcdError); ok {
return err
}
select {
case <-c.balancer.ConnectNotify():
case <-rpcCtx.Done():
return rpcCtx.Err()
case <-c.ctx.Done():
return c.ctx.Err()
}
}
}
}
type retryKVClient struct {
pb.KVClient
retryf retryRpcFunc
}
// RetryKVClient implements a KVClient that uses the client's FailFast retry policy.
func RetryKVClient(c *Client) pb.KVClient {
return &retryKVClient{pb.NewKVClient(c.conn), c.retryWrapper}
}
func (rkv *retryKVClient) Put(ctx context.Context, in *pb.PutRequest, opts ...grpc.CallOption) (resp *pb.PutResponse, err error) {
err = rkv.retryf(ctx, func(rctx context.Context) error {
resp, err = rkv.KVClient.Put(rctx, in, opts...)
return err
})
return resp, err
}
func (rkv *retryKVClient) DeleteRange(ctx context.Context, in *pb.DeleteRangeRequest, opts ...grpc.CallOption) (resp *pb.DeleteRangeResponse, err error) {
err = rkv.retryf(ctx, func(rctx context.Context) error {
resp, err = rkv.KVClient.DeleteRange(rctx, in, opts...)
return err
})
return resp, err
}
func (rkv *retryKVClient) Txn(ctx context.Context, in *pb.TxnRequest, opts ...grpc.CallOption) (resp *pb.TxnResponse, err error) {
err = rkv.retryf(ctx, func(rctx context.Context) error {
resp, err = rkv.KVClient.Txn(rctx, in, opts...)
return err
})
return resp, err
}
func (rkv *retryKVClient) Compact(ctx context.Context, in *pb.CompactionRequest, opts ...grpc.CallOption) (resp *pb.CompactionResponse, err error) {
err = rkv.retryf(ctx, func(rctx context.Context) error {
resp, err = rkv.KVClient.Compact(rctx, in, opts...)
return err
})
return resp, err
}
type retryLeaseClient struct {
pb.LeaseClient
retryf retryRpcFunc
}
// RetryLeaseClient implements a LeaseClient that uses the client's FailFast retry policy.
func RetryLeaseClient(c *Client) pb.LeaseClient {
return &retryLeaseClient{pb.NewLeaseClient(c.conn), c.retryWrapper}
}
func (rlc *retryLeaseClient) LeaseGrant(ctx context.Context, in *pb.LeaseGrantRequest, opts ...grpc.CallOption) (resp *pb.LeaseGrantResponse, err error) {
err = rlc.retryf(ctx, func(rctx context.Context) error {
resp, err = rlc.LeaseClient.LeaseGrant(rctx, in, opts...)
return err
})
return resp, err
}
func (rlc *retryLeaseClient) LeaseRevoke(ctx context.Context, in *pb.LeaseRevokeRequest, opts ...grpc.CallOption) (resp *pb.LeaseRevokeResponse, err error) {
err = rlc.retryf(ctx, func(rctx context.Context) error {
resp, err = rlc.LeaseClient.LeaseRevoke(rctx, in, opts...)
return err
})
return resp, err
}
type retryClusterClient struct {
pb.ClusterClient
retryf retryRpcFunc
}
// RetryClusterClient implements a ClusterClient that uses the client's FailFast retry policy.
func RetryClusterClient(c *Client) pb.ClusterClient {
return &retryClusterClient{pb.NewClusterClient(c.conn), c.retryWrapper}
}
func (rcc *retryClusterClient) MemberAdd(ctx context.Context, in *pb.MemberAddRequest, opts ...grpc.CallOption) (resp *pb.MemberAddResponse, err error) {
err = rcc.retryf(ctx, func(rctx context.Context) error {
resp, err = rcc.ClusterClient.MemberAdd(rctx, in, opts...)
return err
})
return resp, err
}
func (rcc *retryClusterClient) MemberRemove(ctx context.Context, in *pb.MemberRemoveRequest, opts ...grpc.CallOption) (resp *pb.MemberRemoveResponse, err error) {
err = rcc.retryf(ctx, func(rctx context.Context) error {
resp, err = rcc.ClusterClient.MemberRemove(rctx, in, opts...)
return err
})
return resp, err
}
func (rcc *retryClusterClient) MemberUpdate(ctx context.Context, in *pb.MemberUpdateRequest, opts ...grpc.CallOption) (resp *pb.MemberUpdateResponse, err error) {
err = rcc.retryf(ctx, func(rctx context.Context) error {
resp, err = rcc.ClusterClient.MemberUpdate(rctx, in, opts...)
return err
})
return resp, err
}
type retryAuthClient struct {
pb.AuthClient
retryf retryRpcFunc
}
// RetryAuthClient implements a AuthClient that uses the client's FailFast retry policy.
func RetryAuthClient(c *Client) pb.AuthClient {
return &retryAuthClient{pb.NewAuthClient(c.conn), c.retryWrapper}
}
func (rac *retryAuthClient) AuthEnable(ctx context.Context, in *pb.AuthEnableRequest, opts ...grpc.CallOption) (resp *pb.AuthEnableResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.AuthEnable(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) AuthDisable(ctx context.Context, in *pb.AuthDisableRequest, opts ...grpc.CallOption) (resp *pb.AuthDisableResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.AuthDisable(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) UserAdd(ctx context.Context, in *pb.AuthUserAddRequest, opts ...grpc.CallOption) (resp *pb.AuthUserAddResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.UserAdd(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) UserDelete(ctx context.Context, in *pb.AuthUserDeleteRequest, opts ...grpc.CallOption) (resp *pb.AuthUserDeleteResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.UserDelete(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) UserChangePassword(ctx context.Context, in *pb.AuthUserChangePasswordRequest, opts ...grpc.CallOption) (resp *pb.AuthUserChangePasswordResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.UserChangePassword(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) UserGrantRole(ctx context.Context, in *pb.AuthUserGrantRoleRequest, opts ...grpc.CallOption) (resp *pb.AuthUserGrantRoleResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.UserGrantRole(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) UserRevokeRole(ctx context.Context, in *pb.AuthUserRevokeRoleRequest, opts ...grpc.CallOption) (resp *pb.AuthUserRevokeRoleResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.UserRevokeRole(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) RoleAdd(ctx context.Context, in *pb.AuthRoleAddRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleAddResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.RoleAdd(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) RoleDelete(ctx context.Context, in *pb.AuthRoleDeleteRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleDeleteResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.RoleDelete(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) RoleGrantPermission(ctx context.Context, in *pb.AuthRoleGrantPermissionRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleGrantPermissionResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.RoleGrantPermission(rctx, in, opts...)
return err
})
return resp, err
}
func (rac *retryAuthClient) RoleRevokePermission(ctx context.Context, in *pb.AuthRoleRevokePermissionRequest, opts ...grpc.CallOption) (resp *pb.AuthRoleRevokePermissionResponse, err error) {
err = rac.retryf(ctx, func(rctx context.Context) error {
resp, err = rac.AuthClient.RoleRevokePermission(rctx, in, opts...)
return err
})
return resp, err
}
retry.go的更多相关文章
- 第3月第21天 nsclassfromstring返回null SVN报错:clean the working copy and then retry the operation
1. xcodeproj工程损坏时,.m文件没有加入编译. 2. SVN报错:clean the working copy and then retry the operation http://bl ...
- -bash: fork: retry: Resource temporarily unavailable
登陆不了服务器The server refused to start a shell. 登陆服务器后执行ls命令报错: 1 2 $ls -bash: fork: retry: Resource t ...
- java function retry wrapper
import java.util.concurrent.Callable; /** * Created by huahui.yang on 1/29/16. */ public class Retry ...
- Spring retry基本使用
Spring retry基本使用 背景介绍 在实际工作过程中,重试是一个经常使用的手段.比如MQ发送消息失败,会采取重试手段,比如工程中使用RPC请求外部服务,可能因为网络 波动出现超时而采取重试手段 ...
- freebsd启动报错:My unqualified host name unkown...Sleeping for retry.
原文 http://blog.163.com/sujoe_2006/blog/static/335315120111158576591/ 病状:启动报"My unqualified host ...
- ebs R12.2启动报错"failed to start a managed process after the maximum retry limit"
启动日志: Error --> Process (index=1,uid=1739599208,pid=4479) failed to start a managed process after ...
- Windows Azure Storage 之 Retry Policy (用来处理短暂性错误-Transient Fault)
在使用Windows Azure Storage Service 的时候, 通常会遇到各种各样的问题. 例如网络连接不稳定,导致请求没有发出去.删除一个Blob Container 之后又立刻创建同名 ...
- 启动受管服务器出现:unable to get file lock, will retry...
启动受管服务器出现:unable to get file lock, will retry... 解决方法:一.删掉Domain下的*.lok文件1. 删除edit.lok进入到domain_home ...
- spring retry 使用
1. 场景 系统方法调用时无状态的,同时因为网络原因,或者系统暂时故障,进行的重试 2. maven 依赖 <project xmlns="http://maven.apa ...
- C# Retry重试操作解决方案(附源码)
一.前言 (1)对于Thread的Abort方法,如果线程当前正在执行的是一段非托管代码,那么CLR就不会抛出ThreadAbortException,只有当代码继续回到CLR中时,才会引发Threa ...
随机推荐
- Jmeter(二十五)_Xpath关联
在Jmeter中,除了正则表达式可以用作关联,还有一种方式也可以做关联,那就是 XPath Extractor.它是利用xpath提取出关键信息,传递变量. 具体用法 添加一个后置处理器-XPath ...
- Jfinal调用Orcale存储过程
因为项目需要,最近一直在学习Orcale存储过程,但发现在网上很少有人写Jave中Jfinal调用Orcale存储过程的文章,即使有也是几年前的,很多都不能用,今天给大家分享一段Jfinal调用Orc ...
- javascript预览图片——IT轮子系列(九)
再使用htm控件 <input type="file" name="file" /> 上传图片的时候,往往需要先预览图片,然后点击保存按钮,把图片上 ...
- 框架学习:ibatis框架的结构和分析
由于最近一段时间比较忙碌,<框架学习>系列的文章一直在搁浅着,最近开始继续这个系列的文章更新. 在上篇文章中我们说到了hibernate框架,它是一种基于JDBC的主流持久化框架,是一个优 ...
- JavaScript设计模式之一Interface接口
如何用面向对象的思想来写JavaScript,对于初学者应该是比较难的,我们经常用的JQuery其实也是用面向对象的思想去封装的,今天我们来看看如何在Javascript中用Interface,在C# ...
- JAVA代码设置selector不同状态下的背景颜色
代码实现Shape 代码实现Selector StateListDrawable与GradientDrawable 的运用 在Android开发中,我们时常会用到自定义drawable样式,在draw ...
- C#中的var和dynamic
在理解var和dynamic关键字之前,让我们先了解一下编程语言的类别. C#中有两类编程语言: 静态类型语言类别 动态语言类别 静态类型语言 静态类型语言也被称为强类型语言.所谓强类型语言,通俗的讲 ...
- MAC OSX下用pip安装lxml时遇到xmlversion.h not found的解决办法
http://blog.csdn.NET/wave_1102/article/details/37730589 今天在Mac下用pip安装lxml,总是报如下错误: etree_defs.h::: f ...
- Python入门指南(超详细)
Python 是一门非常容易上手的语言,通过查阅资料和教程,也许一晚上就能写出一个简单的爬虫.但 Python 也是一门很难精通的语言,因为简洁的语法背后隐藏了许多黑科技.本文主要针对的读者是: 毫无 ...
- Grunt的配置和使用
Grunt和Grunt插件是通过NodeJs的包管理工具npm安装并进行管理的. Grunt 0.4.x必须配合NodeJs=>0.8.0版本使用(奇数版本的NodeJs不是稳定的开发版本) ...