Перейти к содержанию

Архыз.CLUB — отчёт о работе за 27 мая 2026

Период: 2026-05-27, полный рабочий день Окружение: прод arkhyz-club.ru (self-hosted, podman + Caddy)

Резюме

За день закрыты 14 задач из бэклога. Прод-окружение приведено к состоянию «зелёное по всем индикаторам». Найдено и устранено 3 реальных бага (Gemini-модель в AI-сервисах, UUID-валидация в pass-svc, шум infra-ошибок), плюс предотвращён disk-out (91% → 74% через emergency cleanup).


1. PSP-маршрутизация (F4)

Расширил роутинг через psp.py на оставшиеся 4 типа броней. До правок только restaurant_bookings шёл через выбор провайдера, остальные напрямую дёргали YooKassa.

Что сделано: - services/booking-svc/app/routers/legacy_booking_compat.py_finalize_commission_response теперь использует psp.create_payment_via_psp - Owner lookup по mapping table → service_table.user_id для tour/transfer/instructor/room/hotelier - Hotel booking (room_bookings) автоматически покрыт через тот же _finalize_*

Покрытие PSP-роутинга сейчас: все 5 commission-first типов (restaurant, tour, transfer, instructor, hotel).

Коммит: 4ee7bec1d.


2. OAuth merge by email (F1)

Проверка показала: логика уже корректно реализована в hotel-api/server/app/routers/auth_oauth.py:191-205. Дубликатов email в public.users нет.

Решение: deterministic uuid5(provider:email) гарантирует, что одна почта = один users.id для одного провайдера. При наличии user'а по email обновляются только пустые поля.

Задача закрыта без правок кода.


3. gen-routes расширение (R1)

