Skip to content

feat: data persistence and rate limit handling - #82

Merged
jmdevita merged 2 commits into
mainfrom
fix/issue-81-rate-limit-and-persistence
Apr 25, 2026
Merged

feat: data persistence and rate limit handling#82
jmdevita merged 2 commits into
mainfrom
fix/issue-81-rate-limit-and-persistence

Conversation

@jmdevita

Copy link
Copy Markdown
Owner

Summary

Adds Store-backed caching and HTTP 429 handling so the integration survives rapid HA restarts without hitting the Parcel API's 20 req/hr rate limit.

  • Persists API responses to .storage/parcelapp_cache_* via HA's Store helper — restarts reuse cached data when fresh enough
  • _async_setup() lifecycle hook loads cache before first poll, skipping the API call entirely if data is younger than update_interval
  • Explicit 429 detection on both deliveries and carrier codes endpoints — parses Retry-After header, stretches polling interval, serves stale data instead of failing
  • Generic error fallback returns cached data when available instead of raising UpdateFailed
  • RestoreEntity mixin on all 4 sensors for immediate state on boot
  • Sensors now use entry.runtime_data instead of hass.data[DOMAIN]

Changed files

  • coordinator.py — Store, _async_setup(), 429 handling, cache fallback
  • sensor.py — RestoreEntity + async_added_to_hass() on all sensors
  • const.pySTORAGE_KEY, STORAGE_VERSION, DEFAULT_RETRY_AFTER_SECONDS
  • __init__.py — runtime_data assignment moved before platform setup

New files

  • tests/test_persistence.py — 9 tests covering cache load/save, 429 with/without cache, retry-after parsing, interval reset

## Summary

Adds Store-backed caching and HTTP 429 handling so the integration
survives rapid HA restarts without hitting the Parcel API's 20 req/hr
rate limit.

- Persists API responses to `.storage/parcelapp_cache_*` via HA's
  `Store` helper — restarts reuse cached data when fresh enough
- `_async_setup()` lifecycle hook loads cache before first poll,
  skipping the API call entirely if data is younger than update_interval
- Explicit 429 detection on both deliveries and carrier codes endpoints
  — parses `Retry-After` header, stretches polling interval, serves
  stale data instead of failing
- Generic error fallback returns cached data when available instead of
  raising `UpdateFailed`
- `RestoreEntity` mixin on all 4 sensors for immediate state on boot
- Sensors now use `entry.runtime_data` instead of `hass.data[DOMAIN]`

## Changed files
- `coordinator.py` — Store, `_async_setup()`, 429 handling, cache fallback
- `sensor.py` — RestoreEntity + `async_added_to_hass()` on all sensors
- `const.py` — `STORAGE_KEY`, `STORAGE_VERSION`, `DEFAULT_RETRY_AFTER_SECONDS`
- `__init__.py` — runtime_data assignment moved before platform setup

## New files
- `tests/test_persistence.py` — 9 tests covering cache load/save,
  429 with/without cache, retry-after parsing, interval reset
@jmdevita
jmdevita merged commit 069c6fc into main Apr 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant