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

Improve retry middleware option parsing #407

Merged

Conversation

britto
Copy link
Contributor

@britto britto commented Aug 3, 2020

When delay or max_delay are less than 1, the Retry middleware currently crashes with the following error:

** (FunctionClauseError) no function clause matching in :rand.uniform_s/2
(stdlib 3.13) rand.erl:326: :rand.uniform_s/2
(stdlib 3.13) rand.erl:299: :rand.uniform/1
(tesla 1.3.3) lib/tesla/middleware/retry.ex:106: Tesla.Middleware.Retry.backoff/3
(tesla 1.3.3) lib/tesla/middleware/retry.ex:94: Tesla.Middleware.Retry.retry/3

It happens because :rand.uniform/1 requires a positive integer.

Original idea

Make sure retry won't crash when either delay or max_delay are misconfigured.

This change adjusts max_delay to 1 when it isn't positive and also adjusts delay to make sure it falls within 1..max_delay. Ideally, I believe we should will raise an ArgumentError right away when these values are invalid, e.g. when they are not integers, but that would be a bigger, breaking change. So this is a compromise we can safely make for now, without any behavior changes.

Update

This change applies strict validation to some retry middleware options. Now we explicitly fail when either one of the following misconfigurations are detected:

  • delay is not a positive integer.
  • max_delay is not a positive integer.
  • max_retries is not a non-negative integer.

@britto britto force-pushed the improve-retry-middleware-option-parsing branch 2 times, most recently from 45f7042 to f5785dd Compare August 4, 2020 13:01
@teamon
Copy link
Member

teamon commented Aug 23, 2020

Hi, thanks for the PR.

Raising a proper ArgumentError instead of FunctionClauseError wouldn't be a breaking change, but a bug fix.

Silently "fixing" the arguments is a bad practice that can lead to hours of frustrating debugging of an unexpected behaviour.

@britto
Copy link
Contributor Author

britto commented Aug 23, 2020

Hi, @teamon. Thanks for your input on this. I'll update this PR with the changes to make the middleware raise an error instead, hopefully with a helpful message, then I'll ask you to take another look as soon as it's done.

@britto
Copy link
Contributor Author

britto commented Aug 23, 2020

Updated and also seized the opportunity to validate max_retries as well. If it is accidentally set to a negative value, the middleware will keep retrying endlessly and that's probably an undesirable behavior. PTAL.

@britto britto force-pushed the improve-retry-middleware-option-parsing branch from 5dbaaa1 to 537df80 Compare August 24, 2020 13:18
By favoring Bitwise.bsl over :math.pow for powers of 2 we make it faster and
avoid the need to truncate it afterwards.
…sconfigured

When `delay` or `max_delay` are less than 1, the Retry middleware currently crashes with
the following error:

    ** (FunctionClauseError) no function clause matching in :rand.uniform_s/2
    (stdlib 3.13) rand.erl:326: :rand.uniform_s/2
    (stdlib 3.13) rand.erl:299: :rand.uniform/1
    (tesla 1.3.3) lib/tesla/middleware/retry.ex:106: Tesla.Middleware.Retry.backoff/3
    (tesla 1.3.3) lib/tesla/middleware/retry.ex:94: Tesla.Middleware.Retry.retry/3

It happens because `:rand.uniform/1` requires a positive integer:

https://erlang.org/doc/man/rand.html#uniform-1

This change adjusts `max_delay` to `1` when it isn't positive and also adjusts
`delay` to make sure it is positive and smaller than `max_delay`.
Now we explicitly fail when either one of the following misconfigurations are detected:

* `delay` is not a positive integer.
* `max_delay` is not a positive integer.
* `max_retries` is not a non-negative integer.
@britto britto force-pushed the improve-retry-middleware-option-parsing branch from 537df80 to 30b8adf Compare August 24, 2020 13:30
@teamon teamon merged commit 65e2483 into elixir-tesla:master Aug 26, 2020
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

Successfully merging this pull request may close these issues.

2 participants