docs: retry tmdb requests
This commit is contained in:
parent
6f9739d4c8
commit
9dcf43052d
2 changed files with 137 additions and 0 deletions
92
docs/superpowers/plans/2026-04-05-tmdb-retry.md
Normal file
92
docs/superpowers/plans/2026-04-05-tmdb-retry.md
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
# TMDB Retry on Timeout / 5xx — Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Retry TMDB HTTP requests automatically on idle timeout and 5xx errors, without retrying legitimate "not found" cases.
|
||||||
|
|
||||||
|
**Architecture:** Wrap the default Symfony HttpClient with `RetryableHttpClient` (3 retries, exponential backoff) and inject it into `TMDBGateway` via service configuration. No PHP class changes needed.
|
||||||
|
|
||||||
|
**Tech Stack:** Symfony 8, `symfony/http-client` (already installed), `Symfony\Component\HttpClient\RetryableHttpClient`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Task 1: Configure RetryableHttpClient for TMDBGateway
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `config/services.yaml`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add the service definition to `config/services.yaml`**
|
||||||
|
|
||||||
|
Append the following inside the existing `services:` block (after the `App\:` resource declaration):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
app.http_client.tmdb:
|
||||||
|
class: Symfony\Component\HttpClient\RetryableHttpClient
|
||||||
|
arguments:
|
||||||
|
$client: '@http_client'
|
||||||
|
$maxRetries: 3
|
||||||
|
|
||||||
|
App\Gateway\TMDBGateway:
|
||||||
|
arguments:
|
||||||
|
$client: '@app.http_client.tmdb'
|
||||||
|
```
|
||||||
|
|
||||||
|
The full `services.yaml` should look like:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# yaml-language-server: $schema=../vendor/symfony/dependency-injection/Loader/schema/services.schema.json
|
||||||
|
|
||||||
|
imports:
|
||||||
|
- { resource: parameters.yml }
|
||||||
|
|
||||||
|
services:
|
||||||
|
_defaults:
|
||||||
|
autowire: true
|
||||||
|
autoconfigure: true
|
||||||
|
|
||||||
|
App\:
|
||||||
|
resource: '../src/'
|
||||||
|
|
||||||
|
app.http_client.tmdb:
|
||||||
|
class: Symfony\Component\HttpClient\RetryableHttpClient
|
||||||
|
arguments:
|
||||||
|
$client: '@http_client'
|
||||||
|
$maxRetries: 3
|
||||||
|
|
||||||
|
App\Gateway\TMDBGateway:
|
||||||
|
arguments:
|
||||||
|
$client: '@app.http_client.tmdb'
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Verify the container compiles without errors**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php bin/console cache:clear --env=test
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output ends with: `[OK] Cache for the "test" environment (debug) was successfully cleared.`
|
||||||
|
|
||||||
|
If you see a `ServiceNotFoundException` or `AutowiringFailedException`, double-check the indentation in `services.yaml` (YAML is indent-sensitive).
|
||||||
|
|
||||||
|
- [ ] **Step 3: Verify TMDBGateway is wired with RetryableHttpClient**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php bin/console debug:container App\\Gateway\\TMDBGateway
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: the `$client` argument shows `app.http_client.tmdb` (or `RetryableHttpClient`).
|
||||||
|
|
||||||
|
- [ ] **Step 4: Run the test suite to confirm nothing is broken**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
php bin/phpunit
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all tests pass (no failures, no errors). The existing tests mock `TMDBGateway` directly so they are unaffected by this wiring change.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add config/services.yaml
|
||||||
|
git commit -m "fix: retry TMDB requests on timeout and 5xx errors"
|
||||||
|
```
|
||||||
45
docs/superpowers/specs/2026-04-05-tmdb-retry-design.md
Normal file
45
docs/superpowers/specs/2026-04-05-tmdb-retry-design.md
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
# TMDB Retry on Timeout / 5xx
|
||||||
|
|
||||||
|
**Date:** 2026-04-05
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
During film import, `TMDBGateway` makes sequential HTTP calls to TMDB (one `searchMovie` + one `getMovieCredits` per new film). Under load, TMDB stops responding and Symfony's HttpClient raises an idle timeout exception, causing the film to be counted as failed.
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Retry TMDB requests automatically on transient failures (idle timeout, 5xx responses) without retrying on legitimate "not found" cases (empty search results).
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
|
||||||
|
Use Symfony's built-in `RetryableHttpClient`, which wraps any `HttpClientInterface` and transparently retries on:
|
||||||
|
- Network/transport errors (including idle timeout)
|
||||||
|
- HTTP 5xx responses
|
||||||
|
|
||||||
|
With exponential backoff: retry 1 → ~1s → retry 2 → ~2s → retry 3 → fail.
|
||||||
|
|
||||||
|
If all retries are exhausted, the exception propagates to `ImportFilmsBatchMessageHandler` which counts the film as `failedFilms` — unchanged behavior.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
|
||||||
|
**Only `config/services.yaml` is modified.** No PHP class changes.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
app.http_client.tmdb:
|
||||||
|
class: Symfony\Component\HttpClient\RetryableHttpClient
|
||||||
|
arguments:
|
||||||
|
$client: '@http_client'
|
||||||
|
$maxRetries: 3
|
||||||
|
|
||||||
|
App\Gateway\TMDBGateway:
|
||||||
|
arguments:
|
||||||
|
$client: '@app.http_client.tmdb'
|
||||||
|
```
|
||||||
|
|
||||||
|
`RetryableHttpClient` is part of `symfony/http-client` which is already a project dependency.
|
||||||
|
|
||||||
|
## Out of scope
|
||||||
|
|
||||||
|
- Rate limiting (not the cause of the current issue)
|
||||||
|
- Batch/concurrent TMDB requests (TMDB has no batch endpoint)
|
||||||
Loading…
Reference in a new issue