From 5ca4b4cd0f8fef9dcb1e21c4ebdffbadc3b8d706 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Tue, 27 Oct 2020 16:02:38 -0500 Subject: [PATCH] Set the translations cache under the lock (#42470) --- homeassistant/helpers/translation.py | 31 ++++++++++++++-------------- tests/helpers/test_translation.py | 11 ++++++++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/homeassistant/helpers/translation.py b/homeassistant/helpers/translation.py index 53d808a5a85..0cc07c93ff9 100644 --- a/homeassistant/helpers/translation.py +++ b/homeassistant/helpers/translation.py @@ -294,7 +294,8 @@ async def async_get_translations( } async with lock: - if integration is None and not config_flow: + use_cache = integration is None and not config_flow + if use_cache: cache = hass.data.get(TRANSLATION_FLATTEN_CACHE) if cache is None: cache = hass.data[TRANSLATION_FLATTEN_CACHE] = FlatCache(hass) @@ -317,24 +318,24 @@ async def async_get_translations( results = await asyncio.gather(*tasks) - if category == "state": - resource_func = merge_resources - else: - resource_func = build_resources + if category == "state": + resource_func = merge_resources + else: + resource_func = build_resources - resources = flatten(resource_func(results[0], components, category)) + resources = flatten(resource_func(results[0], components, category)) - if language != "en": - base_resources = flatten(resource_func(results[1], components, category)) - resources = {**base_resources, **resources} + if language != "en": + base_resources = flatten(resource_func(results[1], components, category)) + resources = {**base_resources, **resources} - if integration is not None: - pass - elif config_flow: + # The cache must be set while holding the lock + if use_cache: + assert cache is not None + cache.async_set_cache(language, category, resources) + + if config_flow: loaded_comp_resources = await async_get_translations(hass, language, category) resources.update(loaded_comp_resources) - else: - assert cache is not None - cache.async_set_cache(language, category, resources) return resources diff --git a/tests/helpers/test_translation.py b/tests/helpers/test_translation.py index 440b3d75439..ff089de8777 100644 --- a/tests/helpers/test_translation.py +++ b/tests/helpers/test_translation.py @@ -170,9 +170,12 @@ async def test_get_translations_while_loading_components(hass): integration = Mock(file_path=pathlib.Path(__file__)) integration.name = "Component 1" hass.config.components.add("component1") + load_count = 0 def mock_load_translation_files(files): """Mock load translation files.""" + nonlocal load_count + load_count += 1 # Mimic race condition by loading a component during setup setup_component(hass, "persistent_notification", {}) return {"component1": {"hello": "world"}} @@ -187,11 +190,15 @@ async def test_get_translations_while_loading_components(hass): "homeassistant.helpers.translation.async_get_integration", return_value=integration, ): - translations = await translation.async_get_translations(hass, "en", "hello") + tasks = [ + translation.async_get_translations(hass, "en", "hello") for _ in range(5) + ] + all_translations = await asyncio.gather(*tasks) - assert translations == { + assert all_translations[0] == { "component.component1.hello": "world", } + assert load_count == 1 async def test_get_translation_categories(hass):