From 7ee7acffbabcf2f036cdaabc7c7bda802561a2ff Mon Sep 17 00:00:00 2001 From: Geert Meersman <geertmeersman+github@gmail.com> Date: Tue, 8 Oct 2024 10:55:50 +0200 Subject: [PATCH 1/3] fix: async for blocking file system operations --- custom_components/robonect/__init__.py | 38 +++++++++++++++++++++----- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/custom_components/robonect/__init__.py b/custom_components/robonect/__init__.py index 9518af0..d2ab1c0 100644 --- a/custom_components/robonect/__init__.py +++ b/custom_components/robonect/__init__.py @@ -1,5 +1,6 @@ """The Robonect component.""" +import asyncio from datetime import timedelta import logging from pathlib import Path @@ -206,18 +207,41 @@ async def job(service: ServiceCall) -> bool: async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: """Handle removal of pubsub subscriptions created during config flow.""" - storage = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}/{entry.entry_id}") - storage.unlink(True) - storage_dir = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}") - if storage_dir.is_dir() and not any(storage_dir.iterdir()): - storage_dir.rmdir() + + # Define blocking file operations + def remove_storage_files(): + storage = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}/{entry.entry_id}") + storage.unlink(True) # Unlink (delete) the storage file + + storage_dir = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}") + # If the directory exists and is empty, remove it + if storage_dir.is_dir() and not any(storage_dir.iterdir()): + storage_dir.rmdir() + + # Offload the file system operations to a thread + await asyncio.to_thread(remove_storage_files) async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" - unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) - if unload_ok: + + # Unload the platforms first + if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): hass.data[DOMAIN].pop(entry.entry_id) + + # Define blocking file operations + def remove_storage_files(): + storage = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}/{entry.entry_id}") + storage.unlink(True) # Unlink (delete) the storage file + + storage_dir = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}") + # If the directory exists and is empty, remove it + if storage_dir.is_dir() and not any(storage_dir.iterdir()): + storage_dir.rmdir() + + # Offload the file system operations to a thread + await asyncio.to_thread(remove_storage_files) + return unload_ok From cf27ddd0c03693c379be138b4eaf367b1a980887 Mon Sep 17 00:00:00 2001 From: Geert Meersman <geertmeersman+github@gmail.com> Date: Tue, 8 Oct 2024 11:03:53 +0200 Subject: [PATCH 2/3] fix: async for blocking file system operations --- custom_components/robonect/__init__.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/custom_components/robonect/__init__.py b/custom_components/robonect/__init__.py index d2ab1c0..8b704af 100644 --- a/custom_components/robonect/__init__.py +++ b/custom_components/robonect/__init__.py @@ -1,6 +1,5 @@ """The Robonect component.""" -import asyncio from datetime import timedelta import logging from pathlib import Path @@ -219,7 +218,7 @@ def remove_storage_files(): storage_dir.rmdir() # Offload the file system operations to a thread - await asyncio.to_thread(remove_storage_files) + await hass.async_add_executor_job(remove_storage_files) async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -240,7 +239,7 @@ def remove_storage_files(): storage_dir.rmdir() # Offload the file system operations to a thread - await asyncio.to_thread(remove_storage_files) + await hass.async_add_executor_job(remove_storage_files) return unload_ok From 206806f458acb6d5a50292761396bd78900fc82f Mon Sep 17 00:00:00 2001 From: Geert Meersman <geertmeersman+github@gmail.com> Date: Tue, 8 Oct 2024 11:09:35 +0200 Subject: [PATCH 3/3] fix: storage.unlink(missing_ok=True) --- custom_components/robonect/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/robonect/__init__.py b/custom_components/robonect/__init__.py index 8b704af..a1eae24 100644 --- a/custom_components/robonect/__init__.py +++ b/custom_components/robonect/__init__.py @@ -210,7 +210,7 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: # Define blocking file operations def remove_storage_files(): storage = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}/{entry.entry_id}") - storage.unlink(True) # Unlink (delete) the storage file + storage.unlink(missing_ok=True) # Unlink (delete) the storage file storage_dir = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}") # If the directory exists and is empty, remove it @@ -231,7 +231,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: # Define blocking file operations def remove_storage_files(): storage = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}/{entry.entry_id}") - storage.unlink(True) # Unlink (delete) the storage file + storage.unlink(missing_ok=True) # Unlink (delete) the storage file storage_dir = Path(f"{hass.config.path(STORAGE_DIR)}/{DOMAIN}") # If the directory exists and is empty, remove it