feat(config): retry validate_config() after a failure, self-healing (#4379) - #4394
feat(config): retry validate_config() after a failure, self-healing (#4379)#4394chalfontchubby wants to merge 1 commit into
Conversation
…pringfall2008#4379) validate_config() only ran at startup and on config change, never periodically - so a transient race (a slow-starting integration's sensor not populated yet at that exact moment) left a stale "config invalid" status sitting until the next manual restart, even though apps.yaml was actually fine moments later. Adds validate_config_schedule_retry()/validate_config_check_retry(): after any validate_config() call that finds errors, arms a retry sequence (default 2 retries, 1 minute apart, both configurable via apps.yaml). Retries only ever start following an actual failure - a clean validation never triggers one. A retry that comes back clean clears the sequence immediately; one that's still failing decrements the counter and reschedules, giving up quietly once retries are exhausted. Checked once per tick from the existing 15-second update_time_loop() rather than registering a new scheduler primitive - this AppDaemon-shim codebase only has run_every(), no one-shot delayed-callback API to build on. New apps.yaml-only settings (APPS_SCHEMA, not HA-exposed): validate_config_retries (default 2, 0 disables), validate_config_retry_minutes (default 1).
There was a problem hiding this comment.
🟡 Not ready to approve
The retry scheduler does not reliably disable/cancel an already-armed retry sequence when validate_config_retries is set to 0, and the new test doesn’t currently catch that case.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.
Pull request overview
This PR adds a self-healing retry mechanism for apps.yaml configuration validation so transient startup races (e.g., sensors not populated yet during an HA restart) can clear stale “config invalid” status without requiring a manual restart.
Changes:
- Adds
validate_config_schedule_retry()andvalidate_config_check_retry()to retry validation only after a failure, driven by the existing 15-secondupdate_time_loop(). - Introduces new
apps.yamlsettingsvalidate_config_retriesandvalidate_config_retry_minutes(documented and added to schema). - Adds a new unit test (
test_validate_config_retry) and registers it in the test runner.
File summaries
| File | Description |
|---|---|
| docs/apps-yaml.md | Documents the new config validation retry settings and behavior. |
| apps/predbat/unit_test.py | Registers the new validate_config_retry test in the test runner. |
| apps/predbat/tests/test_validate_config.py | Adds coverage for the retry scheduling/check logic via a new test. |
| apps/predbat/predbat.py | Implements retry state, scheduling, and periodic checking; wires it into existing validate call sites and the 15s loop. |
| apps/predbat/config.py | Adds schema entries for the two new apps.yaml settings. |
Review details
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.
| if errors: | ||
| retries = self.get_arg("validate_config_retries", 2) | ||
| if retries > 0: | ||
| self.validate_config_retries_remaining = retries | ||
| retry_minutes = self.get_arg("validate_config_retry_minutes", 1) | ||
| self.validate_config_next_retry_time = self.now_utc + timedelta(minutes=retry_minutes) | ||
| else: | ||
| self.validate_config_retries_remaining = 0 | ||
| self.validate_config_next_retry_time = None |
| # validate_config_retries: 0 disables the feature entirely | ||
| my_predbat.args["validate_config_retries"] = 0 | ||
| my_predbat.validate_config_schedule_retry(1) | ||
| assert my_predbat.validate_config_retries_remaining == 0, "validate_config_retries=0 should disable retries" | ||
|
|
Summary
validate_config()only ran at startup and when config actually changed - never periodically. If a sensor mapped inapps.yamlwasn't populated yet at that exact moment (e.g. a slower-starting integration during an HA restart), Predbat correctly logged a config error - but if that sensor came good on its own a few seconds later, nothing re-validated, so the stale "config invalid" status just sat there until the next manual restart.validate_config_schedule_retry()(called right after everyvalidate_config()call site with its error count) andvalidate_config_check_retry()(checked once per tick from the existing 15-secondupdate_time_loop()).balance_inverters_seconds):validate_config_retries(default 2, set to 0 to disable and revert to the old behaviour) andvalidate_config_retry_minutes(default 1).hass.py) only hasrun_every(), no one-shot delayed-callback API, so this piggybacks on the existing 15-second loop rather than registering a new timer.Test plan
./run_pre_commit(viacoverage/run_pre_commit) - all hooks passtest_validate_config_retrycovers: clean validation never arms a retry; default retry count/interval; no premature retry before the due time; still-failing retries decrement and reschedule; exhausting retries gives up cleanly (and doesn't fire again afterwards); a successful retry clears the sequence immediately rather than just decrementing;validate_config_retries: 0disables the feature; custom retry count/interval are respectedtest_validate_configstill passes unchanged./run_all --quick) passesAddresses #4379