Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExponentialBackOff doesn't exit after MaxElapsedTime is passed #120

Open
slnt opened this issue Jan 12, 2022 · 7 comments
Open

ExponentialBackOff doesn't exit after MaxElapsedTime is passed #120

slnt opened this issue Jan 12, 2022 · 7 comments

Comments

@slnt
Copy link

slnt commented Jan 12, 2022

Try out the following test:

func Test_WeirdBackOffThing(t *testing.T) {
	bo := &backoff.ExponentialBackOff{
		InitialInterval:     100 * time.Millisecond,
		RandomizationFactor: 0.5,
		Multiplier:          1.5,
		MaxInterval:         time.Second,
		MaxElapsedTime:      5 * time.Second,
		Clock:               backoff.SystemClock,
	}

	err := backoff.Retry(func() error {
		return errors.New("always error")
	}, bo)

	assert.Error(t, err)
}

It will timeout. Nothing immediately seems wrong to me with the way the BackOff is configured. Why does this happen?

@slnt
Copy link
Author

slnt commented Jan 12, 2022

UPDATE: so it turns out the issue is not setting Stop: backoff.Stop in the backoff configuration - however this raises a question: why do I have to manually set that? Is there value to being able to use a different sentinel value than backoff.Stop?

@cenkalti
Copy link
Owner

I don't remember why it is exported in the first place. You should use NewExponentialBackOff constructor then override the fields you want.

@hamstah
Copy link

hamstah commented Jun 1, 2022

hey, I just got the same issue. The problem is that the code won't work with retry as retry looks specifically for backoff.Stop

if next = b.NextBackOff(); next == Stop {

Will not work, if you want this to work you need

		if next = b.NextBackOff(); next == b.Stop {

but this won't work without changing the interface as Backoff doesn't have a custom Stop value in it, only ExponentialBackoff.

So regardless of the reason for allowing overriding the Stop, it is currently broken as is.

@cenkalti
Copy link
Owner

cenkalti commented Jun 4, 2022

@hamstah You should use the construct for creating new ExponentialBackoff instance and should not change Stop value.

@AntonioYuen
Copy link

@cenkalti sounds like a builder would be beneficial in this case. I just took this library up today and the options are pretty confusing. It's either use the default value or good luck.

I would suggest a builder starting with default values with validations on .build(). Also the builder would not allow a person to set the stop attribute. An example of a basic validation: initial interval cannot be greater than max interval.

@svkoskin
Copy link

It's either use the default value or good luck.

That isn't true, though. Nothing prevents users from modifying configurations created by constructors, and modifying structs by their users seems somewhat common in the Go ecosystem.

I used this library first time yesterday, and had a positive experience even though I needed to set a few non-default values. Even though I found it easiest to understand the customisation options through reading code.

@AntonioYuen
Copy link

@svkoskin I was able to figure out the library very quickly as well by reading the internals. But mistakes such as the one OP posted could be very common. Internals of your struct that aren't meant to be modified should be obscured from the end user, i.e. the Stop field is meant to be a default value.

Yeah modifying structs can be common but you can also set private fields by lower casing the field name, which would prevent unintended issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants