retry

package
v0.9.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 18, 2024 License: Apache-2.0 Imports: 22 Imported by: 94

Documentation

Overview

Package retry implements rpc retry

Index

Constants

View Source
const (
	// TransitKey is transited persistently when the req is a retry call.
	// When a request with this key, the downstream will not do retry(just support in kitex now).
	TransitKey = "RetryReq"

	// CtxReqOp is used to ignore RPC Request concurrent write
	CtxReqOp ctxKey = "K_REQ_OP"

	// CtxRespOp is used to ignore RPC Response concurrent write/read.
	CtxRespOp ctxKey = "K_RESP_OP"

	// Wildcard stands for 'any method' when associated with a retryer.
	Wildcard = "*"
)
View Source
const (
	OpNo int32 = iota
	OpDoing
	OpDone
)

Req or Resp operation state, just be useful when concurrent write may happen

View Source
const TypeRetry iface.ItemType = "retry_config"

TypeRetry serves as itemKey in ConfigValueImpl

Variables

View Source
var NewRetryConfig = util.JsonInitializer(func() iface.ConfigValueItem {
	return &RetryConfig{
		Config: &Policy{},
	}
})

NewRetryConfig is a function decoding json bytes to a RetryConfig object

View Source
var NoneBackOff = &noneBackOff{}

NoneBackOff means there's no backoff.

Functions

func CopyDefaultRetryConfig added in v0.6.0

func CopyDefaultRetryConfig() iface.ConfigValueItem

CopyDefaultRetryConfig returns a copy of defaultRetry, thus avoiding default values changed by business

func IsLocalRetryRequest added in v0.7.2

func IsLocalRetryRequest(ctx context.Context) bool

IsLocalRetryRequest checks whether it's a retry request by checking the RetryTag set in rpcinfo It's supposed to be used in client middlewares

func IsRemoteRetryRequest added in v0.7.2

func IsRemoteRetryRequest(ctx context.Context) bool

IsRemoteRetryRequest checks whether it's a retry request by checking the TransitKey in metainfo It's supposed to be used in server side (handler/middleware)

func PrepareRetryContext added in v0.9.0

func PrepareRetryContext(ctx context.Context) context.Context

PrepareRetryContext adds necessary keys to context for retry These keys should be added to `ctx` no matter whether there's a need to retry, to avoid sharing the same object objects with another method call, since `ctx` might be reused in user-defined middlewares.

func RegisterDDLStop

func RegisterDDLStop(f DDLStopFunc)

RegisterDDLStop registers ddl stop.

Types

type BackOff

type BackOff interface {
	Wait(callTimes int)
}

BackOff is the interface of back off implements

type BackOffCfgKey

type BackOffCfgKey string

BackOffCfgKey represents the keys for BackOff.

const (
	FixMSBackOffCfgKey      BackOffCfgKey = "fix_ms"
	MinMSBackOffCfgKey      BackOffCfgKey = "min_ms"
	MaxMSBackOffCfgKey      BackOffCfgKey = "max_ms"
	InitialMSBackOffCfgKey  BackOffCfgKey = "initial_ms"
	MultiplierBackOffCfgKey BackOffCfgKey = "multiplier"
)

the keys of all back off configs

type BackOffPolicy

type BackOffPolicy struct {
	BackOffType BackOffType               `json:"backoff_type"`
	CfgItems    map[BackOffCfgKey]float64 `json:"cfg_items,omitempty"`
}

BackOffPolicy is the BackOff policy. DON'T FORGET to update Equals() and DeepCopy() if you add new fields

func (*BackOffPolicy) DeepCopy added in v0.5.0

func (p *BackOffPolicy) DeepCopy() *BackOffPolicy

func (*BackOffPolicy) Equals

func (p *BackOffPolicy) Equals(np *BackOffPolicy) bool

Equals to check if BackOffPolicy is equal.

type BackOffType

type BackOffType string

BackOffType means the BackOff type.

const (
	NoneBackOffType   BackOffType = "none"
	FixedBackOffType  BackOffType = "fixed"
	RandomBackOffType BackOffType = "random"
)

all back off types

type BackupPolicy

type BackupPolicy struct {
	RetryDelayMS  uint32     `json:"retry_delay_ms"`
	StopPolicy    StopPolicy `json:"stop_policy"`
	RetrySameNode bool       `json:"retry_same_node"`
}

BackupPolicy for backup request DON'T FORGET to update Equals() and DeepCopy() if you add new fields

func NewBackupPolicy

func NewBackupPolicy(delayMS uint32) *BackupPolicy

NewBackupPolicy init backup request policy the param delayMS is suggested to set as TP99

func (*BackupPolicy) DeepCopy added in v0.5.0

