fix(device-pool): scope primary key by host and thread through capability_tags
- pooled_devices primary key changed from device_id alone to (host_id, device_id), so two hosts reporting the same local device_id no longer crash sync_host_devices() with an uncaught sqlite3.IntegrityError. - Device gained a capability_tags field so DevicePool.sync_host_devices() can actually populate PooledDevice.capability_tags from a real host sync instead of always falling back to an empty list. openspec: device-pool capability, archived change cloud-runtime
This commit is contained in:
@@ -23,8 +23,19 @@ def _config(**overrides) -> CloudConfig:
|
||||
return CloudConfig(**base)
|
||||
|
||||
|
||||
def _device(device_id: str, *, status: str = "idle", driver_type: str = "wda") -> Device:
|
||||
return Device(id=device_id, status=status, driver_type=driver_type) # type: ignore[arg-type]
|
||||
def _device(
|
||||
device_id: str,
|
||||
*,
|
||||
status: str = "idle",
|
||||
driver_type: str = "wda",
|
||||
capability_tags: list[str] | None = None,
|
||||
) -> Device:
|
||||
return Device(
|
||||
id=device_id,
|
||||
status=status, # type: ignore[arg-type]
|
||||
driver_type=driver_type,
|
||||
capability_tags=list(capability_tags or []),
|
||||
)
|
||||
|
||||
|
||||
def test_new_host_sync_creates_registration_and_devices(tmp_path) -> None:
|
||||
@@ -140,3 +151,37 @@ def test_two_hosts_aggregate_into_one_listing(tmp_path) -> None:
|
||||
"b-dev-1": "host-b",
|
||||
"b-dev-2": "host-b",
|
||||
}
|
||||
|
||||
|
||||
def test_two_hosts_syncing_same_local_device_id_do_not_crash(tmp_path) -> None:
|
||||
"""Two hosts legitimately reporting the same local device_id are distinct
|
||||
devices in the pool; syncing both must succeed and yield two entries."""
|
||||
pool = DevicePool(CloudStore(tmp_path / "cloud.sqlite3"), _config())
|
||||
pool.sync_host_devices("host-a", [_device("dev-1", status="idle")], address="a")
|
||||
pool.sync_host_devices("host-b", [_device("dev-1", status="busy")], address="b")
|
||||
|
||||
devices = pool.list_devices()
|
||||
assert len(devices) == 2
|
||||
by_host = {d.host_id: d for d in devices}
|
||||
assert set(by_host) == {"host-a", "host-b"}
|
||||
assert by_host["host-a"].device_id == "dev-1"
|
||||
assert by_host["host-b"].device_id == "dev-1"
|
||||
assert by_host["host-a"].status == "idle"
|
||||
assert by_host["host-b"].status == "busy"
|
||||
|
||||
|
||||
def test_capability_tags_flow_from_device_to_pooled_device(tmp_path) -> None:
|
||||
pool = DevicePool(CloudStore(tmp_path / "cloud.sqlite3"), _config())
|
||||
pool.sync_host_devices(
|
||||
"host-a",
|
||||
[_device("dev-1", capability_tags=["ios", "physical"])],
|
||||
address="a",
|
||||
)
|
||||
|
||||
devices = pool.list_devices()
|
||||
assert len(devices) == 1
|
||||
assert devices[0].capability_tags == ["ios", "physical"]
|
||||
|
||||
fetched = pool.get_device("dev-1")
|
||||
assert fetched is not None
|
||||
assert fetched.capability_tags == ["ios", "physical"]
|
||||
|
||||
Reference in New Issue
Block a user