Skip to content

Commit 4d8419d

Browse files
committed
Data corruption fix
1 parent be2c948 commit 4d8419d

2 files changed

Lines changed: 32 additions & 6 deletions

File tree

bot.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import asyncio
22
import logging
3+
from logging.handlers import RotatingFileHandler
34
import os
45
from typing import Optional
56

@@ -13,14 +14,31 @@
1314
load_dotenv()
1415

1516
# Configure logging
17+
handlers: list[logging.Handler] = [logging.StreamHandler()]
18+
19+
# File logging is best-effort: some hosts have very limited disk.
20+
try:
21+
handlers.append(
22+
RotatingFileHandler(
23+
'modmail_bot.log',
24+
maxBytes=1_000_000,
25+
backupCount=2,
26+
encoding='utf-8',
27+
delay=True,
28+
)
29+
)
30+
except OSError:
31+
# Disk full / read-only FS / permission issue — continue with console logging.
32+
pass
33+
1634
logging.basicConfig(
1735
level=getattr(logging, os.getenv('LOG_LEVEL', 'INFO')),
1836
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
19-
handlers=[
20-
logging.FileHandler('modmail_bot.log'),
21-
logging.StreamHandler()
22-
]
37+
handlers=handlers,
2338
)
39+
40+
# Prevent noisy "--- Logging error ---" tracebacks in production.
41+
logging.raiseExceptions = False
2442
logger = logging.getLogger(__name__)
2543

2644
class ModMailBot(commands.Bot):

cogs/modmail.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,13 @@ async def _load_sessions_from_file(self):
9393
try:
9494
async with aiofiles.open(self.SESSIONS_FILE, "r", encoding="utf-8") as fh:
9595
content = await fh.read()
96-
data = json.loads(content)
96+
if not content.strip():
97+
return
98+
try:
99+
data = json.loads(content)
100+
except json.JSONDecodeError:
101+
logger.warning("modmail: sessions file is not valid JSON; ignoring")
102+
return
97103
for k, v in data.items():
98104
try:
99105
self.modmail_sessions[int(k)] = v
@@ -106,8 +112,10 @@ async def _persist_sessions_to_file(self):
106112
try:
107113
self.SESSIONS_FILE.parent.mkdir(parents=True, exist_ok=True)
108114
dumpable = {str(k): v for k, v in self.modmail_sessions.items()}
109-
async with aiofiles.open(self.SESSIONS_FILE, "w", encoding="utf-8") as fh:
115+
tmp_path = self.SESSIONS_FILE.with_suffix(self.SESSIONS_FILE.suffix + ".tmp")
116+
async with aiofiles.open(tmp_path, "w", encoding="utf-8") as fh:
110117
await fh.write(json.dumps(dumpable))
118+
tmp_path.replace(self.SESSIONS_FILE)
111119
except Exception:
112120
logger.exception("modmail: failed to persist sessions to file")
113121

0 commit comments

Comments
 (0)