mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
Reduce latency in storage by making the tasks eager (#111500)
* Reduce latancy to load storage by making the task eager This changes the semantics a bit under the hood because it can raise sooner which means we do not store the task as _load_task if it raises right away. That means concurrent calls that result in failure are likely to try again now which will be a tiny performance hit for this case. * fix * will now finish in time
This commit is contained in:
parent
e74e1e3008
commit
78bb6dbe75
@ -133,12 +133,16 @@ class Store(Generic[_T]):
|
|||||||
Will ensure that when a call comes in while another one is in progress,
|
Will ensure that when a call comes in while another one is in progress,
|
||||||
the second call will wait and return the result of the first call.
|
the second call will wait and return the result of the first call.
|
||||||
"""
|
"""
|
||||||
if self._load_task is None:
|
if self._load_task:
|
||||||
self._load_task = self.hass.async_create_task(
|
return await self._load_task
|
||||||
self._async_load(), f"Storage load {self.key}"
|
|
||||||
)
|
|
||||||
|
|
||||||
return await self._load_task
|
load_task = self.hass.async_create_task(
|
||||||
|
self._async_load(), f"Storage load {self.key}", eager_start=True
|
||||||
|
)
|
||||||
|
if not load_task.done():
|
||||||
|
# Only set the load task if it didn't complete immediately
|
||||||
|
self._load_task = load_task
|
||||||
|
return await load_task
|
||||||
|
|
||||||
async def _async_load(self) -> _T | None:
|
async def _async_load(self) -> _T | None:
|
||||||
"""Load the data and ensure the task is removed."""
|
"""Load the data and ensure the task is removed."""
|
||||||
@ -318,7 +322,9 @@ class Store(Generic[_T]):
|
|||||||
# wrote. Reschedule the timer to the next write time.
|
# wrote. Reschedule the timer to the next write time.
|
||||||
self._async_reschedule_delayed_write(self._next_write_time)
|
self._async_reschedule_delayed_write(self._next_write_time)
|
||||||
return
|
return
|
||||||
self.hass.async_create_task(self._async_callback_delayed_write())
|
self.hass.async_create_task(
|
||||||
|
self._async_callback_delayed_write(), eager_start=True
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_ensure_final_write_listener(self) -> None:
|
def _async_ensure_final_write_listener(self) -> None:
|
||||||
|
@ -115,7 +115,7 @@ async def test_loading_parallel(
|
|||||||
results = await asyncio.gather(store.async_load(), store.async_load())
|
results = await asyncio.gather(store.async_load(), store.async_load())
|
||||||
|
|
||||||
assert results[0] == MOCK_DATA
|
assert results[0] == MOCK_DATA
|
||||||
assert results[0] is results[1]
|
assert results[1] == MOCK_DATA
|
||||||
assert caplog.text.count(f"Loading data for {store.key}")
|
assert caplog.text.count(f"Loading data for {store.key}")
|
||||||
|
|
||||||
|
|
||||||
@ -795,6 +795,25 @@ async def test_os_error_is_fatal(tmpdir: py.path.local) -> None:
|
|||||||
):
|
):
|
||||||
await store.async_load()
|
await store.async_load()
|
||||||
|
|
||||||
|
# Verify second load is also failing
|
||||||
|
with pytest.raises(OSError), patch(
|
||||||
|
"homeassistant.helpers.storage.json_util.load_json", side_effect=OSError
|
||||||
|
):
|
||||||
|
await store.async_load()
|
||||||
|
|
||||||
|
await hass.async_stop(force=True)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_json_load_failure(tmpdir: py.path.local) -> None:
|
||||||
|
"""Test json load raising HomeAssistantError."""
|
||||||
|
async with async_test_home_assistant() as hass:
|
||||||
|
tmp_storage = await hass.async_add_executor_job(tmpdir.mkdir, "temp_storage")
|
||||||
|
hass.config.config_dir = tmp_storage
|
||||||
|
|
||||||
|
store = storage.Store(
|
||||||
|
hass, MOCK_VERSION_2, MOCK_KEY, minor_version=MOCK_MINOR_VERSION_1
|
||||||
|
)
|
||||||
|
await store.async_save({"hello": "world"})
|
||||||
base_os_error = OSError()
|
base_os_error = OSError()
|
||||||
base_os_error.errno = 30
|
base_os_error.errno = 30
|
||||||
home_assistant_error = HomeAssistantError()
|
home_assistant_error = HomeAssistantError()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user