diff --git a/.forgejo/workflows/deploy-tradein.yml b/.forgejo/workflows/deploy-tradein.yml index e15d8290..76d332bf 100644 --- a/.forgejo/workflows/deploy-tradein.yml +++ b/.forgejo/workflows/deploy-tradein.yml @@ -655,10 +655,21 @@ jobs: # прикрывать, что и требуется. Ожидание ограничено: не дождались за # 900с — падаем с внятным сообщением, а не молча ждём вечно. exec 9>/var/lock/gendesign-docker-deploy.lock - if ! flock -w 900 9; then - echo "ERROR: не дождался лока докер-деплоя за 900с." - echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" - exit 1 + # Сначала неблокирующая попытка — чтобы ОЖИДАНИЕ оставляло след в логе. + # Без этого работающий лок ненаблюдаем: flock при успехе молчит, и отличить + # «второй деплой дождался первого» от «они просто разошлись по времени» + # нельзя — а именно это и есть критерий приёмки #2950. + if flock -n 9; then + echo "→ докер-лок свободен, взят сразу" + else + echo "→ докер-лок занят соседним деплоем, жду (до 900с)…" + lock_wait_started=$(date +%s) + if ! flock -w 900 9; then + echo "ERROR: не дождался лока докер-деплоя за 900с." + echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" + exit 1 + fi + echo "→ докер-лок получен через $(( $(date +%s) - lock_wait_started ))с ожидания" fi cd /opt/gendesign diff --git a/.forgejo/workflows/deploy.yml b/.forgejo/workflows/deploy.yml index 92bb367b..fa30a939 100644 --- a/.forgejo/workflows/deploy.yml +++ b/.forgejo/workflows/deploy.yml @@ -501,10 +501,21 @@ jobs: # прикрывать, что и требуется. Ожидание ограничено: не дождались за # 900с — падаем с внятным сообщением, а не молча ждём вечно. exec 9>/var/lock/gendesign-docker-deploy.lock - if ! flock -w 900 9; then - echo "ERROR: не дождался лока докер-деплоя за 900с." - echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" - exit 1 + # Сначала неблокирующая попытка — чтобы ОЖИДАНИЕ оставляло след в логе. + # Без этого работающий лок ненаблюдаем: flock при успехе молчит, и отличить + # «второй деплой дождался первого» от «они просто разошлись по времени» + # нельзя — а именно это и есть критерий приёмки #2950. + if flock -n 9; then + echo "→ докер-лок свободен, взят сразу" + else + echo "→ докер-лок занят соседним деплоем, жду (до 900с)…" + lock_wait_started=$(date +%s) + if ! flock -w 900 9; then + echo "ERROR: не дождался лока докер-деплоя за 900с." + echo " Кто держит: ssh на хост, затем fuser -v /var/lock/gendesign-docker-deploy.lock" + exit 1 + fi + echo "→ докер-лок получен через $(( $(date +%s) - lock_wait_started ))с ожидания" fi cd /opt/gendesign diff --git a/backend/tests/ops/test_2950_deploy_concurrency_group.py b/backend/tests/ops/test_2950_deploy_concurrency_group.py index d72c64f3..b8fa59b2 100644 --- a/backend/tests/ops/test_2950_deploy_concurrency_group.py +++ b/backend/tests/ops/test_2950_deploy_concurrency_group.py @@ -69,6 +69,27 @@ def test_prod_deploy_takes_the_host_lock(name: str) -> None: ) +@pytest.mark.parametrize("name", PROD_DEPLOYS) +def test_lock_wait_leaves_a_trace(name: str) -> None: + """Ожидание лока видно в логе — иначе работающий лок ненаблюдаем. + + `flock` при успехе молчит. Если брать лок сразу блокирующим вызовом, отличить + «второй деплой дождался первого» от «они просто разошлись по времени» нельзя — + а это и есть критерий приёмки #2950. Поэтому сначала неблокирующая попытка, и + при занятом локе в лог уходит и факт ожидания, и его длительность. + """ + script = _deploy_script(name) + assert "flock -n" in script, ( + f"{name}: лок берётся сразу блокирующим вызовом — ожидание не попадёт в лог, " + "и проверить, что взаимное исключение сработало, будет нечем" + ) + assert "жду" in script, f"{name}: нет строки об ожидании лока" + assert "с ожидания" in script, ( + f"{name}: не печатается длительность ожидания — без неё непонятно, " + "ждал деплой две секунды или четверть часа" + ) + + @pytest.mark.parametrize("name", PROD_DEPLOYS) def test_lock_wait_is_bounded_and_loud(name: str) -> None: """Ожидание ограничено и провал слышен: молча ждать вечно — не вариант."""