pomerium/internal/retry/backoff.go
Caleb Doxsey d062f9d68d
core/logs: remove warnings (#5235)
* core/logs: remove warnings

* switch to error
2024-08-27 09:38:50 -06:00

48 lines
1.2 KiB
Go

package retry
import (
"context"
"strings"
"time"
"github.com/cenkalti/backoff/v4"
"github.com/pomerium/pomerium/internal/log"
)
type serviceName struct{}
// WithBackoff retries the given function with an exponential backoff,
// stopping when the context is done or the function returns a terminal error.
func WithBackoff(ctx context.Context, name string, fn func(context.Context) error) error {
name, ctx = getServiceNameContext(ctx, name)
log.Debug(ctx).Str("service-name", name).Msg("starting")
defer log.Debug(ctx).Str("service-name", name).Msg("stopped")
b := backoff.NewExponentialBackOff()
b.MaxElapsedTime = 0
return backoff.RetryNotify(
func() error {
err := fn(ctx)
if IsTerminalError(err) {
return backoff.Permanent(err)
}
return err
},
backoff.WithContext(b, ctx),
func(err error, next time.Duration) {
log.Error(ctx).Err(err).Str("service-name", name).Dur("next", next).Msg("retrying")
},
)
}
func getServiceNameContext(ctx context.Context, name string) (string, context.Context) {
names, ok := ctx.Value(serviceName{}).([]string)
if ok {
names = append(names, name)
} else {
names = []string{name}
}
return strings.Join(names, "."), context.WithValue(ctx, serviceName{}, names)
}