Skip to content

fix(client): Improve resilience on transient network and auth failures - #2233

Open
dansrogers wants to merge 3 commits into
iMicknl:mainfrom
dansrogers:fix/transient-error-resilience
Open

fix(client): Improve resilience on transient network and auth failures#2233
dansrogers wants to merge 3 commits into
iMicknl:mainfrom
dansrogers:fix/transient-error-resilience

Conversation

@dansrogers

@dansrogers dansrogers commented Aug 26, 2026

Copy link
Copy Markdown

Summary & Overview

This pull request hardens OverkizClient against transient network drops, socket timeouts, and session expirations. It adds automatic exponential backoff retry decorators to register_event_listener(), introduces defensive error trapping in relogin() and refresh_listener() backoff callbacks, and ensures _event_listener_id is consistently invalidated and reset upon re-authentication.

Motivation & Problem Statement

During periods of network instability or Overkiz/Somfy cloud maintenance:

  1. Unhandled Network Drops during Event Registration: register_event_listener() was only decorated with @retry_on_concurrent_requests. A socket timeout, DNS failure, or transient 401 NotAuthenticatedError during listener registration raised an immediate exception instead of triggering retry backoff and automated session recovery.
  2. Backoff Callback Crashes: In relogin() and refresh_listener() backoff callbacks, if a network outage was ongoing when the backoff handler fired, unhandled ClientError, TimeoutError, or OSError exceptions crashed the backoff lifecycle prematurely.
  3. Stale Listener ID Retention: When re-authenticating after session eviction, a stale _event_listener_id could be retained, preventing clean event listener re-registration.

Changes Made

  • Backoff Retries on register_event_listener():
    Decorated register_event_listener() with @retry_on_connection_failure and @retry_on_auth_error alongside @retry_on_concurrent_requests in pyoverkiz/client.py.
  • Defensive Callback Handlers:
    Wrapped client.login() in relogin() and client.register_event_listener() in refresh_listener() with try/except (TimeoutError, ClientError, OSError) blocks to log warnings without terminating backoff sequences.
  • Listener ID Invalidation:
    • Added public helper reset_event_listener_id(self) -> None on OverkizClient.
    • Added explicit listener ID reset inside login() and within relogin() / refresh_listener() handlers.
  • Test Suite Expansion:
    • Added unit test coverage in tests/test_client.py for retry policies on register_event_listener and error handling during backoff callbacks.
    • Added comprehensive adversarial test suite in tests/test_adversarial_transport_auth.py covering cascading faults, prolonged outages, 502/503 server maintenance, and fast-failure on non-retryable bad credentials (BadCredentialsError).

Test Coverage & Verification

  • Full Test Suite: 570+ tests passed.
  • Static Analysis & Pre-commit: All 11 prek / ruff / mypy / ty checks passed cleanly.
============================= test session starts ==============================
collected 570 items
570 passed

Pre-commit & Static Analysis Verification Log

ruff check...............................................................Passed
ruff format..............................................................Passed
trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check json...............................................................Passed
check yaml...............................................................Passed
check for added large files..............................................Passed
don't commit to branch...................................................Passed
Lint GitHub Actions workflow files.......................................Passed
mypy.....................................................................Passed
ty check.................................................................Passed

Cross-Repository Context & Companion PR

  • Home Assistant Core Companion PR: fix(overkiz): Improve coordinator resilience against transient connectivity and auth errors home-assistant/core#180222
  • Defense-in-Depth Architecture:
    • Layer 1 (This PR - python-overkiz-api): Hardens low-level HTTP transport retries, session backoff, and event listener lifecycle management.
    • Layer 2 (Downstream - home-assistant/core): Implements coordinator state self-healing, execution TTL cleanup (EXECUTION_TTL = 60s), and full device state resynchronization (_need_full_resync).
  • Decoupled Deployment: This PR does not alter public API signatures and maintains 100% backward compatibility with existing downstream consumers. Downstream integrations can take advantage of these resilience enhancements immediately upon package update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant