Here's the PR body:
## Summary
Checkout called the FX provider on every cart render. During Friday's sale that went over the provider's 1,000 requests/minute limit, and checkout started returning 429 errors. `get_rate` now keeps each rate in memory for 5 minutes.
```diff
get_rate(base, quote)
+ if base:quote was fetched less than 300s ago
+ return the saved rate
GET api.example-fx.com/latest
raise on HTTP error
+ save rate for base:quote with time.monotonic()
return rate
Evidence
-
Before:
pytestshows 14 passed. Everyget_ratecall makes its own HTTP request.
After:pytestshows 15 passed. Addedtest_get_rate_uses_cache_within_ttl:get_rate("USD", "EUR") get_rate("USD", "EUR") assert provider was called once
Merge Danger
Door: two-way
The cache only lives in memory, with nothing persisted and no schema change. To roll back, revert the commit.
Blast Radius: checkout
- Stale rates: prices can use a rate up to 5 minutes old. Confirm that's acceptable for checkout pricing.
- Per-process cache: each worker keeps its own cache. Provider calls per 5 minutes are roughly workers × currency pairs, so the limit could still be reached with many workers.
- No size limit or eviction: this is fine for a fixed set of currency pairs.
- No locking: two requests that miss the cache at the same moment can both call the provider. The only cost is an extra request.
- Test isolation:
_cacheis module-level, so it carries over between tests unless a fixture clears it.
- **No `GLOSSARY.md`:** the repo doesn't have one, so I used the wording from your context and the code.
- **Check this before merging:** `test_get_rate_returns_quote` already caches `USD:EUR`. If nothing clears `_cache` between tests, the new test should see 0 provider calls and fail. Since it passes, the `mock_get` fixture probably resets the cache, but I couldn't see the fixture to confirm. If it doesn't, the test result depends on the order tests run in, and I'd add an autouse fixture that calls `_cache.clear()`.
Real run recorded with claude-code / claude-opus-5-5. Output is shown verbatim, unmodified. The only change: the trial machine's temp-folder path was replaced with a generic placeholder.
Qué hace
Escribe una descripción de pull request que sea rápida de revisar, en tres partes.
Cómo funciona
- Resumen: el recurso visual más pequeño que deja claro el punto. Puede ser pseudocódigo, un árbol de llamadas, un árbol de componentes, un árbol de archivos, un diagrama de Mermaid o un boceto de diff, colocado junto al texto breve al que respalda.
- Evidencia: un antes y un después concretos. Las capturas de pantalla son lo mejor cuando el cambio es visual; si no, la prueba exacta que pasa de fallar a pasar.
- Peligro de merge: si el cambio es una puerta de un solo sentido o de doble sentido (¿se puede revertir?), y su radio de impacto, como desplazamientos de layout o roturas para los consumidores.
- Omite preámbulos y mantiene la prosa breve, usando la terminología de tu
GLOSSARY.mdsi el repositorio tiene uno.
Ideal para
Pull requests en los que quienes revisan necesitan ver qué cambió y cuánto riesgo implica.
Conviene saber
En nuestra prueba, también señaló un riesgo que no podía verificar a partir del diff, una cuestión de aislamiento de pruebas, en lugar de ocultarlo.
Solo contiene archivos de instrucciones: sin scripts y sin acceso a la red. El menú de recursos visuales de la sección Resumen está adaptado de la Skill show-me de Dex Horthy (HumanLayer, licencia MIT); el paquete incluye esa licencia como LICENSE-show-me y una nota en CREDITS.md. Solo escribe texto y no ejecuta git ni abre el pull request. El paquete también contiene el LICENSE MIT original y agents/openai.yaml (nombre para mostrar de Codex).