func (p *BackupPolicy) DeepCopy() *BackupPolicy

func (*BackupPolicy) DisableChainRetryStop

func (p *BackupPolicy) DisableChainRetryStop()

DisableChainRetryStop disables chain stop

func (*BackupPolicy) Equals

func (p *BackupPolicy) Equals(np *BackupPolicy) bool

Equals to check if BackupPolicy is equal

func (BackupPolicy) String

func (p BackupPolicy) String() string

String is used to print human readable debug info.

func (*BackupPolicy) WithMaxRetryTimes

func (p *BackupPolicy) WithMaxRetryTimes(retryTimes int)

WithMaxRetryTimes default is 1, not include first call

func (*BackupPolicy) WithRetryBreaker

func (p *BackupPolicy) WithRetryBreaker(errRate float64)

WithRetryBreaker sets error rate.

func (*BackupPolicy) WithRetrySameNode

func (p *BackupPolicy) WithRetrySameNode()

WithRetrySameNode set retry to use the same node.

type CBPolicy

type CBPolicy struct {
	ErrorRate float64 `json:"error_rate"`
}

CBPolicy is the circuit breaker policy

type Container

type Container struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Container is a wrapper for Retryer.

func NewRetryContainer

func NewRetryContainer(opts ...ContainerOption) *Container

NewRetryContainer build Container that need to build circuit breaker and do circuit breaker statistic. The caller is responsible for calling Container.Close() to release resources referenced.

func NewRetryContainerWithCB

func NewRetryContainerWithCB(cc *circuitbreak.Control, cp circuitbreaker.Panel) *Container

NewRetryContainerWithCB build Container that doesn't do circuit breaker statistic but get statistic result. Which is used in case that circuit breaker is enabled. eg:

   cbs := circuitbreak.NewCBSuite(circuitbreak.RPCInfo2Key)
   retryC := retry.NewRetryContainerWithCB(cbs.ServiceControl(), cbs.ServicePanel())
	  var opts []client.Option
	  opts = append(opts, client.WithRetryContainer(retryC))
   // enable service circuit breaker
	  opts = append(opts, client.WithMiddleware(cbs.ServiceCBMW()))

func NewRetryContainerWithCBStat

func NewRetryContainerWithCBStat(cc *circuitbreak.Control, cp circuitbreaker.Panel) *Container

NewRetryContainerWithCBStat build Container that need to do circuit breaker statistic. Which is used in case that the service CB key is customized. eg:

cbs := circuitbreak.NewCBSuite(YourGenServiceCBKeyFunc)
retry.NewRetryContainerWithCBStat(cbs.ServiceControl(), cbs.ServicePanel())

func NewRetryContainerWithPercentageLimit added in v0.7.2

func NewRetryContainerWithPercentageLimit() *Container

NewRetryContainerWithPercentageLimit build a Container to limiting the percentage of retry requests; This is the RECOMMENDED initializer if you want to control PRECISELY the percentage of retry requests.

func (*Container) Close added in v0.7.2

func (rc *Container) Close() (err error)

Close releases all possible resources referenced.

func (*Container) DeletePolicy added in v0.7.0

func (rc *Container) DeletePolicy(method string)

DeletePolicy to delete the method by method.

func (*Container) Dump

func (rc *Container) Dump() interface{}

Dump is used to show current retry policy

func (*Container) Init

func (rc *Container) Init(mp map[string]Policy, rr *ShouldResultRetry) (err error)

Init to build Retryer with code config.

func (*Container) InitWithPolicies

func (rc *Container) InitWithPolicies(methodPolicies map[string]Policy) error

InitWithPolicies to init Retryer with methodPolicies Notice, InitWithPolicies is export func, the lock should be added inside

func (*Container) NotifyPolicyChange

func (rc *Container) NotifyPolicyChange(method string, p Policy)

NotifyPolicyChange to receive policy when it changes

func (*Container) WithRetryIfNeeded

func (rc *Container) WithRetryIfNeeded(ctx context.Context, callOptRetry *Policy, rpcCall RPCCallFunc, ri rpcinfo.RPCInfo, request interface{}) (lastRI rpcinfo.RPCInfo, recycleRI bool, err error)

WithRetryIfNeeded to check if there is a retryer can be used and if current call can retry. When the retry condition is satisfied, use retryer to call

type ContainerOption added in v0.7.2

type ContainerOption func(rc *Container)

ContainerOption is used when initializing a Container

func WithContainerCBControl added in v0.7.2

func WithContainerCBControl(ctrl *circuitbreak.Control) ContainerOption

WithContainerCBControl is specifies the circuitbreak.Control used in the retry circuitbreaker It's user's responsibility to make sure it's paired with panel

func WithContainerCBPanel added in v0.7.2

