- prices.fetchPrice wraps invoke('fetch_price', ...) with local rate-limit (1/2s), in-flight dedup, exp backoff on 5xx (2/4/8s, max 3 retries), no retry on 4xx/429, hard 100/session cap
- 9 vitest tests with vi.useFakeTimers() (happy, 401/403/404, 429 no-retry, 5xx retries, dedup, pacing, session cap)
- Annexe B i18n mapping wired (PriceError → balance.priceFetching.errors.* keys)
- Session cap checked before rate-limit/dedup; failures do not consume budget (MEDIUM decision)
Closes #156
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
26 lines
1.4 KiB
Markdown
26 lines
1.4 KiB
Markdown
# Decisions Log — /autopilot run of 2026-04-27
|
|
|
|
## Issue #156 — session cap budget policy (MEDIUM)
|
|
|
|
The 100-request session cap is checked BEFORE rate-limit enforcement and in-flight
|
|
deduplication. Successful fetches increment the counter; failures (4xx, 5xx, network)
|
|
do NOT consume the budget. Rationale: a user who hits a bad symbol or an auth error
|
|
should not have their session budget drained by error conditions outside their control.
|
|
This is the most user-friendly interpretation of "hard 100/session cap" while still
|
|
protecting against runaway loops.
|
|
|
|
## Issue #156 — __resetForTests helper exported from prices namespace (LOW)
|
|
|
|
The `prices.__resetForTests()` helper is exported alongside `fetchPrice`. This avoids
|
|
the need for `vi.resetModules()` + dynamic import between tests, which is flakier and
|
|
slower. The helper is named with `__` prefix to signal test-only usage. Alternative
|
|
considered: module-level export — rejected because it would pollute the public API
|
|
surface of balance.service outside the prices namespace.
|
|
|
|
## Issue #156 — rate-limit pacing test strategy (LOW)
|
|
|
|
The pacing test verifies that setTimeout is called with a positive delay for the 2nd
|
|
and 3rd concurrent calls, rather than asserting exact wall-clock timestamps via
|
|
Date.now(). This is because vi.useFakeTimers() advances Date.now() via timer
|
|
advancement, not automatically between microtasks. The spy approach is more resilient
|
|
to vitest internals and fake-timer edge cases.
|