Skip to content

Commit 9e182bb

Browse files
committed
CRAI suggestions
1 parent 49618e5 commit 9e182bb

File tree

1 file changed

+26
-5
lines changed

1 file changed

+26
-5
lines changed

plugwise_usb/helpers/cache.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,13 @@
66
from contextlib import suppress
77
import logging
88
from os import (
9+
close as os_close,
910
fsync as os_fsync,
1011
getenv as os_getenv,
1112
getpid as os_getpid,
1213
name as os_name,
14+
open as os_open,
15+
O_RDONLY as os_O_RDONLY,
1316
)
1417
from os.path import expanduser as os_path_expand_user, join as os_path_join
1518
from pathlib import Path
@@ -27,6 +30,15 @@
2730
_LOGGER = logging.getLogger(__name__)
2831

2932

33+
def _fsync_parent_dir(path: Path) -> None:
34+
"""Helper function to ensure persisted on POSIX."""
35+
fd = os_open(str(path), os_O_RDONLY)
36+
try:
37+
os_fsync(fd)
38+
finally:
39+
os_close(fd)
40+
41+
3042
class PlugwiseCache:
3143
"""Base class to cache plugwise information."""
3244

@@ -98,15 +110,15 @@ async def write_cache(self, data: dict[str, str], rewrite: bool = False) -> None
98110
if not rewrite:
99111
current_data = await self.read_cache()
100112

101-
processed_keys: list[str] = []
113+
processed_keys: set[str] = set()
102114
data_to_write: list[str] = []
103115

104116
# Prepare data exactly as in original implementation
105117
for _cur_key, _cur_val in current_data.items():
106118
_write_val = _cur_val
107119
if _cur_key in data:
108120
_write_val = data[_cur_key]
109-
processed_keys.append(_cur_key)
121+
processed_keys.add(_cur_key)
110122
data_to_write.append(f"{_cur_key}{CACHE_KEY_SEPARATOR}{_write_val}\n")
111123

112124
# Write remaining new data
@@ -129,16 +141,25 @@ async def write_cache(self, data: dict[str, str], rewrite: bool = False) -> None
129141
file=str(temp_path),
130142
mode="w",
131143
encoding=UTF8,
144+
newline="\n",
132145
) as temp_file:
133146
await temp_file.writelines(data_to_write)
134147
await temp_file.flush()
135148
# Ensure data reaches disk before rename
136-
loop = get_running_loop()
137-
await loop.run_in_executor(None, os_fsync, temp_file.fileno())
149+
try:
150+
loop = get_running_loop()
151+
await loop.run_in_executor(None, os_fsync, temp_file.fileno())
152+
except (OSError, TypeError, AttributeError):
153+
# If fsync fails due to fileno() issues or other problems,
154+
# continue without it. flush() provides reasonable durability.
155+
pass
138156

139157
# Atomic rename (overwrites atomically on all platforms)
140158
temp_path.replace(cache_file_path)
141159
temp_path = None # Successfully renamed
160+
if os_name != "nt":
161+
# Ensure directory entry is persisted on POSIX
162+
await loop.run_in_executor(None, _fsync_parent_dir, cache_file_path.parent)
142163

143164
if not self._cache_file_exists:
144165
self._cache_file_exists = True
@@ -165,7 +186,7 @@ async def read_cache(self) -> dict[str, str]:
165186
"""Return current data from cache file."""
166187
if not self._initialized:
167188
raise CacheError(
168-
f"Unable to save cache. Initialize cache file '{self._file_name}' first."
189+
f"Unable to read cache. Initialize cache file '{self._file_name}' first."
169190
)
170191
current_data: dict[str, str] = {}
171192
if self._cache_file is None:

0 commit comments

Comments
 (0)