func WithContainerCBPanel(panel circuitbreaker.Panel) ContainerOption

WithContainerCBPanel is specifies the circuitbreaker.Panel used in the retry circuitbreaker It's user's responsibility to make sure it's paired with control

func WithContainerCBStat added in v0.7.2

func WithContainerCBStat() ContainerOption

WithContainerCBStat instructs the circuitbreak.RecordStat is called within the retryer

func WithContainerCBSuite added in v0.7.2

func WithContainerCBSuite(cbs *circuitbreak.CBSuite) ContainerOption

WithContainerCBSuite specifies the CBSuite used in the retry circuitbreak retryer will use its ServiceControl and ServicePanel Its priority is lower than WithContainerCBControl and WithContainerCBPanel

func WithContainerEnablePercentageLimit added in v0.7.2

func WithContainerEnablePercentageLimit() ContainerOption

WithContainerEnablePercentageLimit should be called for limiting the percentage of retry requests

type DDLStopFunc

type DDLStopFunc func(ctx context.Context, policy StopPolicy) (bool, string)

DDLStopFunc is the definition of ddlStop func

type FailurePolicy

type FailurePolicy struct {
	StopPolicy        StopPolicy         `json:"stop_policy"`
	BackOffPolicy     *BackOffPolicy     `json:"backoff_policy,omitempty"`
	RetrySameNode     bool               `json:"retry_same_node"`
	ShouldResultRetry *ShouldResultRetry `json:"-"`

	// Extra is not used directly by kitex. It's used for better integrating your own config source.
	// After loading FailurePolicy from your config source, `Extra` can be decoded into a user-defined schema,
	// with which, more complex strategies can be implemented, such as modifying the `ShouldResultRetry`.
	Extra string `json:"extra"`
}

FailurePolicy for failure retry DON'T FORGET to update Equals() and DeepCopy() if you add new fields

func NewFailurePolicy

func NewFailurePolicy() *FailurePolicy

NewFailurePolicy init default failure retry policy

func NewFailurePolicyWithResultRetry added in v0.4.0

func NewFailurePolicyWithResultRetry(rr *ShouldResultRetry) *FailurePolicy

NewFailurePolicyWithResultRetry init failure retry policy with ShouldResultRetry

func (*FailurePolicy) DeepCopy added in v0.5.0

func (p *FailurePolicy) DeepCopy() *FailurePolicy

func (*FailurePolicy) DisableChainRetryStop

func (p *FailurePolicy) DisableChainRetryStop()

DisableChainRetryStop disables chain stop

func (*FailurePolicy) Equals

func (p *FailurePolicy) Equals(np *FailurePolicy) bool

Equals to check if FailurePolicy is equal

func (FailurePolicy) IsErrorRetryNonNil added in v0.4.0

func (p FailurePolicy) IsErrorRetryNonNil() bool

IsErrorRetryNonNil is used to check if ErrorRetry is nil

func (FailurePolicy) IsRespRetryNonNil added in v0.4.0

func (p FailurePolicy) IsRespRetryNonNil() bool

IsRespRetryNonNil is used to check if RespRetry is nil

func (FailurePolicy) IsRetryForTimeout added in v0.5.2

func (p FailurePolicy) IsRetryForTimeout() bool

IsRetryForTimeout is used to check if timeout error need to retry

func (FailurePolicy) String

func (p FailurePolicy) String() string

String prints human readable information.

func (*FailurePolicy) WithDDLStop

func (p *FailurePolicy) WithDDLStop()

WithDDLStop sets ddl stop to true.

func (*FailurePolicy) WithFixedBackOff

func (p *FailurePolicy) WithFixedBackOff(fixMS int)

WithFixedBackOff set fixed time.

func (*FailurePolicy) WithMaxDurationMS

func (p *FailurePolicy) WithMaxDurationMS(maxMS uint32)

WithMaxDurationMS include first call and retry call, if the total duration exceed limit then stop retry

func (*FailurePolicy) WithMaxRetryTimes

func (p *FailurePolicy) WithMaxRetryTimes(retryTimes int)

WithMaxRetryTimes default is 2, not include first call

func (*FailurePolicy) WithRandomBackOff

func (p *FailurePolicy) WithRandomBackOff(minMS, maxMS int)

WithRandomBackOff sets the random time.

func (*FailurePolicy) WithRetryBreaker

func (p *FailurePolicy) WithRetryBreaker(errRate float64)

WithRetryBreaker sets the error rate.

func (*FailurePolicy) WithRetrySameNode

func (p *FailurePolicy) WithRetrySameNode()

WithRetrySameNode sets to retry the same node.

func (*FailurePolicy) WithSpecifiedResultRetry added in v0.4.0

