From 1e08cd0c2e8af7e1499d96924fab6b5d5a6ae8dc Mon Sep 17 00:00:00 2001 From: lekss361 Date: Mon, 18 May 2026 00:38:52 +0300 Subject: [PATCH 1/2] feat(22d): admin endpoint POST /admin/scrape/kn-catalog-objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Manual trigger для catalog-object scraper (PR #335). Smoke-тест и ad-hoc повторные runs до next beat fire (Tuesday 04:00 UTC). Body: {"region_code": 66, "max_objects": 3?} Header: X-Admin-Token: --- backend/app/api/v1/admin_scrape.py | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/backend/app/api/v1/admin_scrape.py b/backend/app/api/v1/admin_scrape.py index d9606667..55b1d14a 100644 --- a/backend/app/api/v1/admin_scrape.py +++ b/backend/app/api/v1/admin_scrape.py @@ -1249,3 +1249,38 @@ def trigger_ekburg_permits( scope = f"year_{payload.year}" return {"task_id": result.id, "scope": scope, "queued_at": "now"} + + +class TriggerKnCatalogObjectsRequest(BaseModel): + region_code: int = Field(default=66, ge=1, le=99) + max_objects: int | None = Field(default=None, ge=1, le=2000) + + +@router.post("/kn-catalog-objects") +def trigger_kn_catalog_objects( + payload: TriggerKnCatalogObjectsRequest, + _: AdminTokenAuth, +) -> dict[str, Any]: + """Manual trigger для catalog-OBJECT scraper (заполняет wall_type, energy_eff, + ceiling_height_m, parking_*, playground_*, scores из SSR __NEXT_DATA__). + + Beat schedule: Tuesday 04:00 UTC, batch 300/run. Этот endpoint — для ad-hoc + запуска (smoke-тест после деплоя или повторный pass для свежесозданных + объектов до next beat fire). + + - max_objects=None → берёт из job_settings (default 300 для beat). + - max_objects=3 → smoke-тест. + """ + from app.workers.tasks.scrape_kn_catalog_objects import scrape_kn_catalog_objects + + kwargs: dict[str, Any] = {"region_code": payload.region_code} + if payload.max_objects is not None: + kwargs["max_objects"] = payload.max_objects + result = scrape_kn_catalog_objects.apply_async(kwargs=kwargs) + + return { + "task_id": result.id, + "region_code": payload.region_code, + "max_objects": payload.max_objects, + "queued_at": "now", + } -- 2.45.3 From f3707712e544964a246d008ee5ea0f43d9eb6f45 Mon Sep 17 00:00:00 2001 From: lekss361 Date: Mon, 18 May 2026 00:50:07 +0300 Subject: [PATCH 2/2] fix(22d): register scrape_kn_catalog_objects in celery include list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #335 добавил task, но celery_app.py имеет explicit `include=[]` (а не autodiscover), поэтому worker не импортировал новый модуль и не зарегистрировал task name. apply_async из admin endpoint падал с KeyError: 'tasks.scrape_kn_catalog_objects.scrape_kn_catalog_objects'. One-line add to include list. --- backend/app/workers/celery_app.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/app/workers/celery_app.py b/backend/app/workers/celery_app.py index 9a3afa0c..112c2fa1 100644 --- a/backend/app/workers/celery_app.py +++ b/backend/app/workers/celery_app.py @@ -49,6 +49,7 @@ celery_app = Celery( backend=settings.redis_url, include=[ "app.workers.tasks.scrape_kn", + "app.workers.tasks.scrape_kn_catalog_objects", "app.workers.tasks.refresh_analytics", "app.workers.tasks.scrape_objective", "app.workers.tasks.objective_etl", -- 2.45.3