Avoid writing HomeKit state to disk unless its missing (#111970)

This commit is contained in:
J. Nick Koston 2024-03-21 09:19:55 -10:00 committed by GitHub
parent d0708b5b32
commit 9a863638f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 27 additions and 6 deletions

View File

@ -550,8 +550,13 @@ class HomeKit:
self._reset_lock = asyncio.Lock() self._reset_lock = asyncio.Lock()
self._cancel_reload_dispatcher: CALLBACK_TYPE | None = None self._cancel_reload_dispatcher: CALLBACK_TYPE | None = None
def setup(self, async_zeroconf_instance: AsyncZeroconf, uuid: str) -> None: def setup(self, async_zeroconf_instance: AsyncZeroconf, uuid: str) -> bool:
"""Set up bridge and accessory driver.""" """Set up bridge and accessory driver.
Returns True if data was loaded from disk
Returns False if the persistent data was not loaded
"""
assert self.iid_storage is not None assert self.iid_storage is not None
persist_file = get_persist_fullpath_for_entry_id(self.hass, self._entry_id) persist_file = get_persist_fullpath_for_entry_id(self.hass, self._entry_id)
self.driver = HomeDriver( self.driver = HomeDriver(
@ -573,6 +578,9 @@ class HomeKit:
# as pyhap uses a random one until state is restored # as pyhap uses a random one until state is restored
if os.path.exists(persist_file): if os.path.exists(persist_file):
self.driver.load() self.driver.load()
return True
return False
async def async_reset_accessories(self, entity_ids: Iterable[str]) -> None: async def async_reset_accessories(self, entity_ids: Iterable[str]) -> None:
"""Reset the accessory to load the latest configuration.""" """Reset the accessory to load the latest configuration."""
@ -842,7 +850,9 @@ class HomeKit:
# Avoid gather here since it will be I/O bound anyways # Avoid gather here since it will be I/O bound anyways
await self.aid_storage.async_initialize() await self.aid_storage.async_initialize()
await self.iid_storage.async_initialize() await self.iid_storage.async_initialize()
await self.hass.async_add_executor_job(self.setup, async_zc_instance, uuid) loaded_from_disk = await self.hass.async_add_executor_job(
self.setup, async_zc_instance, uuid
)
assert self.driver is not None assert self.driver is not None
if not await self._async_create_accessories(): if not await self._async_create_accessories():
@ -850,8 +860,12 @@ class HomeKit:
self._async_register_bridge() self._async_register_bridge()
_LOGGER.debug("Driver start for %s", self._name) _LOGGER.debug("Driver start for %s", self._name)
await self.driver.async_start() await self.driver.async_start()
async with self.hass.data[PERSIST_LOCK_DATA]: if not loaded_from_disk:
await self.hass.async_add_executor_job(self.driver.persist) # If the state was not loaded from disk, it means this is the
# first time the bridge is ever starting up. In this case, we
# need to make sure its persisted to disk.
async with self.hass.data[PERSIST_LOCK_DATA]:
await self.hass.async_add_executor_job(self.driver.persist)
self.status = STATUS_RUNNING self.status = STATUS_RUNNING
if self.driver.state.paired: if self.driver.state.paired:

View File

@ -765,9 +765,16 @@ async def test_homekit_start(
f"{PATH_HOMEKIT}.async_show_setup_message" f"{PATH_HOMEKIT}.async_show_setup_message"
) as mock_setup_msg, patch( ) as mock_setup_msg, patch(
"pyhap.accessory_driver.AccessoryDriver.async_start" "pyhap.accessory_driver.AccessoryDriver.async_start"
) as hk_driver_start: ) as hk_driver_start, patch(
"pyhap.accessory_driver.AccessoryDriver.load"
) as load_mock, patch(
"pyhap.accessory_driver.AccessoryDriver.persist"
) as persist_mock, patch(f"{PATH_HOMEKIT}.os.path.exists", return_value=True):
await homekit.async_stop()
await homekit.async_start() await homekit.async_start()
assert load_mock.called
assert not persist_mock.called
device = device_registry.async_get_device( device = device_registry.async_get_device(
identifiers={(DOMAIN, entry.entry_id, BRIDGE_SERIAL_NUMBER)} identifiers={(DOMAIN, entry.entry_id, BRIDGE_SERIAL_NUMBER)}
) )