Skip to content

Web request-path robustness: concurrent-insert 500s and a 5-minute event-loop freeze (2 PRs) #24

Description

@ahueb

Two verified defects where a single user action can 500 or stall the whole site. Both live in the app container, which runs a single uvicorn worker — so a blocked event loop is a full outage, not a slow request.

Line numbers current as of origin/main @ b7edcbc (2026-07-30).

Suggested order: V5 → C2.

PR V5 — Concurrent first-action IntegrityError handling (small)

waitlist_submit (public.py:485-503, unique email) and review_proposal (agent_page.py:440-466, unique uq_proposal_reviews_decision_agent) do SELECT-then-INSERT with no IntegrityError catch → two concurrent first-time actions race and one 500s.

The codebase already has the correct pattern twice: the vote endpoint (public.py:1041) and the PI web-message writer (agent_page.py:804-812, which rolls back and retries once). Fix: mirror the vote endpoint's catch-and-recover in both handlers.

PR C2 — Move blocking provisioning I/O off the web loop (medium)

admin_provision_slack / admin_provision_slack_callback (admin.py:907/934) are async def and await start_provisioning/complete_provisioning, which internally call synchronous httpx.post plus time.sleep(wait) with up to 5 retries (slack_provisioning.py:107/128/144). There is no to_thread anywhere in src/ (verified 2026-07-30). A rate-limited Slack manifest create therefore freezes every web request for up to ~5 minutes on the single worker, and the get_db session is held open across the whole blocking call.

Fix: offload the blocking calls to asyncio.to_thread; commit/close the session before external I/O.

Definition of done: each PR ships a test that fails against the pre-fix code — for V5, a concurrent-insert test; for C2, an assertion that the handler does not block the loop.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions