Stage 06.1 - journal management UI, export and system menu redesign
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
# app/src/storage/repositories/journal.py
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
@@ -20,10 +22,10 @@ class JournalRepository:
|
||||
with get_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
'''
|
||||
"""
|
||||
INSERT INTO journal_events (level, event_type, message, payload_json)
|
||||
VALUES (%s, %s, %s, %s::jsonb)
|
||||
''',
|
||||
""",
|
||||
(
|
||||
level.upper().strip(),
|
||||
event_type.strip(),
|
||||
@@ -32,32 +34,69 @@ class JournalRepository:
|
||||
),
|
||||
)
|
||||
|
||||
def list_recent_events(self, limit: int = 10) -> list[dict[str, str]]:
|
||||
def _parse_payload(self, raw_payload: Any) -> dict[str, Any] | None:
|
||||
if raw_payload is None:
|
||||
return None
|
||||
|
||||
if isinstance(raw_payload, dict):
|
||||
return raw_payload
|
||||
|
||||
if isinstance(raw_payload, str):
|
||||
try:
|
||||
parsed = json.loads(raw_payload)
|
||||
return parsed if isinstance(parsed, dict) else None
|
||||
except json.JSONDecodeError:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
def list_recent_events(self, limit: int = 10) -> list[dict[str, Any]]:
|
||||
with get_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
'''
|
||||
SELECT id, created_at, level, event_type, message
|
||||
"""
|
||||
SELECT id, created_at, level, event_type, message, payload_json
|
||||
FROM journal_events
|
||||
ORDER BY created_at DESC, id DESC
|
||||
LIMIT %s
|
||||
''',
|
||||
""",
|
||||
(limit,),
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
|
||||
items: list[dict[str, str]] = []
|
||||
for row in rows:
|
||||
items.append(
|
||||
{
|
||||
"id": str(row[0]),
|
||||
"created_at": str(row[1]),
|
||||
"level": str(row[2]),
|
||||
"event_type": str(row[3]),
|
||||
"message": str(row[4]),
|
||||
}
|
||||
)
|
||||
return items
|
||||
return [self._row_to_dict(row) for row in rows]
|
||||
|
||||
def list_recent_with_offset(self, limit: int, offset: int) -> list[dict[str, Any]]:
|
||||
with get_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT id, created_at, level, event_type, message, payload_json
|
||||
FROM journal_events
|
||||
ORDER BY created_at DESC, id DESC
|
||||
LIMIT %s OFFSET %s
|
||||
""",
|
||||
(limit, offset),
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
|
||||
return [self._row_to_dict(row) for row in rows]
|
||||
|
||||
def list_export_rows(self, limit: int = 5000) -> list[dict[str, Any]]:
|
||||
with get_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT id, created_at, level, event_type, message, payload_json
|
||||
FROM journal_events
|
||||
ORDER BY created_at DESC, id DESC
|
||||
LIMIT %s
|
||||
""",
|
||||
(limit,),
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
|
||||
return [self._row_to_dict(row) for row in rows]
|
||||
|
||||
def count_events(self) -> int:
|
||||
with get_connection() as connection:
|
||||
@@ -67,26 +106,35 @@ class JournalRepository:
|
||||
|
||||
return int(row[0]) if row else 0
|
||||
|
||||
def list_recent_with_offset(self, limit: int, offset: int):
|
||||
def delete_all(self) -> int:
|
||||
with get_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("DELETE FROM journal_events")
|
||||
deleted_count = cursor.rowcount
|
||||
|
||||
return int(deleted_count or 0)
|
||||
|
||||
def _row_to_dict(self, row: tuple[Any, ...]) -> dict[str, Any]:
|
||||
return {
|
||||
"id": str(row[0]),
|
||||
"created_at": str(row[1]),
|
||||
"level": str(row[2]),
|
||||
"event_type": str(row[3]),
|
||||
"message": str(row[4]),
|
||||
"payload": self._parse_payload(row[5]),
|
||||
}
|
||||
|
||||
|
||||
def delete_older_than_days(self, days: int) -> int:
|
||||
with get_connection() as connection:
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT created_at, level, event_type, message
|
||||
FROM journal_events
|
||||
ORDER BY created_at DESC
|
||||
LIMIT %s OFFSET %s
|
||||
DELETE FROM journal_events
|
||||
WHERE created_at < NOW() - (%s * INTERVAL '1 day')
|
||||
""",
|
||||
(limit, offset),
|
||||
(days,),
|
||||
)
|
||||
rows = cursor.fetchall()
|
||||
deleted_count = cursor.rowcount
|
||||
|
||||
return [
|
||||
{
|
||||
"created_at": str(r[0]),
|
||||
"level": r[1],
|
||||
"event_type": r[2],
|
||||
"message": r[3],
|
||||
}
|
||||
for r in rows
|
||||
]
|
||||
return deleted_count
|
||||
Reference in New Issue
Block a user