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

Feature | Add exponential backoff for retry interval #304

Merged
merged 5 commits into from
Dec 2, 2023

Conversation

binaryfire
Copy link
Contributor

Exponential backoff helps with unreliable APIs. A second failed attempt usually means the service is overloaded or there's a problem with network connectivity. In both cases it's best to pause for a longer period before retrying again. This PR adds an exponential backoff option for retries.

@binaryfire
Copy link
Contributor Author

@Sammyjo20 I think this is all that's needed? Don't have time to test today, but I can test tomorrow if you'd like.

@Sammyjo20
Copy link
Member

Hey @binaryfire yep that's pretty much what I was thinking - we'd need to add it to the sendAndRetry method and maybe in the HasTries trait for connector/request retries?

@binaryfire
Copy link
Contributor Author

@Sammyjo20 Changed it to a class property, same as $tries and $retryInterval.

@boryn
Copy link
Contributor

boryn commented Oct 1, 2023

Hi @binaryfire! That's great idea!

What about possibility to specify exact seconds of delay, like it is in Laravel's jobs?

public function backoff(): array
{
    return [1, 5, 10];
}

How will backoff behave in case of pagination? Will it keep in memory what has been fetched so far and try to merge it with the remaining, eventually successful tries?

@binaryfire
Copy link
Contributor Author

binaryfire commented Oct 1, 2023

Hi @boryn. This PR just adds the option to use exponentially increasing intervals instead of fixed intervals with Saloon’s retry system. It doesn’t change the underlying system in any way.

Manually specifying intervals in an array is different to exponential (auto-calculated) backoff. That’s beyond the scope of what I need. But you could create a PR for that if you need it.

@Sammyjo20
Copy link
Member

Looks great @binaryfire - many thanks for contributing to this. Are you happy to write a test for the manual sendAndRetry and the class-based retry logic, similar to what I've already written files for? I know that you said you might be free to write one tomorrow - we might be able to get this out before v3 (about 5-6pm BST)

@binaryfire
Copy link
Contributor Author

binaryfire commented Oct 2, 2023

@Sammyjo20 Happy to contribute! I’m not familiar with writing tests that use mocking though, so I can’t help with that part.

@Sammyjo20
Copy link
Member

Hey @binaryfire no worries at all! I'm going to merge this PR after Saloon v3 launch just to have some extra time to work with it as I don't want to rush it :)

@binaryfire
Copy link
Contributor Author

Hey @Sammyjo20 :) Any thoughts on this PR? I’m still using my own code for interacting with some less reliable APIs. Would love to swap that out for Saloon integrations.

@Sammyjo20
Copy link
Member

Hey @binaryfire I will take a look this weekend for you! 🔥

@boryn
Copy link
Contributor

boryn commented Nov 24, 2023

It would be great to see this exponential backoff built into Saloon.

Though I still wonder if in general retries work for single pagination calls? So if let's say out of 10 pages, the page number 3 fails, will it be retried and later all the results from 10 pages combined and returned?

@Sammyjo20 Sammyjo20 changed the title Add exponential backoff Feature | Add exponential backoff for retry interval Dec 2, 2023
@Sammyjo20
Copy link
Member

Sammyjo20 commented Dec 2, 2023

Hey @binaryfire I hope you are well!

I've added a test for the exponential backoff - please could you review my test and make sure it's still okay?

I had to change the backoff algorithm slightly because I think it was calculating it wrong.

Request 1 (No delay)
Request 2 (2000ms delay) - Double 1000ms original delay
Request 3 (4000ms delay)
Request 4 (8000ms delay)

It was taking 14 seconds for the test to pass.

I've changed it so that the first failure (interval retry) is considered the first attempt for the backoff algorithm so now it's:

Request 1 (No delay)
Request 2 (1000ms delay) - Original Delay
Request 3 (2000ms delay)
Request 4 (4000ms delay)

Is that correct?

@binaryfire
Copy link
Contributor Author

Hey @Sammyjo20. Yep that makes sense! Looks good.

@Sammyjo20
Copy link
Member

Wooo! Any objections for release? Thank you for coming up with this idea!

@binaryfire
Copy link
Contributor Author

@Sammyjo20 All looks good to me! Time to pull the trigger 🎉

@Sammyjo20 Sammyjo20 merged commit 8a1b163 into saloonphp:v3 Dec 2, 2023
14 checks passed
@boryn
Copy link
Contributor

boryn commented Dec 2, 2023

Hi @Sammyjo20 and @binaryfire!

It's not clear to me. Do automatic retries handle synchronous pagination calls? If let's say we have pages 1, 2, 3, 4 to fetch and if the call for the page 2 has a connection problem, will it be automatically retried for $tries times (where tries $tries are defined in connector)? And after success, the following pages 3, 4 will be fetched as well? And if page 2 failes, the whole pagination "batch" failes?

@Sammyjo20
Copy link
Member

Hey @boryn I believe for synchronous requests you're right - if it fails, it will be retried and if you have defined an interval, it will automatically back off for each subsequent attempt.

With a synchronous paginator, each request is run one after another, so for example one could have 3 attempts before it's considered "successful" to the paginator and then it move onto the next page/request.

Yes, if page 2 exhausts all attempts, then the whole paginator will fail, but the attempts are reset on a per-request basis.

@boryn
Copy link
Contributor

boryn commented Dec 3, 2023

@Sammyjo20 it would be great to add this info to documentation. Because on the 'retrying-requests' page it's not mentioned that is supports pagination and at pagination it's not written that it supports retries :)

@Sammyjo20
Copy link
Member

@boryn I haven’t got round to it yet but I will update the docs soon.

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.

3 participants