Документация Блока 3 и версия 0.3.5
- docs/events.md дополнен схемой ClickHouse, агрегатами, регламентом хранения и списком уведомлений в чат логов - README описывает аналитику, уведомления, бэкап событий и структуру проекта - DEPLOY.md описывает сервис ClickHouse, проверку, настройку бэкапа и cron - примеры сообщений коммитов приведены к стилю без префиксов - версия 0.3.5
This commit is contained in:
parent
dbf78aa1d5
commit
cd9004c10f
71
DEPLOY.md
71
DEPLOY.md
|
|
@ -15,9 +15,13 @@ cd DispelEvilBot
|
|||
|
||||
```bash
|
||||
cp env/test.env.example env/test.env
|
||||
# заполнить: BOT_TOKEN, DB_PASSWORD, CHAT_ID (основной чат), ALERT_CHAT_ID (опц.), ADMIN_IDS (опц.)
|
||||
# заполнить: BOT_TOKEN, DB_PASSWORD, CHAT_ID (основной чат), ALERT_CHAT_ID (опц.),
|
||||
# ADMIN_IDS (опц.), CLICKHOUSE_PASSWORD (аналитика событий)
|
||||
```
|
||||
|
||||
Порт ClickHouse на хосте (`CLICKHOUSE_HTTP_PORT`) у контуров должен различаться:
|
||||
`prod` — `8123`, `test` — `8124` (иначе контейнеры конфликтуют на одной VPS).
|
||||
|
||||
## 3. Логин в registry (если пакет приватный)
|
||||
|
||||
```bash
|
||||
|
|
@ -46,7 +50,62 @@ docker compose -p test --env-file env/test.env -f docker-compose.prod.yml logs -
|
|||
|
||||
1. `postgres` поднимается и проходит healthcheck;
|
||||
2. `migrate` (**Flyway**) накатывает миграции из `sql/` — для пустой БД с нуля;
|
||||
3. `bot` стартует (`Запуск DispelEvilBot v<версия> (APP_ENV=...)`).
|
||||
3. `clickhouse` поднимается и применяет `clickhouse/init/001_events.sql` —
|
||||
**только при первой инициализации** пустого data-каталога;
|
||||
4. `bot` стартует (`Запуск DispelEvilBot v<версия> (APP_ENV=...)`), аналитика и рассылки — в нём же.
|
||||
|
||||
Проверка контура (сервисы, миграции, Postgres, ClickHouse):
|
||||
|
||||
```bash
|
||||
make check E=test
|
||||
```
|
||||
|
||||
## ClickHouse (аналитика событий)
|
||||
|
||||
События всех действий бота пишутся в `analytics.events` (контракт — [`docs/events.md`](docs/events.md)).
|
||||
ClickHouse наружу **не публикуется**: только loopback хоста (`127.0.0.1:${CLICKHOUSE_HTTP_PORT}`).
|
||||
|
||||
```bash
|
||||
make ch E=test # clickhouse-client контура
|
||||
# пример: события за сегодня по типам
|
||||
docker compose -p test --env-file env/test.env -f docker-compose.prod.yml exec -T clickhouse \
|
||||
clickhouse-client --user "$CLICKHOUSE_USER" --password "$CLICKHOUSE_PASSWORD" \
|
||||
--query "SELECT event_type, count() FROM analytics.events WHERE toDate(event_time) = today() GROUP BY event_type"
|
||||
```
|
||||
|
||||
Если ClickHouse недоступен, бот продолжает работать: события уходят в stdout (WARNING),
|
||||
полностью выключить можно флагом `CLICKHOUSE_ENABLED=false`.
|
||||
|
||||
Изменения схемы: `clickhouse/init/*.sql` применяются лишь на пустом data-каталоге,
|
||||
поэтому на существующем контуре DDL нужно применить вручную (`make ch E=...`).
|
||||
|
||||
## Бэкап событий на домашний сервер
|
||||
|
||||
Сырые события живут на VPS ограниченное время: раз в сутки вчерашняя партиция
|
||||
выгружается в `Parquet.gz`, передаётся на домашний сервер, импортируется в тамошний
|
||||
ClickHouse и сверяется по количеству строк — **только после сверки** партиции старше
|
||||
`BACKUP_GRACE_DAYS` (по умолчанию 7) удаляются на VPS. На VPS остаются агрегаты
|
||||
(`events_daily`, `money_daily`).
|
||||
|
||||
Разовая настройка:
|
||||
|
||||
```bash
|
||||
cp env/backup.env.example env/backup.env # BACKUP_REMOTE, BACKUP_DIR, BACKUP_SSH_KEY, ...
|
||||
# на домашнем сервере (в каталоге, куда кладутся архивы) разместить:
|
||||
# scripts/clickhouse_import.sh
|
||||
# clickhouse/init/001_events.sql -> как 001_events.sql рядом со скриптом
|
||||
```
|
||||
|
||||
Проверочный прогон (без cron): `make backup E=test`.
|
||||
|
||||
Cron на VPS (вчерашний день уже закрыт, время московское):
|
||||
|
||||
```cron
|
||||
0 4 * * * cd /opt/DispelEvilBot && ./scripts/clickhouse_backup.sh test >> /var/log/clickhouse-backup-test.log 2>&1
|
||||
```
|
||||
|
||||
Ошибка на любом шаге оставляет данные на VPS (партиции не удаляются) и пишет понятный лог.
|
||||
Импорт дня идемпотентен: повторный прогон не дублирует строки.
|
||||
|
||||
## Обновление и откат
|
||||
|
||||
|
|
@ -67,7 +126,13 @@ docker compose -p <контур> --env-file env/<контур>.env -f docker-com
|
|||
|
||||
## Переменные окружения
|
||||
|
||||
См. `env/prod.env.example` / `env/test.env.example`.
|
||||
См. `env/prod.env.example` / `env/test.env.example` (контуры) и `env/backup.env.example` (бэкап событий).
|
||||
|
||||
## Дашборд (позже)
|
||||
|
||||
Superset поднимается на домашнем сервере и читает **локальный** ClickHouse с полной
|
||||
историей событий (сюда ежедневно приезжают архивы). Отдельный read-only пользователь
|
||||
ClickHouse и сам дашборд — финальный этап, в этот контур не входят.
|
||||
|
||||
## Перенос данных на прод (позже, короткое окно простоя)
|
||||
|
||||
|
|
|
|||
49
README.md
49
README.md
|
|
@ -6,9 +6,12 @@ Telegram-бот клана Dispel Evil (aiogram 3 + Postgres). Монорепо
|
|||
## Структура
|
||||
|
||||
```
|
||||
common/ # общий пакет: config, logging, db, repositories, models, texts
|
||||
bot/ # сервис бота: handlers, services, keyboards, notifications
|
||||
common/ # общий пакет: config, logging, db, repositories, models, texts, analytics
|
||||
bot/ # сервис бота: handlers, services, keyboards, middlewares, notifications
|
||||
sql/ # миграции Flyway (V__*.sql, R__*.sql)
|
||||
clickhouse/ # init-скрипты ClickHouse (схема аналитики)
|
||||
docs/ # документация (docs/events.md — события аналитики)
|
||||
scripts/ # эксплуатационные скрипты (проверка контура, бэкап событий)
|
||||
images/ # статичные картинки (приветствие)
|
||||
deploy/ # материалы деплоя (Caddyfile, инструкции)
|
||||
tests/ # тесты
|
||||
|
|
@ -21,6 +24,7 @@ docker-compose.yml / docker-compose.prod.yml
|
|||
|
||||
- Python 3.12
|
||||
- PostgreSQL 14+
|
||||
- ClickHouse 25.3 (аналитика событий; можно выключить — `CLICKHOUSE_ENABLED=false`)
|
||||
|
||||
## Настройка
|
||||
|
||||
|
|
@ -44,9 +48,25 @@ APP_ENV=prod python -m bot # prod
|
|||
Схема управляется миграциями **Flyway** в `sql/` (`V__*.sql` — versioned, `R__*.sql` — repeatable).
|
||||
При Docker-развёртывании накат выполняется автоматически сервисом `migrate` перед ботом.
|
||||
|
||||
## Аналитика (ClickHouse)
|
||||
|
||||
Все значимые действия бота пишутся в ClickHouse в единую таблицу `analytics.events`.
|
||||
Контракт событий — [`docs/events.md`](docs/events.md) (типы, payload, примеры запросов).
|
||||
|
||||
- схема — `clickhouse/init/001_events.sql` (применяется при первой инициализации контейнера);
|
||||
- клиент и батчинг — `common/analytics/` (запись неблокирующая, сбой ClickHouse не влияет на бота);
|
||||
- сырые события живут на VPS 7 дней и ежедневно уезжают архивом на домашний сервер,
|
||||
на VPS остаются агрегаты (`events_daily`, `money_daily`) — см. [DEPLOY.md](DEPLOY.md);
|
||||
- выключается флагом `CLICKHOUSE_ENABLED=false`.
|
||||
|
||||
## Уведомления в чат логов
|
||||
|
||||
В `ALERT_CHAT_ID` (если задан) уходят: вход и выход участников, успешные очищения и
|
||||
ежечасный пинг «бот живой». Отправка не критична: ошибки только пишутся в лог.
|
||||
|
||||
## Docker
|
||||
|
||||
Локальный запуск (postgres + migrate + bot):
|
||||
Локальный запуск (postgres + migrate + clickhouse + bot):
|
||||
|
||||
```bash
|
||||
cp .env.example .env # заполнить
|
||||
|
|
@ -71,9 +91,20 @@ black --check .
|
|||
pytest
|
||||
```
|
||||
|
||||
## Бэкап событий
|
||||
|
||||
Сырые события ClickHouse ежедневно выгружаются архивом на домашний сервер (по cron),
|
||||
на VPS остаются только агрегаты и последние дни сырых данных:
|
||||
|
||||
```bash
|
||||
make backup E=test # ./scripts/clickhouse_backup.sh test
|
||||
```
|
||||
|
||||
Настройка и расписание — см. [`DEPLOY.md`](DEPLOY.md).
|
||||
|
||||
## Версионирование
|
||||
|
||||
- Единый источник версии — `common/version.py` (`__version__`), текущая — `0.3.4`.
|
||||
- Единый источник версии — `common/version.py` (`__version__`), текущая — `0.3.5`.
|
||||
- Схема — SemVer-подобная (`MAJOR.MINOR.PATCH`); git-тег = `v` + версия (`v0.1`).
|
||||
- Docker-образы тегируются версией (Блок 2), события ClickHouse получают `bot_version` (Блок 3).
|
||||
- Выпуск: изменить `common/version.py` → коммит → аннотированный тег `vX.Y` → `git push --tags`.
|
||||
|
|
@ -90,14 +121,14 @@ pytest
|
|||
- Переход на «ветки + PR» и защиту ветки — когда появится второй разработчик.
|
||||
|
||||
```bash
|
||||
# обычная работа
|
||||
# обычная работа: сообщение без префиксов, по существу изменения
|
||||
git add -A
|
||||
git commit -m "feat: ..."
|
||||
git commit -m "Краткое описание изменения"
|
||||
git push origin master
|
||||
|
||||
# выпуск релиза
|
||||
# 1) поднять __version__ в common/version.py
|
||||
git commit -am "chore: bump version to X.Y"
|
||||
git commit -am "Версия X.Y"
|
||||
git tag -a vX.Y -m "Release vX.Y"
|
||||
git push origin master --tags
|
||||
```
|
||||
|
|
@ -109,4 +140,6 @@ git push origin master --tags
|
|||
|
||||
## Переменные окружения
|
||||
|
||||
См. `.env.example`.
|
||||
- общие — `.env.example` (включая `CLICKHOUSE_*` и параметры батчинга `ANALYTICS_*`);
|
||||
- контуры — `env/prod.env.example`, `env/test.env.example`;
|
||||
- бэкап событий — `env/backup.env.example`.
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
__version__ = "0.3.4"
|
||||
__version__ = "0.3.5"
|
||||
|
|
|
|||
|
|
@ -8,6 +8,48 @@
|
|||
> Расхождение со списком ниже ловит `tests/test_analytics.py`.
|
||||
> Добавляешь событие — добавь строку в таблицу.
|
||||
|
||||
## Схема в ClickHouse
|
||||
|
||||
DDL — `clickhouse/init/001_events.sql` (применяется при первой инициализации контейнера).
|
||||
|
||||
- `analytics.events` — сырые события, `MergeTree`, `PARTITION BY toYYYYMMDD(event_time)`,
|
||||
`ORDER BY (event_time, event_type, user_id)`. Партиционирование по дню выбрано специально:
|
||||
сырые партиции ежедневно удаляются после бэкапа (дешёвый `DROP PARTITION`, без mutation).
|
||||
- `analytics.events_daily` — агрегат (`SummingMergeTree`): `day`, `event_type`, `user_id`,
|
||||
`chat_id`, `events`. Строится материализованным представлением `events_daily_mv`.
|
||||
- `analytics.money_daily` — агрегат по деньгам: `day`, `event_type`, `user_id`,
|
||||
`amount_sum`, `events` (из `payload.amount` событий `money_accrual`/`money_spend`).
|
||||
|
||||
Агрегаты остаются на VPS навсегда, поэтому активность, топ команд и денежные потоки
|
||||
доступны и после удаления сырых событий. Запросы к агрегатам суммируют `events`/`amount_sum`
|
||||
(фон слияний `SummingMergeTree` не гарантирует полную свёртку в любой момент).
|
||||
|
||||
## Хранение и бэкап
|
||||
|
||||
| Что | Где | Сколько |
|
||||
| --- | --- | --- |
|
||||
| Сырые события | VPS, `analytics.events` | последние `BACKUP_GRACE_DAYS` дней (по умолчанию 7) |
|
||||
| Агрегаты | VPS | постоянно |
|
||||
| Полная история | домашний сервер, свой ClickHouse | архивы `events_YYYY-MM-DD.parquet.gz` (ежедневно) |
|
||||
|
||||
Каждую ночь (по Москве) `scripts/clickhouse_backup.sh` выгружает вчерашнюю партицию,
|
||||
передаёт её на домашний сервер, импортирует и **сверяет количество строк**; только после
|
||||
успешной сверки на VPS удаляются партиции старше грейса. Ошибка бэкапа данные не удаляет.
|
||||
Подробности — `DEPLOY.md`.
|
||||
|
||||
## Уведомления в чат логов
|
||||
|
||||
Помимо записи в ClickHouse часть событий дублируется сообщением в `ALERT_CHAT_ID`
|
||||
(если он задан; `0` — выключено). Отправка не критична: ошибки только логируются.
|
||||
|
||||
| Уведомление | Когда | Событие в ClickHouse |
|
||||
| --- | --- | --- |
|
||||
| Вход участника | кто-то вошёл в основной чат | `join` |
|
||||
| Выход участника | кто-то вышел из основного чата | `leave` |
|
||||
| Очищение | успешное `/очищение` (`+опыт`, `+монеты`) | `purification` |
|
||||
| Пинг «бот живой» | раз в час | `bot_alive` |
|
||||
| Попытка доступа извне | не участник чата стучится в бота | `access_denied` |
|
||||
|
||||
## Поля события
|
||||
|
||||
| Поле | Тип | Описание |
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ from common import __version__
|
|||
|
||||
def test_version_is_set():
|
||||
assert __version__
|
||||
assert __version__ == "0.3.4"
|
||||
assert __version__ == "0.3.5"
|
||||
|
|
|
|||
Loading…
Reference in New Issue