Set the translations cache under the lock (#42470)

This commit is contained in:
J. Nick Koston 2020-10-27 16:02:38 -05:00 committed by GitHub
parent 30a3fe69bc
commit 5ca4b4cd0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 17 deletions

View file

@ -294,7 +294,8 @@ async def async_get_translations(
} }
async with lock: 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) cache = hass.data.get(TRANSLATION_FLATTEN_CACHE)
if cache is None: if cache is None:
cache = hass.data[TRANSLATION_FLATTEN_CACHE] = FlatCache(hass) cache = hass.data[TRANSLATION_FLATTEN_CACHE] = FlatCache(hass)
@ -317,24 +318,24 @@ async def async_get_translations(
results = await asyncio.gather(*tasks) results = await asyncio.gather(*tasks)
if category == "state": if category == "state":
resource_func = merge_resources resource_func = merge_resources
else: else:
resource_func = build_resources resource_func = build_resources
resources = flatten(resource_func(results[0], components, category)) resources = flatten(resource_func(results[0], components, category))
if language != "en": if language != "en":
base_resources = flatten(resource_func(results[1], components, category)) base_resources = flatten(resource_func(results[1], components, category))
resources = {**base_resources, **resources} resources = {**base_resources, **resources}
if integration is not None: # The cache must be set while holding the lock
pass if use_cache:
elif config_flow: 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) loaded_comp_resources = await async_get_translations(hass, language, category)
resources.update(loaded_comp_resources) resources.update(loaded_comp_resources)
else:
assert cache is not None
cache.async_set_cache(language, category, resources)
return resources return resources

View file

@ -170,9 +170,12 @@ async def test_get_translations_while_loading_components(hass):
integration = Mock(file_path=pathlib.Path(__file__)) integration = Mock(file_path=pathlib.Path(__file__))
integration.name = "Component 1" integration.name = "Component 1"
hass.config.components.add("component1") hass.config.components.add("component1")
load_count = 0
def mock_load_translation_files(files): def mock_load_translation_files(files):
"""Mock load translation files.""" """Mock load translation files."""
nonlocal load_count
load_count += 1
# Mimic race condition by loading a component during setup # Mimic race condition by loading a component during setup
setup_component(hass, "persistent_notification", {}) setup_component(hass, "persistent_notification", {})
return {"component1": {"hello": "world"}} return {"component1": {"hello": "world"}}
@ -187,11 +190,15 @@ async def test_get_translations_while_loading_components(hass):
"homeassistant.helpers.translation.async_get_integration", "homeassistant.helpers.translation.async_get_integration",
return_value=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", "component.component1.hello": "world",
} }
assert load_count == 1
async def test_get_translation_categories(hass): async def test_get_translation_categories(hass):