Бэкап событий переведён на pull с домашнего сервера

- скрипт бэкапа запускается на домашнем сервере и сам забирает вчерашнюю партицию с VPS по ssh
- входящий ssh на домашний сервер больше не нужен, rsync не требуется
- выгрузка идёт через docker compose на VPS, пароль ClickHouse читается из окружения контейнера
- архив пишется сначала во временный файл, импорт идемпотентен, удаление партиций только после сверки
- env/backup.env.example переписан под новые параметры, cron теперь на домашнем сервере
- версия 0.3.7
This commit is contained in:
MpakobecEx 2026-10-16 15:57:22 +05:00
parent a0fa223eaa
commit 2a88fab0b4
9 changed files with 116 additions and 115 deletions

View File

@ -79,29 +79,34 @@ docker compose -p test --env-file env/test.env -f docker-compose.prod.yml exec -
Изменения схемы: `clickhouse/init/*.sql` применяются лишь на пустом data-каталоге, Изменения схемы: `clickhouse/init/*.sql` применяются лишь на пустом data-каталоге,
поэтому на существующем контуре DDL нужно применить вручную (`make ch E=...`). поэтому на существующем контуре DDL нужно применить вручную (`make ch E=...`).
## Бэкап событий на домашний сервер ## Бэкап событий (забирает домашний сервер)
Сырые события живут на VPS ограниченное время: раз в сутки вчерашняя партиция Сырые события живут на VPS ограниченное время: раз в сутки домашний сервер **сам забирает**
выгружается в `Parquet.gz`, передаётся на домашний сервер, импортируется в тамошний вчерашнюю партицию (`pull`), складывает её в `Parquet.gz`, импортирует в свой ClickHouse и
ClickHouse и сверяется по количеству строк — **только после сверки** партиции старше сверяет количество строк — **только после сверки** на VPS удаляются партиции старше
`BACKUP_GRACE_DAYS` (по умолчанию 7) удаляются на VPS. На VPS остаются агрегаты `BACKUP_GRACE_DAYS` (по умолчанию 7). На VPS остаются агрегаты (`events_daily`, `money_daily`).
(`events_daily`, `money_daily`).
Входящий SSH на домашний сервер не нужен: он инициирует соединение сам.
Разовая настройка: Разовая настройка:
```bash ```bash
cp env/backup.env.example env/backup.env # BACKUP_REMOTE, BACKUP_DIR, BACKUP_SSH_KEY, ... # на домашнем сервере
# на домашнем сервере (в каталоге, куда кладутся архивы) разместить: git clone ssh://git@<gitea-host>:2222/mpakobecex/DispelEvilBot.git
# scripts/clickhouse_import.sh cd DispelEvilBot
# clickhouse/init/001_events.sql -> как 001_events.sql рядом со скриптом cp env/backup.env.example env/backup.env # VPS_SSH, VPS_PORT, VPS_PROJECT_DIR, VPS_SSH_KEY, BACKUP_DIR, CLICKHOUSE_*
``` ```
Проверочный прогон (без cron): `make backup E=test`. Требования: на VPS — пользователь с доступом к `docker` и каталог с репозиторием
(`VPS_PROJECT_DIR`, там запускается `docker compose`); на домашнем сервере — `clickhouse-client`
и локальный ClickHouse. Настройка SSH-доступа — `deploy/ssh-access.md`.
Cron на VPS (вчерашний день уже закрыт, время московское): Проверочный прогон (без cron): `make backup E=test` или `./scripts/clickhouse_backup.sh test`.
Cron на домашнем сервере (вчерашний день уже закрыт, время московское):
```cron ```cron
0 4 * * * cd /opt/DispelEvilBot && ./scripts/clickhouse_backup.sh test >> /var/log/clickhouse-backup-test.log 2>&1 0 4 * * * cd /srv/DispelEvilBot && ./scripts/clickhouse_backup.sh test >> /var/log/clickhouse-backup-test.log 2>&1
``` ```
Ошибка на любом шаге оставляет данные на VPS (партиции не удаляются) и пишет понятный лог. Ошибка на любом шаге оставляет данные на VPS (партиции не удаляются) и пишет понятный лог.