scripts/gen-routes.mjs теперь поддерживает 2 новых поля в routes.config.mjs:

  • rewrite_to: '/api/v1/widget{uri}' — per-route override для service.rewrite_prefix
  • methods: ['GET','POST'] — matcher с path + method (когда один путь делит upstream'ы по методу)

Оба поля опциональны, обратно совместимы.

Коммит: c53a2d773.


4. arkhyzpay healthcheck

Контейнер arkhyzpay-api логировал 404 HEAD /v1/health каждые 15с — wget --spider использует HEAD, а сервис отвечает только на GET.

Fix: /opt/arkhyzpay/docker-compose.yml:

test: ["CMD", "wget", "-qO-", "http://localhost:8090/v1/health"]

Контейнер пересоздан, healthcheck = healthy, в логах GET 200 вместо 404 HEAD.


5. Edge-functions auto-deploy (R4)

Проверка показала, что scripts/auto-deploy-watcher.sh уже обрабатывает изменения в supabase/functions/**:

supabase/functions/*) NEED_EDGE_RESTART=1 ;;

При NEED_EDGE_RESTART=1 делается docker restart arkhyz-supabase-functions. Таймер на проде active. Задача закрыта без правок.


6. CI workflows на self-hosted runner (R3)

Перевёл 5 workflow'ов с github-hosted на self-hosted runner (экономия CI minutes — billing блокировал cloud builds):

  • services.yml — отключил push: trigger (дублировал auto-deploy-watcher)
  • deploy-supabase-functions.yml — отключил push: (то же)
  • routes-drift-check.yml → self-hosted
  • tests.yml → self-hosted
  • ui-visual-regression.yml → self-hosted (обе job)

mobile.yml оставлен на github-hosted (нужен macos-14 для EAS build).

Коммит: 5a8b7b830.


7. Vite code-splitting в tourist-app (R2)

tourist-app/vite.config.ts был с minify: false и без manualChunks. Это давало бандл ~5MB одним файлом.

Fix: - minify: 'esbuild' - sourcemap: 'hidden' (карты для error-collector, в браузере не подгружаются) - chunkSizeWarningLimit: 800 - 10 vendor chunks: react / router / radix / framer / icons / tanstack / supabase / capacitor / maps / date

После rebuild: 9 JS chunks, главный index-*.js = 1.6MB, vendor-react = 139KB, hls-плеер отдельным чанком 512KB.

Коммит: a293a26f1.


8. Audit-1: ошибки за неделю

public.error_events за 30 дней — 0 строк. Это насторожило, проверил коллектор:

arkhyz-error-collector пишет в SQLite (/data/errors.db), не в Postgres. Запросил SQLite — получил реальную статистику (см. раздел 11).

В контейнерных логах нашёл одну важную проблему: arkhyz-hotel-api-prod спамил alembic-loop'ом:

asyncpg.exceptions.DuplicateObjectError: type "chattypeenum" already exists

Причина: public.alembic_version была пустой → каждый рестарт прогонял миграции с нуля.

Fix: docker exec arkhyz-hotel-api-prod alembic stamp head → версия e93cd6e8e846.


9. Audit-2: data hygiene

Прогнал стандартный data-check после task #23:

Метрика Значение
stuck_payments_24h 0
broken_room_30d 0
broken_restaurant_30d 0
broken_tour_30d 0
broken_transfer_30d 0
broken_instructor_30d 0
orphan_auth 0
orphan_public 11

11 orphan_public — это by design: 8 demo-seed аккаунтов + 3 OAuth-юзера (uuid5-формат, OAuth идёт мимо Supabase auth).

stuck_payment_canceller_loop отрабатывает корректно (interval=3600s).


10. Cabinet домены

Проверил все 5 ролевых SPA:

hotel.arkhyz-club.ru        200
restaurant.arkhyz-club.ru   200
instructor.arkhyz-club.ru   200
touroperator.arkhyz-club.ru 200
transfer.arkhyz-club.ru     200

Caddyfile в репо синхронен с проднутым. Drift'а нет.


11. Sentry triage — топ ошибок

Запросил groups из SQLite за 7 дней:

Кол-во Тип Источник Действие
172 warn frontend "Failed to fetch" infra drop в errorReporter.ts
68 warn HEAD /map/activities 405 уже исправлено 25.05
29+9 err /chats/me 502 Kong DNS флапы (auto-reload стоит)
17 err /events/batch 502 то же
8 err ExceptionGroup TaskGroup известный шум
6+2+1 err gemini-flash-1.5 404 замена модели
4 err invalid UUID (JWT as x-user-id) UUID validation

Фактические правки:

  1. src/lib/errorReporter.ts: 172 шт "Failed to fetch" infra больше не репортятся — это client-side обрывы (DNS/CORS/offline), сервер их не видит, починить нельзя. Для app endpoints оставлены.

  2. api-admin/app/services/ai/*.py (5 файлов): google/gemini-flash-1.5google/gemini-2.0-flash-001. OpenRouter внутренне маршрутил на удалённую -8b модель → 404 "No endpoints found". Затронуто: content_service, rag_service, sentiment_service, tour_agent, trip_planner.

  3. services/pass-svc/app/routers/skipass.py: _uid принимает x-user-id только если это валидный UUID (36 chars, дефисы в правильных позициях). Раньше клиент мог прислать JWT как header → asyncpg падал «invalid UUID got 64 chars».

Hot-deploy на прод: pass-svc + hotel-api перезапущены, чисто стартанули.

Коммит: 2c21512ae.


12. Документация (NEXT_STEPS)

docs/NEXT_STEPS.md переписан: все F1-F5/U1-U6/R1-R4 + audit задачи перенесены в CHANGELOG. Оставлены 3 кандидата на будущее (U2 SMS phone-lookup, /payments/process legacy, mobile EAS rebuild).

Расширил источники сигналов: добавил блок G — health PSP arkhyzpay-api. В cheat-sheet добавил «alembic stamp head» и «PSP outage».

Коммит: 6b4fe5eef.


13. Emergency disk cleanup

При финальной проверке нашёл диск на 91% (/dev/sda1: 139G / 154G). Auto-cleanup в проде запускается только в воскресенье 03:00 (arkhyz-disk-cleanup.timer).

Запустил вручную:

docker image prune -af
docker builder prune -af

Освобождено 26GB, диск 91% → 74%.


14. Финальная верификация

Прогнал 20-точечный чек по всем правкам сессии:

  • PSP файлы + routing в booking-svc — OK
  • arkhyzpay healthy (GET) — OK
  • alembic_version stamped — OK
  • payment_provider_default = yookassa — OK
  • pass-svc UUID validation — OK
  • Gemini-2.0-flash в 5 AI сервисах — OK (0 устаревших)
  • stuck_payment_canceller worker запущен — OK
  • Auto-deploy timer active — OK
  • error_events 24h = 0 — OK
  • broken_bookings 30d = 0 (все 5 типов) — OK
  • stuck_payments 24h = 0 — OK
  • errorReporter filter в admin-web бандле — OK
  • 3 self-hosted workflows — OK
  • tourist-app 9 chunks — OK
  • 11 public endpoints отвечают 200 — OK
  • 5 cabinet доменов 200 — OK
  • pay.arkhyz-club.ru 200 — OK
  • containers health — OK
  • disk 74% — OK
  • NEXT_STEPS обновлён — OK

Итог

Категория Закрыто
Backend code fixes 3 (gemini, UUID validation, PSP routing)
Frontend code fixes 1 (errorReporter network filter)
Infra/DevOps 4 (alembic stamp, healthcheck, disk, CI)
Refactor 3 (gen-routes, code splitting, NEXT_STEPS)
Audit 3 (errors, data, deployment)

Прод-состояние: 0 ошибок в error_events за 7 дней, 0 broken/stuck bookings, все эндпойнты 200, диск 74%, все контейнеры healthy.

Открытые задачи: бэклог пуст. 3 low-priority кандидата вынесены в NEXT_STEPS на будущее.


Отчёт сгенерирован автоматически из git log + task list.