mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
fix(oidc): survive a failing rollback in the never-raise handler too
The recovery rollback after a failed commit was itself unguarded, so a rollback that raises on a wedged connection would still take the boot down -- the exact failure the never-raise contract exists to prevent. Suppressed; the caller's `async with` discards the session regardless. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016q8EAf9Rj7ZHL92sPnXYxy
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
be19461470
commit
6eea61dc78
@@ -9,6 +9,7 @@ check the UI enforces.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
|
||||
@@ -100,8 +101,12 @@ async def apply_env_oidc_provider(db: AsyncSession) -> None:
|
||||
# Never str(exc): a DB error message can echo a configured value. Class only.
|
||||
logger.error("BAMBUDDY_OIDC_* could not be applied: %s", type(exc).__name__)
|
||||
# A commit may have half-applied; roll back so the shared session is
|
||||
# left clean for the rest of startup.
|
||||
await db.rollback()
|
||||
# left clean for the rest of startup. Suppressed because rollback on a
|
||||
# wedged connection can itself raise -- and the whole point here is that
|
||||
# nothing in this path takes the boot down. The session is discarded by
|
||||
# the caller's `async with` regardless.
|
||||
with contextlib.suppress(Exception):
|
||||
await db.rollback()
|
||||
|
||||
|
||||
async def _apply_env_oidc_provider(db: AsyncSession) -> None:
|
||||
|
||||
@@ -220,6 +220,29 @@ async def test_a_commit_failure_is_survivable_and_leaks_nothing(db_session, monk
|
||||
assert "leaked-secret" not in caplog.text # ...but nothing from the message
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_a_failing_rollback_is_also_survivable(db_session, monkeypatch, caplog):
|
||||
"""The handler rolls back after a failed commit -- but rollback on a wedged
|
||||
connection can raise too, and 'never raises' has to hold for that as well
|
||||
or the boot dies on the recovery path. The rollback is suppressed."""
|
||||
|
||||
async def _raise_on_commit():
|
||||
raise RuntimeError("database is locked")
|
||||
|
||||
async def _raise_on_rollback():
|
||||
raise RuntimeError("connection is closed")
|
||||
|
||||
monkeypatch.setattr(db_session, "commit", _raise_on_commit)
|
||||
monkeypatch.setattr(db_session, "rollback", _raise_on_rollback)
|
||||
_configure(monkeypatch, BAMBUDDY_OIDC_CLIENT_SECRET="leaked-secret")
|
||||
|
||||
with caplog.at_level(logging.ERROR):
|
||||
await apply_env_oidc_provider(db_session) # must not raise, even here
|
||||
|
||||
assert "could not be applied" in caplog.text
|
||||
assert "leaked-secret" not in caplog.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_applying_twice_without_changes_is_a_no_op(db_session, monkeypatch):
|
||||
"""Every boot re-applies; the second run must not create a second row."""
|
||||
|
||||
Reference in New Issue
Block a user