View File

@ -23,7 +23,7 @@ help:
> @echo " make check E=test проверка контура (скрипт)" > @echo " make check E=test проверка контура (скрипт)"
> @echo " make psql E=test psql в БД контура" > @echo " make psql E=test psql в БД контура"
> @echo " make ch E=test clickhouse-client контура" > @echo " make ch E=test clickhouse-client контура"
> @echo " make backup E=test бэкап вчерашних событий на домашний сервер" > @echo " make backup E=test бэкап событий с VPS (запускать на домашнем сервере)"
up: up:
> $(COMPOSE) up -d > $(COMPOSE) up -d

View File

@ -93,18 +93,18 @@ pytest
## Бэкап событий ## Бэкап событий
Сырые события ClickHouse ежедневно выгружаются архивом на домашний сервер (по cron), Сырые события ClickHouse ежедневно забираются с VPS домашним сервером (`pull`), на VPS
на VPS остаются только агрегаты и последние дни сырых данных: остаются только агрегаты и последние дни сырых данных:
```bash ```bash
make backup E=test # ./scripts/clickhouse_backup.sh test make backup E=test # на домашнем сервере: ./scripts/clickhouse_backup.sh test
``` ```
Настройка и расписание — см. [`DEPLOY.md`](DEPLOY.md). Настройка, cron и SSH-доступ — см. [`DEPLOY.md`](DEPLOY.md).
## Версионирование ## Версионирование
- Единый источник версии — `common/version.py` (`__version__`), текущая — `0.3.6`. - Единый источник версии — `common/version.py` (`__version__`), текущая — `0.3.7`.
- Схема — SemVer-подобная (`MAJOR.MINOR.PATCH`); git-тег = `v` + версия (`v0.1`). - Схема — SemVer-подобная (`MAJOR.MINOR.PATCH`); git-тег = `v` + версия (`v0.1`).
- Docker-образы тегируются версией (Блок 2), события ClickHouse получают `bot_version` (Блок 3). - Docker-образы тегируются версией (Блок 2), события ClickHouse получают `bot_version` (Блок 3).
- Выпуск: изменить `common/version.py` → коммит → аннотированный тег `vX.Y` → `git push --tags`. - Выпуск: изменить `common/version.py` → коммит → аннотированный тег `vX.Y` → `git push --tags`.

View File

@ -7,4 +7,4 @@
from __future__ import annotations from __future__ import annotations
__version__ = "0.3.6" __version__ = "0.3.7"

View File

