From 81cf274e8093edf2ce080cd3f9f95f4bd3190e56 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Sun, 17 May 2026 09:31:43 +0300 Subject: [PATCH] =?UTF-8?q?fix(#234):=20address=20re-review=20nits=20?= =?UTF-8?q?=E2=80=94=20Settings=20singleton=20+=20docstring=20sync?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. _acquire_harvest_lock: Settings() instance → singleton 'settings' import from app.core.config — соответствует convention (scrape_kn.py, objective.py, celery_app.py все используют singleton). 2. _trigger_harvest docstring: убрана incorrect фраза «остальные ... видят harvest_eta_seconds от первого запроса» (код возвращает eta=None для denied-lock callers). Заменена на actual behavior: graceful no-data UI с ПКК fallback на FE. PR #250 re-review followup (issues #3 + docstring sync). --- .../app/services/site_finder/quarter_dump_lookup.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/backend/app/services/site_finder/quarter_dump_lookup.py b/backend/app/services/site_finder/quarter_dump_lookup.py index 1b5dcd63..6dabac98 100644 --- a/backend/app/services/site_finder/quarter_dump_lookup.py +++ b/backend/app/services/site_finder/quarter_dump_lookup.py @@ -1201,9 +1201,9 @@ def _acquire_harvest_lock(quarter: str) -> bool: try: import redis - from app.core.config import Settings + from app.core.config import settings - client = redis.Redis.from_url(Settings().redis_url) + client = redis.Redis.from_url(settings.redis_url) # SET key value NX EX — атомарно: «установи если не существует, TTL N сек». acquired = client.set( f"nspd_harvest_lock:{quarter}", @@ -1223,10 +1223,13 @@ def _trigger_harvest(quarter: str) -> bool: Ленивый импорт чтобы избежать circular import (tasks → services → tasks). - Issue #234: burst-from N concurrent analyze дедуплицируется через + Issue #234: burst N concurrent analyze дедуплицируется через `_acquire_harvest_lock` — только первый запрос ставит task, остальные - получают `False` (т.е. harvest_triggered=False) но видят в response - `harvest_eta_seconds` от первого запроса и не re-poll сразу. + получают `False` (т.е. harvest_triggered=False, harvest_eta_seconds=None). + FE при таком ответе показывает graceful no-data UI с ПКК fallback link + (не infinite spinner). Trade-off: Request B не видит countdown, но и не + сбивает работу Request A. Это намеренный design choice — см. vault + fixes/Bug_NSPD_WMS_NotBulk_2026_May14.md. """ if not _acquire_harvest_lock(quarter): logger.info("quarter=%s harvest skipped (lock held by another request)", quarter)