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)
ROSREESTR_PKK_BASE_URL=https://pkk.rosreestr.ru/api/features/1
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,
}),
}),
onSuccess: () =>
queryClient.invalidateQueries({ queryKey: ["scrape-runs"] }),
onSuccess: (data) => {
console.log("[scrape] queued:", data);
queryClient.invalidateQueries({ queryKey: ["scrape-runs"] });
},
onError: (err) => {
console.error("[scrape] failed:", err);
},
});
const failures = useQuery({
@ -202,20 +207,66 @@ export default function ScrapeAdminPage() {
onClick={() => trigger.mutate()}
disabled={!token || trigger.isPending}
style={primaryBtn}
title={!token ? "Введите Admin Token выше" : undefined}
>
{trigger.isPending ? "Запускаю…" : "Запустить сейчас"}
</button>
{trigger.isError ? (
<span style={{ color: "#b3261e", marginLeft: 12 }}>
Ошибка: {String(trigger.error)}
</span>
) : null}
{trigger.isSuccess ? (
<span style={{ color: "#0a7a3a", marginLeft: 12 }}>
Поставлено в очередь: {trigger.data.task_id}
{!token ? (
<span style={{ marginLeft: 12, color: "#9a6700", fontSize: 13 }}>
введите Admin Token выше
</span>
) : null}
</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 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
LocalForward 15432 127.0.0.1:5432
LocalForward 8000 127.0.0.1:8000
token admin 15c99983d471718fe5c320f36bad01994d91ff34cb5646ce957b060ec039275e