fix: сокеты dev не закрываются при недоступной БД поколений
This commit is contained in:
parent
fb9c27977d
commit
491655de5c
2 changed files with 32 additions and 1 deletions
|
|
@ -72,7 +72,13 @@ async def _close_auth_state_unavailable(ws: WebSocket) -> None:
|
||||||
|
|
||||||
|
|
||||||
def _close_unverified_sockets() -> None:
|
def _close_unverified_sockets() -> None:
|
||||||
for sockets in list(_active_sockets.values()):
|
# Синтетический `dev` middleware пропускает без сверки поколения — и его
|
||||||
|
# сокеты не зависят от синхронизации с БД, иначе стенд без базы рвёт
|
||||||
|
# занятие через две секунды после старта.
|
||||||
|
synthetic = {"dev"} if get_settings().dev_auth_bypass else set()
|
||||||
|
for login, sockets in list(_active_sockets.items()):
|
||||||
|
if login in synthetic:
|
||||||
|
continue
|
||||||
for ws, loop in list(sockets.items()):
|
for ws, loop in list(sockets.items()):
|
||||||
try:
|
try:
|
||||||
if not loop.is_closed():
|
if not loop.is_closed():
|
||||||
|
|
|
||||||
|
|
@ -674,3 +674,28 @@ def test_backup_error_redacts_database_credentials(monkeypatch):
|
||||||
detail = admin._safe_backup_error(admin.backup_service.BackupError(f"bad DSN: {dsn}"))
|
detail = admin._safe_backup_error(admin.backup_service.BackupError(f"bad DSN: {dsn}"))
|
||||||
assert "supersecret" not in detail
|
assert "supersecret" not in detail
|
||||||
assert dsn not in detail
|
assert dsn not in detail
|
||||||
|
|
||||||
|
|
||||||
|
def test_stale_generation_sync_keeps_synthetic_dev_socket():
|
||||||
|
"""`dev` не хранится в users, и middleware не сверяет его поколение.
|
||||||
|
Закрывать его сокеты при недоступной БД — значит рвать занятие на
|
||||||
|
стенде без базы, хотя HTTP того же входа продолжает работать."""
|
||||||
|
class FakeWebSocket:
|
||||||
|
closed_with = None
|
||||||
|
|
||||||
|
async def close(self, code, reason):
|
||||||
|
self.closed_with = (code, reason)
|
||||||
|
|
||||||
|
async def run():
|
||||||
|
websocket = FakeWebSocket()
|
||||||
|
sockets = auth._active_sockets.setdefault("dev", weakref.WeakKeyDictionary())
|
||||||
|
sockets[websocket] = asyncio.get_running_loop()
|
||||||
|
try:
|
||||||
|
auth._close_unverified_sockets()
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
await asyncio.sleep(0)
|
||||||
|
assert websocket.closed_with is None
|
||||||
|
finally:
|
||||||
|
sockets.pop(websocket, None)
|
||||||
|
|
||||||
|
asyncio.run(run())
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue