Add --debug flag, dual-mode logging, and auto-run on startup

- logger.py: root-level handlers; normal mode shows only user-facing INFO
  (sync, export, push, MBOX) plus WARNING/ERROR; --debug shows all DEBUG
  with full context (module.func:line). Third-party loggers silenced to WARNING.
- main.py: add --debug CLI flag, call configure_logging() at startup,
  auto-trigger sync on first run or when last sync is overdue by the interval
- database.py: add metadata table with record_sync_time() / get_last_sync_time()
  so startup knows whether a sync is due; sync time recorded on success
- forwarder.py: INFO at push start and push complete with counts
- packager.py: INFO before MBOX conversion begins
- exporter.py: INFO when Proton Mail export starts

https://claude.ai/code/session_01KjaNo9RXevw6x1DjJD8mj6
This commit is contained in:
Claude
2026-03-24 21:54:25 +00:00
parent f021410622
commit 69c685798c
6 changed files with 114 additions and 24 deletions
+20 -1
View File
@@ -29,7 +29,7 @@ from modules import packager
from modules import processor
from modules import scheduler
from modules import tools
from modules.logger import get_logger, tail_log
from modules.logger import get_logger, configure_logging, tail_log
log = get_logger(__name__)
app = typer.Typer(add_completion=False, pretty_exceptions_show_locals=False)
@@ -52,9 +52,12 @@ def main(
status: bool = typer.Option(False, "--status", help="Print status summary and exit."),
logs: bool = typer.Option(False, "--logs", help="Tail the log file and exit."),
change_config: bool = typer.Option(False, "--config", help="Change a config value."),
debug: bool = typer.Option(False, "--debug", help="Show all debug output on the console."),
) -> None:
global _master_password
configure_logging(debug=debug)
if setup:
_run_setup()
return
@@ -139,8 +142,22 @@ def _start_service(run_now: bool = False) -> None:
scheduler.start(sync, interval)
# Auto-run if this is the first sync ever, or the last one was overdue
if run_now:
scheduler.run_now(sync)
else:
last = database.get_last_sync_time()
if last is None:
log.info("No previous sync found — running immediately.")
scheduler.run_now(sync)
else:
elapsed_min = (datetime.now(timezone.utc) - last).total_seconds() / 60
if elapsed_min >= interval:
log.info(
"Last sync was %.0f minute(s) ago (interval: %d min) — running immediately.",
elapsed_min, interval,
)
scheduler.run_now(sync)
log.info("MailRelay running. Press Ctrl+C to stop.")
@@ -218,6 +235,8 @@ def _sync_cycle(conf: dict) -> None:
except Exception as exc:
log.error("Unexpected error in sync cycle: %s", exc, exc_info=True)
summary["error"] = str(exc)
else:
database.record_sync_time()
finally:
summary["finished_at"] = datetime.now(timezone.utc).isoformat()
_last_run = summary