Skip to content

[HttpClient] Expose retry count such that decorators can use this information. #60829

@jvdlaar

Description

@jvdlaar

Description

The RetryableHttpClient does the retrying logic and keeps a count of how many times the request has been retried. When decorating this class the retry count is not exposed. In our situation we are doing a http call and if it falls then we want to retry it with a number of different proxy servers. For this we want to know if it's the first, second, etc attempt at doing this call.

I can make the PR if wanted, just want to discuss first how such an approach would look like.

Example

This is currently the code section that retries the call:

            $context->setInfo('retry_count', $retryCount);
            $context->replaceRequest($method, $url, self::shiftBaseUri($options, $baseUris));
            $context->pause($delay / 1000);

            if ($retryCount >= $maxRetries) {
                $context->passthru();
            }

If it would add the count to the $options array then subsequent decorating clients can add logic like this:

declare(strict_types=1);

namespace Infrastructure\HttpClient;

use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
use Symfony\Component\HttpClient\DecoratorTrait;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;

#[AsDecorator('http_client.transport')]
class RetryAlteringProxyHttpClient implements HttpClientInterface
{
    use DecoratorTrait;

    public function __construct(
        HttpClientInterface $client,
        private readonly string $datacenterProxy,
        private readonly string $residentialProxy,
        private readonly string $unblockerProxy,
    ) {
        $this->client = $client;
    }

    /**
     * @param array<string, mixed> $options
     */
    public function request(string $method, string $url, array $options = []): ResponseInterface
    {
        $options['proxy'] = match ($options['retry_count']) {
            1 => $this->datacenterProxy,
            2 => $this->residentialProxy,
            3 => $this->unblockerProxy,
            default => null,
        };
        return $this->client->request($method, $url, $options);
    }

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions