Files
webmail-client/backend/workers/worker.py
T
lukasandClaude Opus 4.8 3951df9755 Two-way draft sync, signatures, sent/bcc fixes, and mail-list UI
Backend
- Sent copies: persist locally on send + periodic multi-folder CONDSTORE poll
  (Sent/Archive/Trash/Junk) so they thread and show without an IDLE-only INBOX.
- Bcc: transmitted copy omits Bcc, Sent copy keeps it; store/display bcc_addr.
- Drafts: mirror local drafts to the IMAP Drafts folder (append/replace/expunge);
  inbound sync of foreign drafts (un-threaded) with adopt-to-edit + dedup by UID.
- Per-user storage quota (5 GiB default) and manual "sync all folders" action.
- Account editing (display/color/server/password) and per-account HTML signature.
- Account view scoped to that account's inbox; new migrations 0006–0009.

Frontend
- Mail-list pagination, folder filters (All/Unread/Pinned), sort toggle, refresh.
- Aligned + widened mail-list margins; reading-pane bars fixed height.
- Rich-text composer: color palette, highlight, image; attachments; expand/pop-out.
- Signatures: auto-insert for new mail, replace on From change, reply insert.
- Restore/Delete actions per folder; drafts view merges local + remote, date-sorted.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-18 15:27:09 +02:00

73 lines
2.1 KiB
Python

"""arq worker entrypoint (SPEC §2 ``workers/worker.py``).
Run with: ``arq workers.worker.WorkerSettings`` (from ``backend/``).
"""
from __future__ import annotations
import logging
import uuid
from typing import Any
from app.config import get_settings
from app.outbox.draft_sync import push_draft_to_imap_job, remove_imap_draft_job
from app.outbox.jobs import send_job
from app.queue import redis_settings as arq_redis_settings
from app.sync.actions import (
delete_thread_job,
move_job,
move_thread_to_folder_job,
push_flags_job,
)
from app.sync.engine import bootstrap_and_backfill, refresh_account_job
logger = logging.getLogger(__name__)
async def sync_bootstrap_account(ctx: dict[str, Any], account_id: str) -> int:
"""Bootstrap + backfill an account (enqueued on account creation)."""
logger.info("sync.bootstrap_account start account=%s", account_id)
count = await bootstrap_and_backfill(uuid.UUID(account_id))
logger.info("sync.bootstrap_account done account=%s messages=%d", account_id, count)
return count
async def on_startup(ctx: dict[str, Any]) -> None:
logging.basicConfig(level=get_settings().log_level)
from app.sync.supervisor import start_supervisor
await start_supervisor(ctx)
logger.info("webmail worker started")
async def on_shutdown(ctx: dict[str, Any]) -> None:
from app.db import dispose_engine
from app.redis_client import close_redis
from app.sync.supervisor import stop_supervisor
await stop_supervisor(ctx)
await dispose_engine()
await close_redis()
logger.info("webmail worker stopped")
class WorkerSettings:
"""arq worker configuration."""
functions = [
sync_bootstrap_account,
push_flags_job,
move_job,
move_thread_to_folder_job,
delete_thread_job,
send_job,
push_draft_to_imap_job,
remove_imap_draft_job,
refresh_account_job,
]
on_startup = on_startup
on_shutdown = on_shutdown
max_jobs = 10 # global worker cap (SPEC §6.3)
job_timeout = 3600 # backfill of a large account can be long
redis_settings = arq_redis_settings()