Skip to content

v2.6.1: single scheduler, live options reload, visible failures, ut1 backoff - #2

Merged
Lexorius merged 1 commit into
mainfrom
fix/v2.6.1-runtime
Sep 25, 2026
Merged

Lexorius merged 1 commit into
mainfrom
fix/v2.6.1-runtime

Conversation

@Lexorius

Copy link
Copy Markdown
Owner

Summary

Runtime fixes from the full code review (items #5, #6, #8, #10). This changes observable behaviour — please test in a live instance before it is tagged.

# Fix File
5 Every entity was updated twice: should_poll returned True, so HA polled every sensor every 30 s on top of the plugin timer. Now False; a tick is skipped while the previous one still runs. sensor.py
6 Options saved under Configure only applied after a restart — no update_listener was registered. Now the entry reloads automatically. The options flow passes entry.options through unchanged so only one reload fires. __init__.py, config_flow.py
10 Failed update() calls were logged at DEBUG only and the state went stale silently. Now: first failure of a streak → WARNING, further → DEBUG, recovery → INFO; entity becomes unavailable after 3 consecutive failures. sensor.py
8 ut1 retried the IERS API every second (10 s timeout each, WARNING each time) while it was down, with a new ClientSession per call. Now HA's shared session + exponential backoff 60 s → 1 h cap, warn once per streak. calendars/ut1.py
— _CONFIG_ENTRIES cleaned on unload; broad except in async_setup_entry removed (errors propagate to HA); dead async_reload_entry removed. sensor.py, __init__.py

Behaviour changes users may notice

  • Entities can now show unavailable if a plugin keeps failing (previously: last stale value). The cause is in the log as a WARNING from the first failure on.
  • Saving options reloads the entry — entities disappear for a moment and come back.
  • Hourly calendars now change last_updated only hourly, not every 30 s.

Test plan

  • python -m py_compile + ruff check --select E,F,W,I --ignore E501 on all touched files
  • Stubbed-HA unit test, 33 assertions: should_poll False; warn-once / unavailable-after-3 / recovery / counter reset; skip-if-busy with an overlapping slow update; no state write after removal; ut1 backoff 60→120→…→3600 cap, no network call during backoff, recovery resets, HTTP 500 counts as failure
  • Discovery smoke test from 2.6.0.7 still green (45 calendars, all importable)
  • Live HA (reviewer): install from this branch, restart, then:
    1. Open an entry's Configure, change an option, save → entry reloads by itself, new value visible without restart
    2. Check an hourly calendar's last_updated in Developer Tools → States: should no longer bump every 30 s
    3. grep -c "Updated German Rescue DTG" home-assistant.log over a fixed window: roughly 1/s, not ~1.03/s (the old 30-s platform poll on top)
    4. Log stays free of custom_components.alternative_time WARNING/ERROR

Installing the branch for testing

curl -L https://github.com/Lexorius/alternative_time/archive/refs/heads/fix/v2.6.1-runtime.zip -o at.zip
unzip -q at.zip
cp -r alternative_time-fix-v2.6.1-runtime/custom_components/alternative_time /config/custom_components/

then restart HA. (HACS cannot install a branch while the repo has releases.)

Tag v2.6.1 + release follow after the live check.

🤖 Generated with Claude Code

…backoff

Runtime fixes from the code review. Unlike 2.6.0.7 this changes observable
behaviour (see CHANGELOG "Hinweis").

sensor.py
- should_poll returned True, so HA polled every entity every 30 s on top
  of the plugin's own timer: hourly calendars recomputed every 30 s, and
  sync update() could run concurrently in two executor threads on the
  same instance. should_poll is now False; the timer is the only
  scheduler. A tick is skipped while the previous one is still running.
- _async_timer_tick: first failure of a streak -> WARNING (traceback at
  DEBUG), further consecutive failures -> DEBUG, recovery -> INFO. After
  3 consecutive failures the entity is marked unavailable via
  _attr_available (the hard-coded `available -> True` override is gone;
  HA's Entity.available is inherited). No state write when hass is None.
- forget_config_entry(): _CONFIG_ENTRIES was never emptied.

__init__.py
- Register entry.add_update_listener -> async_reload; options saved
  under "Configure" now apply immediately instead of after a restart.
- Let async_forward_entry_setups failures propagate instead of the
  broad except that returned False and hid the cause.
- Remove async_reload_entry: bypassed HA's entry state machine, no callers.

config_flow.py
- OptionsFlow passes entry.options through unchanged on finish so the
  data write (which already fires the listener) is the only reload.

calendars/ut1.py
- Use HA's shared aiohttp session (async_get_clientsession) instead of a
  new ClientSession per fetch.
- Exponential backoff after a failed IERS fetch: 60 s doubling to a
  3600 s cap. Previously the 1-second update retried (10 s timeout,
  serialised by the lock) and logged a WARNING every second while the
  API was down. WARNING once per streak and once per hour at the cap;
  INFO on recovery.

Verified locally with a stubbed-HA unit test (33 assertions): warn-once,
unavailable-after-3, recovery, skip-if-busy, no-write-after-removal,
ut1 backoff growth/cap/no-refetch/recovery/HTTP-error; plus the
discovery smoke test from 2.6.0.7 (45 calendars, all importable).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Lexorius
Lexorius merged commit cd2ba81 into main Sep 25, 2026
3 checks passed
@Lexorius
Lexorius deleted the fix/v2.6.1-runtime branch September 25, 2026 23:07
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