func (p *FailurePolicy) WithSpecifiedResultRetry(rr *ShouldResultRetry)

WithSpecifiedResultRetry sets customized ShouldResultRetry.

type Policy

type Policy struct {
	Enable bool `json:"enable"`
	// 0 is failure retry, 1 is backup
	Type Type `json:"type"`
	// notice: only one retry policy can be enabled, which one depend on Policy.Type
	FailurePolicy *FailurePolicy `json:"failure_policy,omitempty"`
	BackupPolicy  *BackupPolicy  `json:"backup_policy,omitempty"`
}

Policy contains all retry policies DON'T FORGET to update Equals() and DeepCopy() if you add new fields

func BuildBackupRequest added in v0.4.0

func BuildBackupRequest(p *BackupPolicy) Policy

BuildBackupRequest is used to build Policy with *BackupPolicy

func BuildFailurePolicy added in v0.4.0

func BuildFailurePolicy(p *FailurePolicy) Policy

BuildFailurePolicy is used to build Policy with *FailurePolicy

func (*Policy) DeepCopy added in v0.5.0

func (p *Policy) DeepCopy() *Policy

func (Policy) Equals

func (p Policy) Equals(np Policy) bool

Equals to check if policy is equal

type RPCCallFunc

type RPCCallFunc func(context.Context, Retryer) (rpcinfo rpcinfo.RPCInfo, resp interface{}, err error)

RPCCallFunc is the definition with wrap rpc call

type RetryConfig added in v0.6.0

type RetryConfig struct {
	Config *Policy `json:"config"`
}

RetryConfig serves as itemValue in ConfigValueImpl It could have been an alias of Policy, but we need to keep compatibility with ByteDance's internal use

func (*RetryConfig) DeepCopy added in v0.6.0

func (c *RetryConfig) DeepCopy() iface.ConfigValueItem

DeepCopy returns a copy of the current RetryConfig

func (*RetryConfig) EqualsTo added in v0.6.0

func (c *RetryConfig) EqualsTo(other iface.ConfigValueItem) bool

EqualsTo returns true if the current RetryConfig equals to the other one

type Retryer

type Retryer interface {
	// AllowRetry to check if current request satisfy retry condition[eg: circuit, retry times == 0, chain stop, ddl].
	// If not satisfy won't execute Retryer.Do and return the reason message
	// Execute anyway for the first time regardless of able to retry.
	AllowRetry(ctx context.Context) (msg string, ok bool)

	// ShouldRetry to check if retry request can be called, it is checked in retryer.Do.
	// If not satisfy will return the reason message
	ShouldRetry(ctx context.Context, err error, callTimes int, req interface{}, cbKey string) (msg string, ok bool)
	UpdatePolicy(policy Policy) error

	// Retry policy execute func. recycleRI is to decide if the firstRI can be recycled.
	Do(ctx context.Context, rpcCall RPCCallFunc, firstRI rpcinfo.RPCInfo, request interface{}) (lastRI rpcinfo.RPCInfo, recycleRI bool, err error)
	AppendErrMsgIfNeeded(err error, ri rpcinfo.RPCInfo, msg string)

	// Prepare to do something needed before retry call.
	Prepare(ctx context.Context, prevRI, retryRI rpcinfo.RPCInfo)
	Dump() map[string]interface{}
	Type() Type
}

Retryer is the interface for Retry implements

func NewRetryer

func NewRetryer(p Policy, r *ShouldResultRetry, cbC *cbContainer) (retryer Retryer, err error)

NewRetryer build a retryer with policy

type ShouldResultRetry added in v0.4.0

type ShouldResultRetry struct {
	ErrorRetry func(err error, ri rpcinfo.RPCInfo) bool
	RespRetry  func(resp interface{}, ri rpcinfo.RPCInfo) bool
	// disable the default timeout retry in specific scenarios (e.g. the requests are not non-idempotent)
	NotRetryForTimeout bool
}

ShouldResultRetry is used for specifying which error or resp need to be retried

func AllErrorRetry added in v0.4.0

func AllErrorRetry() *ShouldResultRetry

AllErrorRetry is common choice for ShouldResultRetry.

type StopPolicy

type StopPolicy struct {
	MaxRetryTimes    int      `json:"max_retry_times"`
	MaxDurationMS    uint32   `json:"max_duration_ms"`
	DisableChainStop bool     `json:"disable_chain_stop"`
	DDLStop          bool     `json:"ddl_stop"`
	CBPolicy         CBPolicy `json:"cb_policy"`
}

StopPolicy is a group policies to decide when stop retry

type Type

type Type int

Type is retry type include FailureType, BackupType

const (
	FailureType Type = iota
	BackupType
)

retry types

func (Type) String

func (t Type) String() string

String prints human readable information.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL