func (r *failureRetryer) AllowRetry(ctx context.Context) (string, bool) {
	r.RLock()
	defer r.RUnlock()
	if !r.enable || r.policy.StopPolicy.MaxRetryTimes == 0 {
		return "", false
	}
	if stop, msg := chainStop(ctx, r.policy.StopPolicy); stop {
		return msg, false
	}
	if stop, msg := ddlStop(ctx, r.policy.StopPolicy, r.logger); stop {
		return msg, false
	}
	return "", true
}
AllowRetry implements the Retryer interface.
package retry
import (
	"context"
	"errors"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
	"github.com/cloudwego/kitex/pkg/circuitbreak"
	"github.com/cloudwego/kitex/pkg/kerrors"
	"github.com/cloudwego/kitex/pkg/klog"
	"github.com/cloudwego/kitex/pkg/rpcinfo"
)
func newFailureRetryer(policy Policy, cbC *cbContainer, logger klog.FormatLogger) (Retryer, error) {
	fr := &failureRetryer{cbContainer: cbC, logger: logger}
	if err := fr.UpdatePolicy(policy); err != nil {
		return nil, fmt.Errorf("newfailureRetryer failed, err=%w", err)
	}
	return fr, nil
}
type failureRetryer struct {
	enable      bool
	policy      *FailurePolicy
	backOff     BackOff
	cbContainer *cbContainer
	logger      klog.FormatLogger
	sync.RWMutex
	errMsg string
}
func (r *failureRetryer) ShouldRetry(ctx context.Context, err error, callTimes int, request interface{}, cbKey string) (string, bool) {
	r.RLock()
	defer r.RUnlock()
	if !r.enable || !r.isRetryErr(err) {
		return "", false
	}
	if stop, msg := circuitBreakerStop(ctx, r.policy.StopPolicy, r.cbContainer, request, cbKey); stop {
		return msg, false
	}
	if stop, msg := ddlStop(ctx, r.policy.StopPolicy, r.logger); stop {
		return msg, false
	}
	r.backOff.Wait(callTimes)
	return "", true
}