correctness batch: atomic writes, task refs, hmac, import-star, pickle
Per review §2: - web/db.py: new _tx() context manager wraps multi-statement writers in BEGIN IMMEDIATE … COMMIT/ROLLBACK (our connections run in autocommit mode, so plain `with _lock:` doesn't give atomicity). partnership_accept (UPDATE + DELETE) and cleanup_retention (3 deletes/updates) now use it. - Fire-and-forget tasks: add module-level _bg_tasks sets in web/app.py and web/enrichment.py. A _spawn() helper holds a strong ref until the task finishes so the GC can't drop it mid-flight (CPython's event loop only weakly references pending tasks). - apply/main.py: require_api_key uses hmac.compare_digest, matching web's check. Also imports now use explicit names instead of `from settings *`. - apply/language.py: replace `from settings import *` + `from paths import *` with explicit imports — this is the pattern that caused the LANGUAGE NameError earlier. - alert/utils.py: pickle-based hash_any_object → deterministic JSON+sha256. Cheaper, portable across Python versions, no pickle attack surface. - web/notifications.py: /fehler links repointed to /bewerbungen (the former page doesn't exist). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
77098c82df
commit
eb73b5e415
7 changed files with 66 additions and 19 deletions
|
|
@ -218,8 +218,20 @@ def _record_failure(flat_id: str, step: str, reason: str) -> None:
|
|||
pass
|
||||
|
||||
|
||||
# Holding strong references to every spawned task so asyncio doesn't GC them
|
||||
# mid-flight. create_task only weakly references tasks from the event loop.
|
||||
_bg_tasks: set[asyncio.Task] = set()
|
||||
|
||||
|
||||
def _spawn(coro) -> asyncio.Task:
|
||||
t = asyncio.create_task(coro)
|
||||
_bg_tasks.add(t)
|
||||
t.add_done_callback(_bg_tasks.discard)
|
||||
return t
|
||||
|
||||
|
||||
def kick(flat_id: str) -> None:
|
||||
asyncio.create_task(asyncio.to_thread(enrich_flat_sync, flat_id))
|
||||
_spawn(asyncio.to_thread(enrich_flat_sync, flat_id))
|
||||
|
||||
|
||||
async def _backfill_runner() -> None:
|
||||
|
|
@ -234,5 +246,5 @@ async def _backfill_runner() -> None:
|
|||
|
||||
def kick_backfill() -> int:
|
||||
pending = db.flats_needing_enrichment(limit=200)
|
||||
asyncio.create_task(_backfill_runner())
|
||||
_spawn(_backfill_runner())
|
||||
return len(pending)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue