From d80073e504eea08e1991a0b759fd85a972b844da Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Mon, 23 Dec 2024 17:21:35 +0100 Subject: [PATCH 1/2] Use atomic writes for the storage file --- matter_server/server/storage.py | 12 +++++++++--- pyproject.toml | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/matter_server/server/storage.py b/matter_server/server/storage.py index eeb896aa..64a0e0bd 100644 --- a/matter_server/server/storage.py +++ b/matter_server/server/storage.py @@ -5,8 +5,11 @@ import asyncio import logging from pathlib import Path +import shutil from typing import TYPE_CHECKING, Any, cast +from atomicwrites import atomic_write + from ..common.helpers.json import JSON_DECODE_EXCEPTIONS, json_dumps, json_loads if TYPE_CHECKING: @@ -152,11 +155,14 @@ async def async_save(self) -> None: def do_save() -> None: # make backup before we write a new file - if self.filename.is_file(): - self.filename.replace(self.filename_backup) + self.filename_backup.unlink(True) + shutil.copy(self.filename, self.filename_backup) - with open(self.filename, "w", encoding="utf-8") as _file: + # use atomomic write to avoid corrupting the file + # if power is cut during write, we don't write a corrupted file + with atomic_write(self.filename, encoding="utf-8", overwrite=True) as _file: _file.write(json_dumps(self._data)) + LOGGER.debug("Saved data to persistent storage") async with self._save_lock: diff --git a/pyproject.toml b/pyproject.toml index c5786a04..13f45a87 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,6 +35,7 @@ server = [ "aiohttp==3.11.10", "aiorun==2024.8.1", "async-timeout==5.0.1", + "atomicwrites==1.4.0", "coloredlogs==15.0.1", "cryptography==44.0.0", "orjson==3.10.12", From 2222a7eda97c38f53fe83c6cc65e137e47104b44 Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Mon, 23 Dec 2024 17:44:17 +0100 Subject: [PATCH 2/2] Update pyproject.toml Co-authored-by: Stefan Agner --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 13f45a87..b4069fef 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,7 +35,7 @@ server = [ "aiohttp==3.11.10", "aiorun==2024.8.1", "async-timeout==5.0.1", - "atomicwrites==1.4.0", + "atomicwrites==1.4.1", "coloredlogs==15.0.1", "cryptography==44.0.0", "orjson==3.10.12",