Rate-limit config files writing
This commit is contained in:
		@@ -3,7 +3,7 @@ import json
 | 
				
			|||||||
import logging as log
 | 
					import logging as log
 | 
				
			||||||
from dataclasses import dataclass, field
 | 
					from dataclasses import dataclass, field
 | 
				
			||||||
from pathlib import Path
 | 
					from pathlib import Path
 | 
				
			||||||
from typing import Any, Dict
 | 
					from typing import Any, Dict, Optional
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import aiofiles
 | 
					import aiofiles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -21,6 +21,13 @@ class ConfigFile:
 | 
				
			|||||||
    backend:  Backend = field(repr=False)
 | 
					    backend:  Backend = field(repr=False)
 | 
				
			||||||
    filename: str     = field()
 | 
					    filename: str     = field()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _to_write: Optional[str] = field(init=False, default=None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __post_init__(self) -> None:
 | 
				
			||||||
 | 
					        asyncio.ensure_future(self._write_loop())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def path(self) -> Path:
 | 
					    def path(self) -> Path:
 | 
				
			||||||
        return Path(self.backend.app.appdirs.user_config_dir) / self.filename
 | 
					        return Path(self.backend.app.appdirs.user_config_dir) / self.filename
 | 
				
			||||||
@@ -36,11 +43,20 @@ class ConfigFile:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def write(self, data) -> None:
 | 
					    async def write(self, data) -> None:
 | 
				
			||||||
        async with WRITE_LOCK:
 | 
					        self._to_write = data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async def _write_loop(self) -> None:
 | 
				
			||||||
        self.path.parent.mkdir(parents=True, exist_ok=True)
 | 
					        self.path.parent.mkdir(parents=True, exist_ok=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while True:
 | 
				
			||||||
 | 
					            if self._to_write is not None:
 | 
				
			||||||
                async with aiofiles.open(self.path, "w") as new:
 | 
					                async with aiofiles.open(self.path, "w") as new:
 | 
				
			||||||
                await new.write(data)
 | 
					                    await new.write(self._to_write)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self._to_write = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await asyncio.sleep(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@dataclass
 | 
					@dataclass
 | 
				
			||||||
@@ -73,6 +89,7 @@ class JSONConfigFile(ConfigFile):
 | 
				
			|||||||
class Accounts(JSONConfigFile):
 | 
					class Accounts(JSONConfigFile):
 | 
				
			||||||
    filename: str = "accounts.json"
 | 
					    filename: str = "accounts.json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def any_saved(self) -> bool:
 | 
					    async def any_saved(self) -> bool:
 | 
				
			||||||
        return bool(await self.read())
 | 
					        return bool(await self.read())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -101,6 +118,7 @@ class Accounts(JSONConfigFile):
 | 
				
			|||||||
class UISettings(JSONConfigFile):
 | 
					class UISettings(JSONConfigFile):
 | 
				
			||||||
    filename: str = "settings.json"
 | 
					    filename: str = "settings.json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async def default_data(self) -> JsonData:
 | 
					    async def default_data(self) -> JsonData:
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            "alertOnMessageForMsec": 4000,
 | 
					            "alertOnMessageForMsec": 4000,
 | 
				
			||||||
@@ -159,6 +177,7 @@ class UISettings(JSONConfigFile):
 | 
				
			|||||||
class UIState(JSONConfigFile):
 | 
					class UIState(JSONConfigFile):
 | 
				
			||||||
    filename: str = "state.json"
 | 
					    filename: str = "state.json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def path(self) -> Path:
 | 
					    def path(self) -> Path:
 | 
				
			||||||
        return Path(self.backend.app.appdirs.user_data_dir) / self.filename
 | 
					        return Path(self.backend.app.appdirs.user_data_dir) / self.filename
 | 
				
			||||||
@@ -176,6 +195,7 @@ class UIState(JSONConfigFile):
 | 
				
			|||||||
class History(JSONConfigFile):
 | 
					class History(JSONConfigFile):
 | 
				
			||||||
    filename: str = "history.json"
 | 
					    filename: str = "history.json"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def path(self) -> Path:
 | 
					    def path(self) -> Path:
 | 
				
			||||||
        return Path(self.backend.app.appdirs.user_data_dir) / self.filename
 | 
					        return Path(self.backend.app.appdirs.user_data_dir) / self.filename
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user