@ -32,10 +32,10 @@ DDL — `clickhouse/init/001_events.sql` (применяется при перв
| Агрегаты | VPS | постоянно | | Агрегаты | VPS | постоянно |
| Полная история | домашний сервер, свой ClickHouse | архивы `events_YYYY-MM-DD.parquet.gz` (ежедневно) | | Полная история | домашний сервер, свой ClickHouse | архивы `events_YYYY-MM-DD.parquet.gz` (ежедневно) |
Каждую ночь (по Москве) `scripts/clickhouse_backup.sh` выгружает вчерашнюю партицию, Каждую ночь (по Москве) домашний сервер **сам забирает** вчерашнюю партицию с VPS (`pull`
передаёт её на домашний сервер, импортирует и **сверяет количество строк**; только после по ssh), импортирует её в свой ClickHouse и **сверяет количество строк**; только после
успешной сверки на VPS удаляются партиции старше грейса. Ошибка бэкапа данные не удаляет. успешной сверки он просит VPS удалить партиции старше грейса. Ошибка бэкапа данные не
Подробности — `DEPLOY.md`. удаляет. Подробности — `DEPLOY.md` и `deploy/ssh-access.md`.
## Уведомления в чат логов ## Уведомления в чат логов

View File

@ -1,28 +1,32 @@
# Параметры ежедневного бэкапа событий ClickHouse с VPS на домашний сервер. # Параметры бэкапа событий ClickHouse (pull: домашний сервер забирает данные с VPS).
# Скопируйте в env/backup.env (env/*.env в git не попадает) и заполните. # Скопируйте в env/backup.env (env/*.env в git не попадает) и заполните.
# #
# Используется скриптами: # Запускается НА ДОМАШНЕМ СЕРВЕРЕ по cron:
# scripts/clickhouse_backup.sh (запускается на VPS по cron, см. DEPLOY.md) # scripts/clickhouse_backup.sh test|prod
# scripts/clickhouse_import.sh (лежит на домашнем сервере) #
# SSH-доступ к VPS настраивается отдельно (инструкция — deploy/ssh-access.md).
# Куда передавать архивы: пользователь@хост и каталог на домашнем сервере. # --- VPS ---
BACKUP_REMOTE=user@home.example # user@host (хост указывайте без скобок; порт задаётся отдельно)
VPS_SSH=deploy@vps.example
VPS_PORT=27
# Каталог с репозиторием на VPS (там запускается docker compose)
VPS_PROJECT_DIR=/opt/DispelEvilBot
# Приватный ключ для ssh на VPS (публичная часть добавлена в authorized_keys на VPS)
VPS_SSH_KEY=/root/.ssh/id_ed25519_vps
# --- Домашний сервер ---
# Куда складывать архивы events_YYYY-MM-DD.parquet.gz
BACKUP_DIR=/srv/dispelevilbot/events BACKUP_DIR=/srv/dispelevilbot/events
# Приватный ключ для ssh/rsync (без пароля; на домашнем сервере — соответствующий public key). # --- Хранение ---
BACKUP_SSH_KEY=/root/.ssh/dispelevilbot_backup # Сколько дней сырых событий остаётся на VPS (остальное удаляется после успешной сверки)
# Сколько дней сырых событий оставлять на VPS (остальное удаляется после успешной сверки).
BACKUP_GRACE_DAYS=7 BACKUP_GRACE_DAYS=7
# Таймзона расчёта «вчерашнего» дня
# Таймзона расчёта «вчерашнего» дня.
BACKUP_TZ=Europe/Moscow BACKUP_TZ=Europe/Moscow
# Как запускать импорт на домашнем сервере (путь к scripts/clickhouse_import.sh). # --- ClickHouse домашнего сервера (сюда импортируются архивы) ---
REMOTE_IMPORT_SCRIPT=./clickhouse_import.sh CLICKHOUSE_HOST=localhost
CLICKHOUSE_PORT=9000
# ClickHouse домашнего сервера. Пароль лучше без кавычек и пробелов — он передаётся по ssh. CLICKHOUSE_USER=default
REMOTE_CLICKHOUSE_HOST=localhost CLICKHOUSE_PASSWORD=
REMOTE_CLICKHOUSE_PORT=9000
REMOTE_CLICKHOUSE_USER=default
REMOTE_CLICKHOUSE_PASSWORD=

View File

@ -1,32 +1,28 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Ежедневный бэкап сырых событий ClickHouse с VPS на домашний сервер. # Бэкап сырых событий ClickHouse: домашний сервер забирает данные с VPS (pull).
#
# Запускается НА ДОМАШНЕМ СЕРВЕРЕ по cron. Входящий SSH на домашний сервер не нужен:
# скрипт сам ходит на VPS по ключу и запускает там docker compose.
# #
# Что делает: # Что делает:
# 1) выгружает партицию «вчерашнего» дня из analytics.events в Parquet.gz; # 1) по ssh выгружает на VPS вчерашнюю партицию analytics.events в Parquet;
# 2) передаёт файл на домашний сервер (rsync) и импортирует его в тамошний ClickHouse; # 2) складывает events_YYYY-MM-DD.parquet.gz в BACKUP_DIR;
# 3) сверяет количество строк на VPS и на домашнем сервере; # 3) импортирует архив в локальный ClickHouse (идемпотентно, scripts/clickhouse_import.sh);
# 4) только после успешной сверки удаляет на VPS партиции старше BACKUP_GRACE_DAYS. # 4) сверяет количество строк на VPS и локально;
# 5) только после успешной сверки просит VPS удалить партиции старше BACKUP_GRACE_DAYS.
# #
# Ошибка на любом шаге оставляет данные на VPS и возвращает ненулевой код. # Ошибка на любом шаге оставляет данные на VPS (партиции не удаляются) и возвращает ненулевой код.
# #
# Запуск (на VPS, из каталога проекта): # Использование:
# ./scripts/clickhouse_backup.sh test # или prod # ./scripts/clickhouse_backup.sh test # или prod
# make backup E=test # make backup E=test
# #
# Настройки (env/<контур>.env + env/backup.env, см. env/backup.env.example): # Настройки — env/backup.env (см. env/backup.env.example).
# CLICKHOUSE_* доступ к ClickHouse контура
# BACKUP_REMOTE user@host домашнего сервера
# BACKUP_DIR каталог архива на домашнем сервере
# BACKUP_SSH_KEY приватный ключ для ssh/rsync
# BACKUP_GRACE_DAYS сколько дней сырых событий оставлять на VPS (по умолчанию 7)
# BACKUP_TZ таймзона расчёта «вчера» (по умолчанию Europe/Moscow)
set -euo pipefail set -euo pipefail
E="${1:-test}" E="${1:-test}"
ENV_FILE="env/${E}.env" BACKUP_ENV="${BACKUP_ENV:-env/backup.env}"
BACKUP_ENV="env/backup.env"
COMPOSE="docker compose -p ${E} --env-file ${ENV_FILE} -f docker-compose.prod.yml"
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; } log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
fail() { fail() {
@ -34,76 +30,72 @@ fail() {
exit 1 exit 1
} }
[ -f "$ENV_FILE" ] || fail "нет файла окружения ${ENV_FILE}" [ -f "$BACKUP_ENV" ] || fail "нет файла настроек ${BACKUP_ENV} (скопируйте env/backup.env.example)"
# shellcheck disable=SC1090
set -a && . "./${ENV_FILE}" && set +a
if [ -f "$BACKUP_ENV" ]; then
# shellcheck disable=SC1090 # shellcheck disable=SC1090
set -a && . "./${BACKUP_ENV}" && set +a set -a && . "./${BACKUP_ENV}" && set +a
fi
: "${BACKUP_REMOTE:?задайте BACKUP_REMOTE в env/backup.env}" : "${VPS_SSH:?задайте VPS_SSH в env/backup.env}"
: "${BACKUP_DIR:?задайте BACKUP_DIR в env/backup.env}" : "${BACKUP_DIR:?задайте BACKUP_DIR в env/backup.env}"
BACKUP_SSH_KEY="${BACKUP_SSH_KEY:-$HOME/.ssh/id_rsa}" VPS_PORT="${VPS_PORT:-22}"
VPS_PROJECT_DIR="${VPS_PROJECT_DIR:?задайте VPS_PROJECT_DIR в env/backup.env}"
VPS_SSH_KEY="${VPS_SSH_KEY:-$HOME/.ssh/id_ed25519_vps}"
VPS_COMPOSE_FILE="${VPS_COMPOSE_FILE:-docker-compose.prod.yml}"
BACKUP_GRACE_DAYS="${BACKUP_GRACE_DAYS:-7}" BACKUP_GRACE_DAYS="${BACKUP_GRACE_DAYS:-7}"
BACKUP_TZ="${BACKUP_TZ:-Europe/Moscow}" BACKUP_TZ="${BACKUP_TZ:-Europe/Moscow}"
REMOTE_IMPORT_SCRIPT="${REMOTE_IMPORT_SCRIPT:-./clickhouse_import.sh}" IMPORT_SCRIPT="${IMPORT_SCRIPT:-$(dirname "$0")/clickhouse_import.sh}"
REMOTE_CLICKHOUSE_HOST="${REMOTE_CLICKHOUSE_HOST:-localhost}" SCHEMA_FILE="${SCHEMA_FILE:-$(dirname "$0")/../clickhouse/init/001_events.sql}"
REMOTE_CLICKHOUSE_PORT="${REMOTE_CLICKHOUSE_PORT:-9000}"
REMOTE_CLICKHOUSE_USER="${REMOTE_CLICKHOUSE_USER:-default}"
REMOTE_CLICKHOUSE_PASSWORD="${REMOTE_CLICKHOUSE_PASSWORD:-}"
SSH=(ssh -i "$BACKUP_SSH_KEY" -o BatchMode=yes "$BACKUP_REMOTE")
ch() { SSH=(ssh -i "$VPS_SSH_KEY" -p "$VPS_PORT" -o BatchMode=yes -o ServerAliveInterval=30 "$VPS_SSH")
$COMPOSE exec -T clickhouse clickhouse-client \
--user "$CLICKHOUSE_USER" --password "$CLICKHOUSE_PASSWORD" "$@" # Запустить команду на VPS. Пароль ClickHouse читается из окружения контейнера,
# поэтому клиент вызывается через `sh -c` уже внутри контейнера.
vps_ch() {
"${SSH[@]}" bash -s "$VPS_PROJECT_DIR" "$E" "$VPS_COMPOSE_FILE" "$@" <<'REMOTE'
set -euo pipefail
project_dir="$1"; contour="$2"; compose_file="$3"; shift 3
cd "$project_dir"
exec docker compose -p "$contour" --env-file "env/$contour.env" -f "$compose_file" exec -T clickhouse \
sh -c 'clickhouse-client --user "$CLICKHOUSE_USER" --password "$CLICKHOUSE_PASSWORD" "$@"' sh "$@"
REMOTE
} }
DAY="$(TZ="$BACKUP_TZ" date -d 'yesterday' '+%Y-%m-%d')" DAY="$(TZ="$BACKUP_TZ" date -d 'yesterday' '+%Y-%m-%d')"
PARTITION="${DAY//-/}" PARTITION="${DAY//-/}"
GRACE_CUTOFF="$(TZ="$BACKUP_TZ" date -d "${BACKUP_GRACE_DAYS} days ago" '+%Y%m%d')" GRACE_CUTOFF="$(TZ="$BACKUP_TZ" date -d "${BACKUP_GRACE_DAYS} days ago" '+%Y%m%d')"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT
log "Контур ${E}: бэкап событий за ${DAY} (грейс ${BACKUP_GRACE_DAYS} дней, порог ${GRACE_CUTOFF})" log "Бэкап событий контура ${E} за ${DAY} (грейс ${BACKUP_GRACE_DAYS} дней, порог ${GRACE_CUTOFF})"
if ! $COMPOSE ps --services --status running 2>/dev/null | grep -qx clickhouse; then mkdir -p "$BACKUP_DIR"
fail "контейнер clickhouse контура ${E} не запущен" ARCHIVE="${BACKUP_DIR}/events_${DAY}.parquet.gz"
fi
ROWS_LOCAL="$(ch --query "SELECT count() FROM analytics.events WHERE toDate(event_time) = toDate('${DAY}')" | tr -d '[:space:]')" ROWS_VPS="$(vps_ch --param_day="$DAY" --query "SELECT count() FROM analytics.events WHERE toDate(event_time) = toDate({day:String})" | tr -d '[:space:]')"
log "На VPS строк за ${DAY}: ${ROWS_LOCAL}" log "На VPS строк за ${DAY}: ${ROWS_VPS}"
if [ "$ROWS_LOCAL" = "0" ]; then if [ "$ROWS_VPS" = "0" ]; then
log "ВНИМАНИЕ: за ${DAY} событий нет — партиция пустая, продолжаю (сверка 0 = 0)" log "ВНИМАНИЕ: за ${DAY} событий нет — партиция пустая, продолжаю (сверка 0 = 0)"
fi fi
ARCHIVE="${TMP_DIR}/events_${DAY}.parquet.gz"
log "Выгружаю партицию в ${ARCHIVE}" log "Выгружаю партицию в ${ARCHIVE}"
ch --query "SELECT * FROM analytics.events WHERE toDate(event_time) = toDate('${DAY}') FORMAT Parquet" | gzip -9 >"$ARCHIVE" vps_ch --param_day="$DAY" --query "SELECT * FROM analytics.events WHERE toDate(event_time) = toDate({day:String}) FORMAT Parquet" |
[ -s "$ARCHIVE" ] || fail "не удалось выгрузить архив ${DAY}" gzip -9 >"${ARCHIVE}.part"
[ -s "${ARCHIVE}.part" ] || fail "не удалось выгрузить архив ${DAY}"
mv "${ARCHIVE}.part" "$ARCHIVE"
log "Размер архива: $(du -h "$ARCHIVE" | cut -f1)" log "Размер архива: $(du -h "$ARCHIVE" | cut -f1)"
log "Передаю архив на ${BACKUP_REMOTE}:${BACKUP_DIR}"
rsync -az -e "ssh -i ${BACKUP_SSH_KEY} -o BatchMode=yes" "$ARCHIVE" "${BACKUP_REMOTE}:${BACKUP_DIR}/"
log "Импортирую архив в ClickHouse домашнего сервера" log "Импортирую архив в ClickHouse домашнего сервера"
ROWS_REMOTE="$("${SSH[@]}" \ ROWS_HOME="$(BACKUP_DIR="$BACKUP_DIR" SCHEMA_FILE="$SCHEMA_FILE" "$IMPORT_SCRIPT" "$DAY" | tail -n1 | tr -d '[:space:]')"
"BACKUP_DIR='${BACKUP_DIR}' CLICKHOUSE_HOST='${REMOTE_CLICKHOUSE_HOST}' CLICKHOUSE_PORT='${REMOTE_CLICKHOUSE_PORT}' \ log "На домашнем сервере строк за ${DAY}: ${ROWS_HOME}"
CLICKHOUSE_USER='${REMOTE_CLICKHOUSE_USER}' CLICKHOUSE_PASSWORD='${REMOTE_CLICKHOUSE_PASSWORD}' \
'${REMOTE_IMPORT_SCRIPT}' '${DAY}'" | tail -n1 | tr -d '[:space:]')"
log "На домашнем сервере строк за ${DAY}: ${ROWS_REMOTE}"
[ "$ROWS_LOCAL" = "$ROWS_REMOTE" ] || fail "расхождение строк (VPS ${ROWS_LOCAL}, домашний ${ROWS_REMOTE}) — партиции на VPS не удаляю" [ "$ROWS_VPS" = "$ROWS_HOME" ] || fail "расхождение строк (VPS ${ROWS_VPS}, домашний ${ROWS_HOME}) — партиции на VPS не удаляю"
log "Удаляю на VPS партиции старше ${GRACE_CUTOFF}" log "Удаляю на VPS партиции старше ${GRACE_CUTOFF}"
OLDER="$(ch --query "SELECT DISTINCT partition FROM system.parts WHERE database='analytics' AND table='events' AND active AND partition < '${GRACE_CUTOFF}'")" DROPPED="$(vps_ch --query "SELECT DISTINCT partition FROM system.parts WHERE database='analytics' AND table='events' AND active AND partition < '${GRACE_CUTOFF}'")"
if [ -z "$OLDER" ]; then if [ -z "$DROPPED" ]; then
log "Удалять нечего" log "Удалять нечего"
else else
for partition in $OLDER; do for partition in $DROPPED; do
log "DROP PARTITION ID '${partition}'" log "DROP PARTITION ID '${partition}'"
ch --query "ALTER TABLE analytics.events DROP PARTITION ID '${partition}'" vps_ch --query "ALTER TABLE analytics.events DROP PARTITION ID '${partition}'"
done done
fi fi
log "Готово: события за ${DAY} в архиве, на VPS остались агрегаты и последние ${BACKUP_GRACE_DAYS} дней сырых событий" log "Готово: события за ${DAY} в архиве ${ARCHIVE}, на VPS остались агрегаты и последние ${BACKUP_GRACE_DAYS} дней сырых событий"

View File

@ -1,16 +1,16 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Импорт дневного архива событий в ClickHouse домашнего сервера. # Импорт дневного архива событий в ClickHouse домашнего сервера.
# #
# Запускается на домашнем сервере (обычно по ssh из scripts/clickhouse_backup.sh). # Запускается на домашнем сервере; обычно вызывается из scripts/clickhouse_backup.sh,
# Рядом должны лежать этот скрипт и канонический DDL кликхаус-схемы # но можно и вручную — например, чтобы повторно залить архив после сбоя.
# (clickhouse/init/001_events.sql из репозитория).
# #
# Использование: ./clickhouse_import.sh 2026-01-01 # Использование:
# ./scripts/clickhouse_import.sh 2026-01-01
# В stdout печатается количество строк загруженного дня (для сверки), диагностика — в stderr. # В stdout печатается количество строк загруженного дня (для сверки), диагностика — в stderr.
# #
# Настройки (окружение): # Настройки (окружение):
# BACKUP_DIR каталог, куда складываются архивы events_YYYY-MM-DD.parquet.gz # BACKUP_DIR каталог с архивами events_YYYY-MM-DD.parquet.gz
# SCHEMA_FILE путь к DDL схемы (по умолчанию ./001_events.sql рядом со скриптом) # SCHEMA_FILE DDL схемы (по умолчанию clickhouse/init/001_events.sql рядом с репозиторием)
# CLICKHOUSE_CLIENT бинарь клиента (по умолчанию clickhouse-client) # CLICKHOUSE_CLIENT бинарь клиента (по умолчанию clickhouse-client)
# CLICKHOUSE_HOST/PORT/USER/PASSWORD доступ к ClickHouse домашнего сервера # CLICKHOUSE_HOST/PORT/USER/PASSWORD доступ к ClickHouse домашнего сервера
@ -21,7 +21,7 @@ PARTITION="${DAY//-/}"
ARCHIVE_DIR="${BACKUP_DIR:-.}" ARCHIVE_DIR="${BACKUP_DIR:-.}"
ARCHIVE="${ARCHIVE_DIR}/events_${DAY}.parquet.gz" ARCHIVE="${ARCHIVE_DIR}/events_${DAY}.parquet.gz"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCHEMA_FILE="${SCHEMA_FILE:-${SCRIPT_DIR}/001_events.sql}" SCHEMA_FILE="${SCHEMA_FILE:-${SCRIPT_DIR}/../clickhouse/init/001_events.sql}"
CLIENT="${CLICKHOUSE_CLIENT:-clickhouse-client}" CLIENT="${CLICKHOUSE_CLIENT:-clickhouse-client}"
@ -40,7 +40,7 @@ ch() {
exit 1 exit 1
} }
[ -f "$SCHEMA_FILE" ] || { [ -f "$SCHEMA_FILE" ] || {
log "нет файла схемы ${SCHEMA_FILE} (скопируйте clickhouse/init/001_events.sql на домашний сервер)" log "нет файла схемы ${SCHEMA_FILE} (канонический DDL — clickhouse/init/001_events.sql)"
exit 1 exit 1
} }
@ -55,4 +55,4 @@ log "Импортирую ${ARCHIVE} в analytics.events"
gzip -dc "$ARCHIVE" | ch --query "INSERT INTO analytics.events FORMAT Parquet" gzip -dc "$ARCHIVE" | ch --query "INSERT INTO analytics.events FORMAT Parquet"
log "Импорт завершён" log "Импорт завершён"
ch --query "SELECT count() FROM analytics.events WHERE toDate(event_time) = toDate('${DAY}')" ch --param_day="$DAY" --query "SELECT count() FROM analytics.events WHERE toDate(event_time) = toDate({day:String})"

View File

@ -7,4 +7,4 @@ from common import __version__
def test_version_is_set(): def test_version_is_set():
assert __version__ assert __version__
assert __version__ == "0.3.6" assert __version__ == "0.3.7"