refactor(github): make GitHubProvider fetch non-blocking

startFetch() fires the GraphQL POST and returns the response without
reading it; resolveFetch() does the .toArray()/parse/log work that
used to happen inline right after the request.
This commit is contained in:
2026-07-07 13:31:15 +02:00
parent 11bec43bbe
commit 9f3c54afd1
+13 -6
View File
@@ -9,6 +9,7 @@ use IDCI\Bundle\GraphQLClientBundle\Client\GraphQLApiClientRegistryInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
/**
* Fetches the last 365 days of contributions from the GitHub GraphQL API.
@@ -46,10 +47,7 @@ final class GitHubProvider implements ProviderInterface
])->getContent();
}
/**
* @return array<string, int> date (Y-m-d) => contribution count
*/
public function fetch(): array
public function startFetch(): ResponseInterface
{
$this->logger->debug('GitHubProvider: fetching contributions', ['user' => $this->username]);
@@ -75,15 +73,24 @@ final class GitHubProvider implements ProviderInterface
// GitHub's GraphQL API requires application/json — the bundle's built-in
// transport sends form_params, so we use Symfony HttpClient here instead.
$response = $this->client->request('POST', self::GRAPHQL_URL, [
// request() doesn't block; the response is read in resolveFetch() so
// multiple providers' requests can be in flight at once.
return $this->client->request('POST', self::GRAPHQL_URL, [
'headers' => [
'Authorization' => "Bearer {$this->token}",
'Content-Type' => 'application/json',
],
'json' => ['query' => $query],
]);
}
$data = $response->toArray();
/**
* @return array<string, int> date (Y-m-d) => contribution count
*/
public function resolveFetch(mixed $handle): array
{
/** @var ResponseInterface $handle */
$data = $handle->toArray();
if (isset($data['errors'])) {
throw new ServiceUnavailableHttpException(null, 'GitHub GraphQL error: ' . json_encode($data['errors']));