fix(k1): retire terminal control before read-only recovery
This commit is contained in:
@@ -17994,7 +17994,15 @@ class XgridsK1CompatibilityService:
|
|||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"retained PREPARED STOP owner changed before topology commit"
|
"retained PREPARED STOP owner changed before topology commit"
|
||||||
)
|
)
|
||||||
self._retire_application_control_for_network_change()
|
# Verify owns a read-only replacement of the local control
|
||||||
|
# generation. A terminal device fault may leave that dead
|
||||||
|
# generation in ``failed`` even though its worker/socket are
|
||||||
|
# already gone. Retire only that local owner; the physical
|
||||||
|
# ledger remains unresolved until fresh DeviceInfo/Status
|
||||||
|
# evidence below classifies it.
|
||||||
|
self._retire_application_control_for_network_change(
|
||||||
|
allow_terminal_failure=True,
|
||||||
|
)
|
||||||
projected_intent_id = self._apply_read_only_device_topology(
|
projected_intent_id = self._apply_read_only_device_topology(
|
||||||
transport_ref=actual_transport_ref,
|
transport_ref=actual_transport_ref,
|
||||||
connection_mode=requested_mode,
|
connection_mode=requested_mode,
|
||||||
|
|||||||
@@ -21481,6 +21481,22 @@ def test_public_physical_recovery_refreshes_stale_dhcp_then_classifies_without_w
|
|||||||
)
|
)
|
||||||
|
|
||||||
restarted, runtime = service_with_fake_runtime(tmp_path)
|
restarted, runtime = service_with_fake_runtime(tmp_path)
|
||||||
|
retirement_permissions: list[bool] = []
|
||||||
|
|
||||||
|
class TerminalDeviceFaultControl(FakeInteractiveControlSession):
|
||||||
|
def retire_for_network_change(
|
||||||
|
self,
|
||||||
|
*,
|
||||||
|
allow_terminal_failure: bool = False,
|
||||||
|
**kwargs: object,
|
||||||
|
) -> dict[str, object]:
|
||||||
|
retirement_permissions.append(allow_terminal_failure)
|
||||||
|
if not allow_terminal_failure:
|
||||||
|
raise ApplicationAcceptanceError(
|
||||||
|
"terminal device fault requires explicit local retirement"
|
||||||
|
)
|
||||||
|
return super().retire_for_network_change(**kwargs)
|
||||||
|
|
||||||
association_probe = FakeHostWifiAssociationProbe("a" * 64)
|
association_probe = FakeHostWifiAssociationProbe("a" * 64)
|
||||||
restarted._host_wifi_association_probe = association_probe # type: ignore[assignment] # noqa: SLF001
|
restarted._host_wifi_association_probe = association_probe # type: ignore[assignment] # noqa: SLF001
|
||||||
capture = _durable_status_capture(device_id="test-ble-transport")
|
capture = _durable_status_capture(device_id="test-ble-transport")
|
||||||
@@ -21550,6 +21566,10 @@ def test_public_physical_recovery_refreshes_stale_dhcp_then_classifies_without_w
|
|||||||
assert configured_recovery["required_connection_mode"] == "bridge"
|
assert configured_recovery["required_connection_mode"] == "bridge"
|
||||||
assert configured_recovery["requires_live_gatt_validation"] is True
|
assert configured_recovery["requires_live_gatt_validation"] is True
|
||||||
|
|
||||||
|
restarted._application_control_session = TerminalDeviceFaultControl( # type: ignore[assignment] # noqa: SLF001
|
||||||
|
initial_state="failed"
|
||||||
|
)
|
||||||
|
|
||||||
verified = asyncio.run(restarted.verify_connection(ConnectionVerifyRequest()))
|
verified = asyncio.run(restarted.verify_connection(ConnectionVerifyRequest()))
|
||||||
|
|
||||||
after = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
|
after = restarted._physical_command_ledger.snapshot().record # noqa: SLF001
|
||||||
@@ -21576,6 +21596,7 @@ def test_public_physical_recovery_refreshes_stale_dhcp_then_classifies_without_w
|
|||||||
facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS,
|
facade_module.COMMAND_BOUND_ASSOCIATION_TIMEOUT_SECONDS,
|
||||||
]
|
]
|
||||||
assert command_edges == []
|
assert command_edges == []
|
||||||
|
assert retirement_permissions == [True]
|
||||||
assert runtime.start_calls == []
|
assert runtime.start_calls == []
|
||||||
assert runtime.stop_calls == 0
|
assert runtime.stop_calls == 0
|
||||||
assert verified["k1_ip"] == "192.168.68.51"
|
assert verified["k1_ip"] == "192.168.68.51"
|
||||||
|
|||||||
Reference in New Issue
Block a user