From 9dcf43052d17b9b3f7ee2684f22cb3e65bebb950 Mon Sep 17 00:00:00 2001 From: thibaud-lclr Date: Sun, 5 Apr 2026 23:37:37 +0200 Subject: [PATCH] docs: retry tmdb requests --- .../plans/2026-04-05-tmdb-retry.md | 92 +++++++++++++++++++ .../specs/2026-04-05-tmdb-retry-design.md | 45 +++++++++ 2 files changed, 137 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-05-tmdb-retry.md create mode 100644 docs/superpowers/specs/2026-04-05-tmdb-retry-design.md diff --git a/docs/superpowers/plans/2026-04-05-tmdb-retry.md b/docs/superpowers/plans/2026-04-05-tmdb-retry.md new file mode 100644 index 0000000..3ebfcec --- /dev/null +++ b/docs/superpowers/plans/2026-04-05-tmdb-retry.md @@ -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" +``` diff --git a/docs/superpowers/specs/2026-04-05-tmdb-retry-design.md b/docs/superpowers/specs/2026-04-05-tmdb-retry-design.md new file mode 100644 index 0000000..9010939 --- /dev/null +++ b/docs/superpowers/specs/2026-04-05-tmdb-retry-design.md @@ -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)