Debug JSONL updates.

This commit is contained in:
Leo Vasanko
2026-01-23 23:49:11 +00:00
parent 17961c2bca
commit 5585651e57
3 changed files with 16 additions and 40 deletions
+4 -13
View File
@@ -47,23 +47,16 @@ def cleanup() -> None:
async def flush() -> None:
"""Write all pending database changes to disk."""
import sys
from paskia.db.operations import _db
if _db is None:
_logger.warning("flush() called but _db is None")
print("[DB] flush() called but _db is None", file=sys.stderr)
return
pending_count = len(_db._pending_changes)
if pending_count > 0:
print(f"[DB] flush() called with {pending_count} pending changes, db_path={_db.db_path}", file=sys.stderr)
await flush_changes(_db.db_path, _db._pending_changes)
async def _background_loop():
"""Background task that periodically flushes changes and cleans up."""
import sys
print("[DB] Background loop starting", file=sys.stderr)
_logger.info("Background loop starting")
# Run cleanup immediately on startup to clear old expired items
cleanup()
@@ -94,13 +87,12 @@ async def _background_loop():
async def start_background():
"""Start the background flush/cleanup task."""
import sys
global _background_task
# Check if task exists but is no longer running (e.g., after uvicorn reload)
if _background_task is not None:
if _background_task.done():
print(f"[DB] Previous background task was done, restarting", file=sys.stderr)
_logger.debug("Previous background task was done, restarting")
_background_task = None
else:
# Task exists and is running - but might be in a dead event loop
@@ -109,18 +101,17 @@ async def start_background():
loop = asyncio.get_running_loop()
task_loop = _background_task.get_loop()
if loop is not task_loop:
print(f"[DB] Background task in different event loop, restarting", file=sys.stderr)
_logger.debug("Background task in different event loop, restarting")
_background_task = None
except Exception as e:
print(f"[DB] Error checking background task loop: {e}, restarting", file=sys.stderr)
_logger.debug("Error checking background task loop: %s, restarting", e)
_background_task = None
if _background_task is None:
_background_task = asyncio.create_task(_background_loop())
_logger.info("Database background task started")
print("[DB] Database background task started", file=sys.stderr)
else:
print(f"[DB] Background task already running: {_background_task}", file=sys.stderr)
_logger.debug("Background task already running: %s", _background_task)
async def stop_background():
+1 -3
View File
@@ -119,11 +119,9 @@ async def flush_changes(
# Append all lines in a single write (binary mode for Windows compatibility)
async with aiofiles.open(db_path, "ab") as f:
await f.write(b"\n".join(lines) + b"\n")
_logger.info(
_logger.debug(
"Flushed %d change(s) to %s", len(changes_to_write), db_path
)
import sys
print(f"[DB] Flushed {len(changes_to_write)} change(s) to {db_path}", file=sys.stderr)
return True
except OSError:
_logger.exception("Failed to flush database changes")
+11 -24
View File
@@ -101,15 +101,17 @@ class DB:
create_change_record(self._current_actor, diff)
)
self._previous_builtins = current
_logger.info(
"Queued change by %s, %d pending",
self._current_actor,
len(self._pending_changes),
)
import sys
# Log the change with user display name if available
actor_display = self._current_actor
if self._current_actor not in ("system", "expiry", "migrate"):
try:
user_uuid = UUID(self._current_actor)
if user_uuid in self._data.users:
actor_display = self._data.users[user_uuid].display_name
except (ValueError, KeyError):
pass
import json
print(f"[DB] Queued change by {self._current_actor}, {len(self._pending_changes)} pending", file=sys.stderr)
print(f"[DB] diff: {json.dumps(diff, default=str)}", file=sys.stderr)
_logger.info("DB change by %s: %s", actor_display, json.dumps(diff, default=str))
@contextmanager
def transaction(self, actor: str = "system"):
@@ -173,10 +175,8 @@ def build_role(uuid: UUID) -> Role:
def build_org(uuid: UUID, include_roles: bool = False) -> Org:
import sys
o = _db._data.orgs[uuid]
perm_scopes = [p.scope for p in _db._data.permissions.values() if uuid in p.orgs]
print(f"[DB] build_org({uuid}): permissions={perm_scopes}", file=sys.stderr)
org = Org(uuid=uuid, display_name=o.display_name, permissions=perm_scopes)
if include_roles:
org.roles = [
@@ -528,9 +528,8 @@ def rename_permission(
"""Rename a permission's scope. The UUID remains the same.
Also updates all role references to use the new scope.
Note: Scopes do not need to be unique (same scope with different domains is valid).
"""
import sys
# Find permission by old scope
key = None
for pid, p in _db._data.permissions.items():
@@ -540,15 +539,6 @@ def rename_permission(
if not key:
raise ValueError(f"Permission with scope '{old_scope}' not found")
# Check if new scope already exists (on a different permission)
for pid, p in _db._data.permissions.items():
if p.scope == new_scope and pid != key:
raise ValueError(f"Permission with scope '{new_scope}' already exists")
# Debug: Print orgs before change
print(f"[DB] rename_permission: {old_scope} -> {new_scope}", file=sys.stderr)
print(f"[DB] orgs BEFORE: {_db._data.permissions[key].orgs}", file=sys.stderr)
with _db.transaction(actor):
# Update the permission
_db._data.permissions[key].scope = new_scope
@@ -562,9 +552,6 @@ def rename_permission(
del r.permissions[old_scope]
r.permissions[new_scope] = True
# Debug: Print orgs after change
print(f"[DB] orgs AFTER: {_db._data.permissions[key].orgs}", file=sys.stderr)
def delete_permission(uuid: str | UUID, actor: str = "system") -> None:
"""Delete a permission."""