mirror of
https://github.com/krau/SaveAny-Bot.git
synced 2026-09-05 23:56:50 +08:00
fix: update backoff handling to use a factory function for concurrency safety
This commit is contained in:
@@ -15,7 +15,7 @@ import (
|
|||||||
// https://github.com/iyear/tdl/blob/master/core/tclient/tclient.go
|
// https://github.com/iyear/tdl/blob/master/core/tclient/tclient.go
|
||||||
func NewDefaultMiddlewares(ctx context.Context, timeout time.Duration) []telegram.Middleware {
|
func NewDefaultMiddlewares(ctx context.Context, timeout time.Duration) []telegram.Middleware {
|
||||||
return []telegram.Middleware{
|
return []telegram.Middleware{
|
||||||
recovery.New(ctx, newBackoff(timeout)),
|
recovery.New(ctx, func() backoff.BackOff { return newBackoff(timeout) }),
|
||||||
retry.New(config.C().Telegram.RpcRetry),
|
retry.New(config.C().Telegram.RpcRetry),
|
||||||
floodwait.NewSimpleWaiter(),
|
floodwait.NewSimpleWaiter(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,19 +14,28 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type recovery struct {
|
type recovery struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
backoff backoff.BackOff
|
newBackoff func() backoff.BackOff
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(ctx context.Context, backoff backoff.BackOff) telegram.Middleware {
|
// New returns a recovery middleware.
|
||||||
|
//
|
||||||
|
// newBackoff is a factory that must return a fresh backoff.BackOff on every call: backoff implementations in
|
||||||
|
// cenkalti/backoff/v4 (notably ExponentialBackOff) are not safe for concurrent
|
||||||
|
// use, and the Telegram client invokes RPCs from many goroutines in parallel.
|
||||||
|
//
|
||||||
|
// Sharing a single instance corrupts its internal counters, breaks the
|
||||||
|
// exponential interval, and defeats MaxElapsedTime - see issue #218.
|
||||||
|
func New(ctx context.Context, newBackoff func() backoff.BackOff) telegram.Middleware {
|
||||||
return &recovery{
|
return &recovery{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
backoff: backoff,
|
newBackoff: newBackoff,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *recovery) Handle(next tg.Invoker) telegram.InvokeFunc {
|
func (r *recovery) Handle(next tg.Invoker) telegram.InvokeFunc {
|
||||||
return func(ctx context.Context, input bin.Encoder, output bin.Decoder) error {
|
return func(ctx context.Context, input bin.Encoder, output bin.Decoder) error {
|
||||||
|
b := r.newBackoff()
|
||||||
|
|
||||||
return backoff.RetryNotify(func() error {
|
return backoff.RetryNotify(func() error {
|
||||||
if err := next.Invoke(ctx, input, output); err != nil {
|
if err := next.Invoke(ctx, input, output); err != nil {
|
||||||
@@ -38,7 +47,7 @@ func (r *recovery) Handle(next tg.Invoker) telegram.InvokeFunc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, r.backoff, func(err error, duration time.Duration) {
|
}, b, func(err error, duration time.Duration) {
|
||||||
log.FromContext(ctx).Debug("Wait for connection recovery", "error", err, "duration", duration)
|
log.FromContext(ctx).Debug("Wait for connection recovery", "error", err, "duration", duration)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user