This commit is contained in:
lekss361 2026-04-27 18:52:21 +03:00
parent 75c2025ba0
commit 692a4fc5eb
4 changed files with 78 additions and 11 deletions

View file

@ -13,3 +13,16 @@ SENTRY_DSN=
# External APIs (Stage 2) # External APIs (Stage 2)
ROSREESTR_PKK_BASE_URL=https://pkk.rosreestr.ru/api/features/1 ROSREESTR_PKK_BASE_URL=https://pkk.rosreestr.ru/api/features/1
OVERPASS_URL=https://overpass-api.de/api/interpreter OVERPASS_URL=https://overpass-api.de/api/interpreter
# ── Scraper наш.дом.рф (Celery beat + admin trigger) ──────────────────────
# Расписание автоматических прогонов (5-полевой crontab). По умолчанию пн 04:15 МСК.
SCRAPE_KN_CRON=15 4 * * mon
# Random delay 0..N сек перед стартом scheduled-таска (анти-pattern detection).
SCRAPE_KN_JITTER_SECONDS=1800
# Регионы по умолчанию для scheduled sweep-а (csv).
SCRAPE_KN_DEFAULT_REGIONS=66
# Путь к Playwright storage_state.json (commited в git, обновляется --save-state).
SCRAPE_KN_STATE_PATH=data/playwright_state.json
# Токен для POST /api/v1/admin/scrape/kn (заголовок X-Admin-Token).
# Пустая строка = endpoint disabled (503). Сгенерировать: openssl rand -hex 32
SCRAPE_ADMIN_TOKEN=

View file

@ -80,8 +80,13 @@ export default function ScrapeAdminPage() {
download_photos: downloadPhotos, download_photos: downloadPhotos,
}), }),
}), }),
onSuccess: () => onSuccess: (data) => {
queryClient.invalidateQueries({ queryKey: ["scrape-runs"] }), console.log("[scrape] queued:", data);
queryClient.invalidateQueries({ queryKey: ["scrape-runs"] });
},
onError: (err) => {
console.error("[scrape] failed:", err);
},
}); });
const failures = useQuery({ const failures = useQuery({
@ -202,20 +207,66 @@ export default function ScrapeAdminPage() {
onClick={() => trigger.mutate()} onClick={() => trigger.mutate()}
disabled={!token || trigger.isPending} disabled={!token || trigger.isPending}
style={primaryBtn} style={primaryBtn}
title={!token ? "Введите Admin Token выше" : undefined}
> >
{trigger.isPending ? "Запускаю…" : "Запустить сейчас"} {trigger.isPending ? "Запускаю…" : "Запустить сейчас"}
</button> </button>
{trigger.isError ? ( {!token ? (
<span style={{ color: "#b3261e", marginLeft: 12 }}> <span style={{ marginLeft: 12, color: "#9a6700", fontSize: 13 }}>
Ошибка: {String(trigger.error)} введите Admin Token выше
</span>
) : null}
{trigger.isSuccess ? (
<span style={{ color: "#0a7a3a", marginLeft: 12 }}>
Поставлено в очередь: {trigger.data.task_id}
</span> </span>
) : null} ) : null}
</div> </div>
{trigger.isError ? (
<div
style={{
marginTop: 12,
padding: 12,
background: "#fef2f2",
border: "1px solid #fecaca",
borderRadius: 6,
color: "#991b1b",
fontSize: 14,
wordBreak: "break-word",
}}
>
<strong>Ошибка:</strong> {String(trigger.error)}
<div style={{ marginTop: 6, fontSize: 12, color: "#7f1d1d" }}>
Подробности в консоли браузера (F12 Console).
</div>
</div>
) : null}
{trigger.isSuccess ? (
<div
style={{
marginTop: 12,
padding: 12,
background: "#f0fdf4",
border: "1px solid #bbf7d0",
borderRadius: 6,
color: "#065f46",
fontSize: 14,
}}
>
<strong> Поставлено в очередь.</strong> task_id={" "}
<code
style={{
background: "#dcfce7",
padding: "2px 6px",
borderRadius: 3,
}}
>
{trigger.data.task_id}
</code>{" "}
· регион {trigger.data.region_code}
<div style={{ marginTop: 6, fontSize: 12, color: "#047857" }}>
Прогон появится в журнале «Последние прогоны» ниже когда worker
подхватит задачу.
</div>
</div>
) : null}
</section> </section>
<section style={{ ...cardStyle, marginTop: 16 }}> <section style={{ ...cardStyle, marginTop: 16 }}>

File diff suppressed because one or more lines are too long

View file

@ -90,3 +90,6 @@ Host gendesign
ServerAliveInterval 60 ServerAliveInterval 60
LocalForward 15432 127.0.0.1:5432 LocalForward 15432 127.0.0.1:5432
LocalForward 8000 127.0.0.1:8000 LocalForward 8000 127.0.0.1:8000
token admin 15c99983d471718fe5c320f36bad01994d91ff34cb5646ce957b060ec039275e