Skip to content

fix: revalidate force_update targets before refresh #367

Description

@eXPerience83

Summary

The global pollenlevels.force_update service filters stale runtime locations while it builds its target list, but it later refreshes that precomputed list without checking whether each location is still configured.

At current main (19f020baf5a721d798e832d67302d64c0f01d944):

  1. handle_force_update_service() enumerates runtime locations and skips subentries that are already stale;
  2. active (entry, subentry_id, coordinator) tuples are appended to targets;
  3. _refresh_force_update_targets() groups that snapshot by parent;
  4. targets within a parent are refreshed sequentially without revalidating the subentry.

A September 2026 Home Assistant harness audit reproduced the race: if the second location is removed while the first location is still refreshing, the already-captured second coordinator is refreshed after its subentry has been deleted.

This violates the current lifecycle contract that pollenlevels.force_update must not refresh runtime coordinators whose location subentry has already been removed.

Existing deletion coverage proves that a location deleted before the service builds its target list is skipped. It does not cover deletion while the service call is already in progress.

Expected behavior

Immediately before refreshing each captured target, confirm that its location is still active for that parent. If the subentry has been removed, skip the stale coordinator.

The fix should use supported public Home Assistant/config-entry state and the existing stale-location semantics. Do not add private lifecycle hooks or force a reload solely to close this race.

Required regression coverage

Use deterministic event-controlled tests; do not depend on real network delays.

  • Parent has two active locations A and B.
  • force_update starts and A blocks during refresh.
  • B is removed while A is blocked.
  • A is released.
  • B's captured coordinator is not refreshed.
  • An active later sibling still refreshes when present.
  • Existing stale-at-service-start behavior remains correct.
  • Different parents remain independently refreshable.
  • Per-parent sequential refresh behavior remains unchanged.
  • Cancellation still propagates.
  • One coordinator failure remains locally isolated and does not prevent other active targets from being attempted.
  • No API key, full URL, or precise coordinates are exposed in failure logs.

Prefer at least one Home Assistant harness test that exercises the real service path and subentry lifecycle.

Constraints

  • No migration or registry-identity changes.
  • No entity ID, unique ID, device identifier, forecast, sensor, button, service-schema, or translation changes.
  • No unsupported/private Home Assistant hooks.
  • Do not remove the temporary stale-runtime diagnostics used after subentry deletion.
  • Do not change release metadata in the runtime-fix PR.

Validation

Run focused service/lifecycle tests first, then the complete locked suite and normal hosted gates.

Priority

P2 / runtime lifecycle correctness. The race is reproducible and directly contradicts the integration's documented stale-location refresh invariant.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions