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