span-panel-api 3.0.0b8__tar.gz → 3.0.0b9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/CHANGELOG.md +8 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/PKG-INFO +1 -1
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/pyproject.toml +1 -1
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/mqtt/client.py +14 -2
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_redispatch_on_reconnect.py +32 -1
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/.gitignore +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/LICENSE +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/README.md +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/__init__.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/_http.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/adapters.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/auth.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/const.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/detection.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/dispatch.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/exceptions.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/factory.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/models.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/mqtt/__init__.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/mqtt/async_client.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/mqtt/connection.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/mqtt/const.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/mqtt/models.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/phase_validation.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/protocol.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/py.typed +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/reference_payloads/README.md +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/reference_payloads/__init__.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/reference_payloads/homie_schema.json +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/schema_drift.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/conftest.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/configs/simulation_config_32_circuit.yaml +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/configs/simulation_config_40_circuit_with_battery.yaml +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/configs/simulation_config_8_tab_workshop.yaml +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/flat_wire.json +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/panelbench_unvalued_by_both.json +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/v2/README.md +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/v2/status.json +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/circuits.response.txt +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/panel.response.txt +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/soe.response.txt +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/status.response.txt +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_accumulator.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_adapters_discovery.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_adopted_control.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_adoption.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_async_mqtt_client.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_auth_and_homie_helpers.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_catalog_divergence.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_detection_auth.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_exceptions.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_factory_dispatch.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_field_metadata.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_live_flat_differential.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_mqtt_bridge.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_mqtt_client_connection.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_mqtt_connect_flow.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_mqtt_debounce.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_mqtt_homie.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_packaging.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_phase_validation_configs.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_phase_validation_errors.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_protocol_conformance.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_protocol_models.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_public_api_unchanged.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_reference_tree_values.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_generation_cross_check.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_migration_delta.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_adapter.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_against_simulator.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_charge_limit.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_circuits.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_conformance.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_connection_health.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_devices.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_discovery.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_panel.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_pcs.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_service_entrance.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_shed_forecast.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_snapshot.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_transport.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_provenance.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_zero_adapter.py +0 -0
- {span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_shared_http_client.py +0 -0
|
@@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [3.0.0b9]
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- **The retry window for a rebooting panel is actually widened this time.** b8 taught the schema fetch to treat a `502` as "not ready yet" but shipped with the old five attempts capped at eight seconds — about twenty-three seconds against a panel observed
|
|
12
|
+
taking four minutes to come back, still answering 502 when the broker returned. The widening was written, lost to a failed edit in the same change, and shipped without it; nothing failed, because catching the 502 and giving up early looks exactly like
|
|
13
|
+
working. Now twelve attempts backing off to thirty seconds, a little over four minutes, and pinned by a test that asserts the total window outlasts the observed reboot rather than checking the constants individually.
|
|
14
|
+
|
|
7
15
|
## [3.0.0b8]
|
|
8
16
|
|
|
9
17
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: span-panel-api
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0b9
|
|
4
4
|
Summary: A client library for SPAN Panel API
|
|
5
5
|
Project-URL: Homepage, https://github.com/SpanPanel/span-panel-api
|
|
6
6
|
Project-URL: Issues, https://github.com/SpanPanel/span-panel-api/issues
|
|
@@ -48,9 +48,21 @@ _CIRCUIT_NAMES_POLL_INTERVAL_S = 0.25
|
|
|
48
48
|
# Re-reading the schema after a suspected generation change. Bounded because the
|
|
49
49
|
# caller is a fire-and-forget task on a live connection, and generous enough to
|
|
50
50
|
# outlast a panel that is still binding its HTTP port after a restart.
|
|
51
|
-
_REDISPATCH_RETRY_ATTEMPTS =
|
|
51
|
+
_REDISPATCH_RETRY_ATTEMPTS = 12
|
|
52
52
|
_REDISPATCH_RETRY_INITIAL_S = 1.0
|
|
53
|
-
_REDISPATCH_RETRY_MAX_S =
|
|
53
|
+
_REDISPATCH_RETRY_MAX_S = 30.0
|
|
54
|
+
"""How long to wait for the panel's HTTP endpoint after it returns on MQTT.
|
|
55
|
+
|
|
56
|
+
Sized from a live firmware upgrade rather than guessed. The panel dropped MQTT at
|
|
57
|
+
11:22:07 and the broker was back at 11:26:15 -- four minutes -- and its HTTP
|
|
58
|
+
front end was still answering 502 at that moment. Five attempts capped at 8s
|
|
59
|
+
gives up after about 23 seconds, which is not the same order of magnitude as a
|
|
60
|
+
device that is still booting: catching the 502 buys nothing if the loop stops
|
|
61
|
+
before the panel is ready.
|
|
62
|
+
|
|
63
|
+
Twelve attempts backing off to 30s is a little over four minutes. Each one is a
|
|
64
|
+
single GET, and the panel is the only thing that can end the wait.
|
|
65
|
+
"""
|
|
54
66
|
|
|
55
67
|
|
|
56
68
|
def _metadata_for_the_log() -> tuple[list[str], str]:
|
|
@@ -31,7 +31,12 @@ from unittest.mock import patch
|
|
|
31
31
|
import pytest
|
|
32
32
|
|
|
33
33
|
from span_panel_api.exceptions import SpanPanelConnectionError, SpanPanelServerError
|
|
34
|
-
from span_panel_api.mqtt.client import
|
|
34
|
+
from span_panel_api.mqtt.client import (
|
|
35
|
+
_REDISPATCH_RETRY_ATTEMPTS,
|
|
36
|
+
_REDISPATCH_RETRY_INITIAL_S,
|
|
37
|
+
_REDISPATCH_RETRY_MAX_S,
|
|
38
|
+
SpanMqttClient,
|
|
39
|
+
)
|
|
35
40
|
from span_panel_api.mqtt.models import MqttClientConfig
|
|
36
41
|
|
|
37
42
|
from conftest import SERIAL
|
|
@@ -364,3 +369,29 @@ async def test_an_unexpected_failure_leaves_a_usable_message_rather_than_a_bare_
|
|
|
364
369
|
assert client.adapter is before
|
|
365
370
|
assert "Reload the integration" in caplog.text
|
|
366
371
|
assert "something nobody predicted" in caplog.text
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def test_the_retry_window_outlasts_a_real_panel_reboot() -> None:
|
|
375
|
+
"""Catching the 502 buys nothing if the loop gives up before the panel is ready.
|
|
376
|
+
|
|
377
|
+
Measured rather than assumed. On a live firmware upgrade the panel dropped
|
|
378
|
+
MQTT at 11:22:07 and the broker was back at 11:26:15 — four minutes — and its
|
|
379
|
+
HTTP front end was still answering 502 at that moment, which is when this
|
|
380
|
+
loop starts.
|
|
381
|
+
|
|
382
|
+
Pinned as a total because the three constants only mean something together,
|
|
383
|
+
and because the widening was written once, lost to a failed edit, and shipped
|
|
384
|
+
without it. Nothing failed: the 502 was caught and the loop still gave up
|
|
385
|
+
after twenty-three seconds. A test on the constants is the only thing that
|
|
386
|
+
would have noticed.
|
|
387
|
+
"""
|
|
388
|
+
delay = _REDISPATCH_RETRY_INITIAL_S
|
|
389
|
+
total = 0.0
|
|
390
|
+
for _ in range(_REDISPATCH_RETRY_ATTEMPTS):
|
|
391
|
+
total += delay
|
|
392
|
+
delay = min(delay * 2, _REDISPATCH_RETRY_MAX_S)
|
|
393
|
+
|
|
394
|
+
observed_reboot_s = 4 * 60
|
|
395
|
+
assert total >= observed_reboot_s, (
|
|
396
|
+
f"the retry window is {total:.0f}s, shorter than the {observed_reboot_s}s reboot " "this loop exists to wait out"
|
|
397
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/reference_payloads/README.md
RENAMED
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/src/span_panel_api/reference_payloads/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/fixtures/panelbench_unvalued_by_both.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/circuits.response.txt
RENAMED
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/panel.response.txt
RENAMED
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/soe.response.txt
RENAMED
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/simulation_fixtures/status.response.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_generation_cross_check.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_against_simulator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{span_panel_api-3.0.0b8 → span_panel_api-3.0.0b9}/tests/test_schema_one_connection_health.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|