From b1797786d2e3372edaa0cfd74e6da7a66755b05f Mon Sep 17 00:00:00 2001 From: Ivan Gerasimov Date: Sun, 27 Sep 2026 15:41:41 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20partition=20smoke=20=D0=B7=D0=B0=D1=81?= =?UTF-8?q?=D1=87=D0=B8=D1=82=D1=8B=D0=B2=D0=B0=D0=B5=D1=82=201012=20?= =?UTF-8?q?=D0=B8=201013=20=D0=BA=D0=B0=D0=BA=20fail-closed=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=BA=D1=80=D1=8B=D1=82=D0=B8=D0=B5=20=D0=BA=D0=B0=D0=BD=D0=B0?= =?UTF-8?q?=D0=BB=D0=BE=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/test_cluster_failover.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/scripts/test_cluster_failover.py b/scripts/test_cluster_failover.py index 0ececc8..eac2e90 100644 --- a/scripts/test_cluster_failover.py +++ b/scripts/test_cluster_failover.py @@ -250,6 +250,10 @@ async def main(args: argparse.Namespace) -> int: instructor_cookie = login(backend, instructor_login, instructor_password) trainee_cookie = login(backend, trainee_login, trainee_password) + # Учётки созданы прямо в БД, вход — на узле A, а сокет занятия Nginx + # может отдать узлу B. B узнаёт новый логин при очередной сверке + # поколений (раз в секунду); до неё middleware считает cookie отозванной. + await asyncio.sleep(2.5) await send_control(ws_base, session_id, instructor_cookie, { "type": "scenario.start", "scenario_id": args.scenario, "trainee": trainee.name, "trainee_id": str(trainee.id), @@ -418,8 +422,19 @@ async def main(args: argparse.Namespace) -> int: f"existing_{channel}_closed": closure["closed"] for channel, closure in result["existing_channel_closures"].items() }) + # Без БД старый владелец закрывает каналы fail-closed одним из двух + # путей: auth не может сверить поколения учёток дольше 2 с — 1013, + # supervisor lease замечает потерю владения (цикл 5 с) — 1012. + # Auth обычно успевает первым; оба кода корректны, фронт их не + # различает. Фактический код остаётся в existing_channel_closures. + result["existing_channel_close_codes"] = { + channel: closure.get("close_code") + for channel, closure in result["existing_channel_closures"].items() + } result["checks"].update({ - f"existing_{channel}_fenced_with_1012": closure["fence_notice"] + f"existing_{channel}_closed_fail_closed": ( + closure["fence_notice"] or closure.get("close_code") == 1013 + ) for channel, closure in result["existing_channel_closures"].items() })