M54: harden operations and demo resilience
MobilityOps acceptance / backend (push) Failing after 19s
MobilityOps acceptance / frontend (push) Successful in 25s
MobilityOps acceptance / e2e (push) Skipped

This commit is contained in:
NuklearRabbit
2026-08-24 03:31:03 +02:00
parent b0706989db
commit 81e3fd63bd
101 changed files with 5641 additions and 828 deletions
+5 -1
View File
@@ -33,7 +33,11 @@ class Settings(BaseSettings):
n8n_callback_token: str = "replace-me-n8n-callback-token"
n8n_dispatch_enabled: bool = True
n8n_dispatch_interval_seconds: float = 3.0
n8n_http_timeout_seconds: float = 5.0
# The synchronous n8n workflow performs two bounded, retried callbacks before it
# acknowledges an event. Keep this above that complete workflow budget, while the
# delivery lease remains the wider crash-recovery boundary (enforced by the contract
# check in scripts/check-contracts.py).
n8n_http_timeout_seconds: float = 15.0
n8n_max_attempts: int = 5
n8n_delivery_lease_seconds: float = 120.0
app_secret: str = "replace-in-production"
+32 -1
View File
@@ -1,6 +1,6 @@
from collections.abc import Generator
from sqlalchemy import create_engine
from sqlalchemy import create_engine, event, func, select
from sqlalchemy.orm import DeclarativeBase, Session, sessionmaker
from app.core.config import get_settings
@@ -10,6 +10,37 @@ settings = get_settings()
engine = create_engine(settings.database_url, pool_pre_ping=True, future=True)
SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True)
# Every SQLAlchemy transaction participates in a shared database-wide barrier. Normal
# reads/writes coexist; the short demo reset takes the exclusive form so it can never
# interleave deletes/inserts with an API request, scanner, callback, or dispatcher cycle.
DEMO_DATA_BARRIER_LOCK_ID = 5_344_725_149_212_793_901
_EXCLUSIVE_RESET_INFO_KEY = "mobilityops_demo_reset_exclusive"
@event.listens_for(Session, "after_begin")
def _acquire_demo_data_barrier(session: Session, _transaction, connection) -> None:
if connection.dialect.name != "postgresql":
return
lock = (
func.pg_advisory_xact_lock(DEMO_DATA_BARRIER_LOCK_ID)
if session.info.get(_EXCLUSIVE_RESET_INFO_KEY)
else func.pg_advisory_xact_lock_shared(DEMO_DATA_BARRIER_LOCK_ID)
)
connection.execute(select(lock))
def begin_exclusive_demo_reset(db: Session) -> None:
"""Make the session's next transaction the exclusive side of the reset barrier."""
if db.in_transaction():
# Auth normally already read the user under a shared barrier. End that read-only
# transaction before requesting exclusive; in-place lock upgrades can deadlock.
db.rollback()
db.info[_EXCLUSIVE_RESET_INFO_KEY] = True
def end_exclusive_demo_reset(db: Session) -> None:
db.info.pop(_EXCLUSIVE_RESET_INFO_KEY, None)
class Base(DeclarativeBase):
pass