Бэкап событий переведён на pull с домашнего сервера
- скрипт бэкапа запускается на домашнем сервере и сам забирает вчерашнюю партицию с VPS по ssh - входящий ssh на домашний сервер больше не нужен, rsync не требуется - выгрузка идёт через docker compose на VPS, пароль ClickHouse читается из окружения контейнера - архив пишется сначала во временный файл, импорт идемпотентен, удаление партиций только после сверки - env/backup.env.example переписан под новые параметры, cron теперь на домашнем сервере - версия 0.3.7
This commit is contained in:
parent
a0fa223eaa
commit
a28bd622c7
31
DEPLOY.md
31
DEPLOY.md
|
|
@ -79,29 +79,34 @@ docker compose -p test --env-file env/test.env -f docker-compose.prod.yml exec -
|
|||
Изменения схемы: `clickhouse/init/*.sql` применяются лишь на пустом data-каталоге,
|
||||
поэтому на существующем контуре DDL нужно применить вручную (`make ch E=...`).
|
||||
|
||||
## Бэкап событий на домашний сервер
|
||||
## Бэкап событий (забирает домашний сервер)
|
||||
|
||||
Сырые события живут на VPS ограниченное время: раз в сутки вчерашняя партиция
|
||||
выгружается в `Parquet.gz`, передаётся на домашний сервер, импортируется в тамошний
|
||||
ClickHouse и сверяется по количеству строк — **только после сверки** партиции старше
|
||||
`BACKUP_GRACE_DAYS` (по умолчанию 7) удаляются на VPS. На VPS остаются агрегаты
|
||||
(`events_daily`, `money_daily`).
|
||||
Сырые события живут на VPS ограниченное время: раз в сутки домашний сервер **сам забирает**
|
||||
вчерашнюю партицию (`pull`), складывает её в `Parquet.gz`, импортирует в свой ClickHouse и
|
||||
сверяет количество строк — **только после сверки** на VPS удаляются партиции старше
|
||||
`BACKUP_GRACE_DAYS` (по умолчанию 7). На VPS остаются агрегаты (`events_daily`, `money_daily`).
|
||||
|
||||
Входящий SSH на домашний сервер не нужен: он инициирует соединение сам.
|
||||
|
||||
Разовая настройка:
|
||||
|
||||
```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 рядом со скриптом
|
||||
# на домашнем сервере
|
||||
git clone ssh://git@<gitea-host>:2222/mpakobecex/DispelEvilBot.git
|
||||
cd DispelEvilBot
|
||||
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
|
||||
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 (партиции не удаляются) и пишет понятный лог.
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -23,7 +23,7 @@ help:
|
|||
> @echo " make check E=test проверка контура (скрипт)"
|
||||
> @echo " make psql E=test psql в БД контура"
|
||||
> @echo " make ch E=test clickhouse-client контура"
|
||||
> @echo " make backup E=test бэкап вчерашних событий на домашний сервер"
|
||||
> @echo " make backup E=test бэкап событий с VPS (запускать на домашнем сервере)"
|
||||
|
||||
up:
|
||||
> $(COMPOSE) up -d
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -93,18 +93,18 @@ pytest
|
|||
|
||||
## Бэкап событий
|
||||
|
||||
Сырые события ClickHouse ежедневно выгружаются архивом на домашний сервер (по cron),
|
||||
на VPS остаются только агрегаты и последние дни сырых данных:
|
||||
Сырые события ClickHouse ежедневно забираются с VPS домашним сервером (`pull`), на VPS
|
||||
остаются только агрегаты и последние дни сырых данных:
|
||||
|
||||
```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`).
|
||||
- Docker-образы тегируются версией (Блок 2), события ClickHouse получают `bot_version` (Блок 3).
|
||||
- Выпуск: изменить `common/version.py` → коммит → аннотированный тег `vX.Y` → `git push --tags`.
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
__version__ = "0.3.6"
|
||||
__version__ = "0.3.7"
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ DDL — `clickhouse/init/001_events.sql` (применяется при перв
|
|||
| Агрегаты | VPS | постоянно |
|
||||
| Полная история | домашний сервер, свой ClickHouse | архивы `events_YYYY-MM-DD.parquet.gz` (ежедневно) |
|
||||
|
||||
Каждую ночь (по Москве) `scripts/clickhouse_backup.sh` выгружает вчерашнюю партицию,
|
||||
передаёт её на домашний сервер, импортирует и **сверяет количество строк**; только после
|
||||
успешной сверки на VPS удаляются партиции старше грейса. Ошибка бэкапа данные не удаляет.
|
||||
Подробности — `DEPLOY.md`.
|
||||
Каждую ночь (по Москве) домашний сервер **сам забирает** вчерашнюю партицию с VPS (`pull`
|
||||
по ssh), импортирует её в свой ClickHouse и **сверяет количество строк**; только после
|
||||
успешной сверки он просит VPS удалить партиции старше грейса. Ошибка бэкапа данные не
|
||||
удаляет. Подробности — `DEPLOY.md` и `deploy/ssh-access.md`.
|
||||
|
||||
## Уведомления в чат логов
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,32 @@
|
|||
# Параметры ежедневного бэкапа событий ClickHouse с VPS на домашний сервер.
|
||||
# Параметры бэкапа событий ClickHouse (pull: домашний сервер забирает данные с VPS).
|
||||
# Скопируйте в env/backup.env (env/*.env в git не попадает) и заполните.
|
||||
#
|
||||
# Используется скриптами:
|
||||
# scripts/clickhouse_backup.sh (запускается на VPS по cron, см. DEPLOY.md)
|
||||
# scripts/clickhouse_import.sh (лежит на домашнем сервере)
|
||||
# Запускается НА ДОМАШНЕМ СЕРВЕРЕ по cron:
|
||||
# scripts/clickhouse_backup.sh test|prod
|
||||
#
|
||||
# SSH-доступ к VPS настраивается отдельно (инструкция — deploy/ssh-access.md).
|
||||
|
||||
# Куда передавать архивы: пользователь@хост и каталог на домашнем сервере.
|
||||
BACKUP_REMOTE=user@home.example
|
||||
# --- VPS ---
|
||||
# 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
|
||||
|
||||
# Приватный ключ для ssh/rsync (без пароля; на домашнем сервере — соответствующий public key).
|
||||
BACKUP_SSH_KEY=/root/.ssh/dispelevilbot_backup
|
||||
|
||||
# Сколько дней сырых событий оставлять на VPS (остальное удаляется после успешной сверки).
|
||||
# --- Хранение ---
|
||||
# Сколько дней сырых событий остаётся на VPS (остальное удаляется после успешной сверки)
|
||||
BACKUP_GRACE_DAYS=7
|
||||
|
||||
# Таймзона расчёта «вчерашнего» дня.
|
||||
# Таймзона расчёта «вчерашнего» дня
|
||||
BACKUP_TZ=Europe/Moscow
|
||||
|
||||
# Как запускать импорт на домашнем сервере (путь к scripts/clickhouse_import.sh).
|
||||
REMOTE_IMPORT_SCRIPT=./clickhouse_import.sh
|
||||
|
||||
# ClickHouse домашнего сервера. Пароль лучше без кавычек и пробелов — он передаётся по ssh.
|
||||
REMOTE_CLICKHOUSE_HOST=localhost
|
||||
REMOTE_CLICKHOUSE_PORT=9000
|
||||
REMOTE_CLICKHOUSE_USER=default
|
||||
REMOTE_CLICKHOUSE_PASSWORD=
|
||||
# --- ClickHouse домашнего сервера (сюда импортируются архивы) ---
|
||||
CLICKHOUSE_HOST=localhost
|
||||
CLICKHOUSE_PORT=9000
|
||||
CLICKHOUSE_USER=default
|
||||
CLICKHOUSE_PASSWORD=
|
||||
|
|
|
|||
|
|
@ -1,32 +1,28 @@
|
|||
#!/usr/bin/env bash
|
||||
# Ежедневный бэкап сырых событий ClickHouse с VPS на домашний сервер.
|
||||
# Бэкап сырых событий ClickHouse: домашний сервер забирает данные с VPS (pull).
|
||||
#
|
||||
# Запускается НА ДОМАШНЕМ СЕРВЕРЕ по cron. Входящий SSH на домашний сервер не нужен:
|
||||
# скрипт сам ходит на VPS по ключу и запускает там docker compose.
|
||||
#
|
||||
# Что делает:
|
||||
# 1) выгружает партицию «вчерашнего» дня из analytics.events в Parquet.gz;
|
||||
# 2) передаёт файл на домашний сервер (rsync) и импортирует его в тамошний ClickHouse;
|
||||
# 3) сверяет количество строк на VPS и на домашнем сервере;
|
||||
# 4) только после успешной сверки удаляет на VPS партиции старше BACKUP_GRACE_DAYS.
|
||||
# 1) по ssh выгружает на VPS вчерашнюю партицию analytics.events в Parquet;
|
||||
# 2) складывает events_YYYY-MM-DD.parquet.gz в BACKUP_DIR;
|
||||
# 3) импортирует архив в локальный ClickHouse (идемпотентно, scripts/clickhouse_import.sh);
|
||||
# 4) сверяет количество строк на VPS и локально;
|
||||
# 5) только после успешной сверки просит VPS удалить партиции старше BACKUP_GRACE_DAYS.
|
||||
#
|
||||
# Ошибка на любом шаге оставляет данные на VPS и возвращает ненулевой код.
|
||||
# Ошибка на любом шаге оставляет данные на VPS (партиции не удаляются) и возвращает ненулевой код.
|
||||
#
|
||||
# Запуск (на VPS, из каталога проекта):
|
||||
# Использование:
|
||||
# ./scripts/clickhouse_backup.sh test # или prod
|
||||
# make backup E=test
|
||||
#
|
||||
# Настройки (env/<контур>.env + 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)
|
||||
# Настройки — env/backup.env (см. env/backup.env.example).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
E="${1:-test}"
|
||||
ENV_FILE="env/${E}.env"
|
||||
BACKUP_ENV="env/backup.env"
|
||||
COMPOSE="docker compose -p ${E} --env-file ${ENV_FILE} -f docker-compose.prod.yml"
|
||||
BACKUP_ENV="${BACKUP_ENV:-env/backup.env}"
|
||||
|
||||
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }
|
||||
fail() {
|
||||
|
|
@ -34,76 +30,72 @@ fail() {
|
|||
exit 1
|
||||
}
|
||||
|
||||
[ -f "$ENV_FILE" ] || fail "нет файла окружения ${ENV_FILE}"
|
||||
# shellcheck disable=SC1090
|
||||
set -a && . "./${ENV_FILE}" && set +a
|
||||
if [ -f "$BACKUP_ENV" ]; then
|
||||
[ -f "$BACKUP_ENV" ] || fail "нет файла настроек ${BACKUP_ENV} (скопируйте env/backup.env.example)"
|
||||
# shellcheck disable=SC1090
|
||||
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_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_TZ="${BACKUP_TZ:-Europe/Moscow}"
|
||||
REMOTE_IMPORT_SCRIPT="${REMOTE_IMPORT_SCRIPT:-./clickhouse_import.sh}"
|
||||
REMOTE_CLICKHOUSE_HOST="${REMOTE_CLICKHOUSE_HOST:-localhost}"
|
||||
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")
|
||||
IMPORT_SCRIPT="${IMPORT_SCRIPT:-$(dirname "$0")/clickhouse_import.sh}"
|
||||
SCHEMA_FILE="${SCHEMA_FILE:-$(dirname "$0")/../clickhouse/init/001_events.sql}"
|
||||
|
||||
ch() {
|
||||
$COMPOSE exec -T clickhouse clickhouse-client \
|
||||
--user "$CLICKHOUSE_USER" --password "$CLICKHOUSE_PASSWORD" "$@"
|
||||
SSH=(ssh -i "$VPS_SSH_KEY" -p "$VPS_PORT" -o BatchMode=yes -o ServerAliveInterval=30 "$VPS_SSH")
|
||||
|
||||
# Запустить команду на 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')"
|
||||
PARTITION="${DAY//-/}"
|
||||
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
|
||||
fail "контейнер clickhouse контура ${E} не запущен"
|
||||
fi
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
ARCHIVE="${BACKUP_DIR}/events_${DAY}.parquet.gz"
|
||||
|
||||
ROWS_LOCAL="$(ch --query "SELECT count() FROM analytics.events WHERE toDate(event_time) = toDate('${DAY}')" | tr -d '[:space:]')"
|
||||
log "На VPS строк за ${DAY}: ${ROWS_LOCAL}"
|
||||
if [ "$ROWS_LOCAL" = "0" ]; then
|
||||
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_VPS}"
|
||||
if [ "$ROWS_VPS" = "0" ]; then
|
||||
log "ВНИМАНИЕ: за ${DAY} событий нет — партиция пустая, продолжаю (сверка 0 = 0)"
|
||||
fi
|
||||
|
||||
ARCHIVE="${TMP_DIR}/events_${DAY}.parquet.gz"
|
||||
log "Выгружаю партицию в ${ARCHIVE}"
|
||||
ch --query "SELECT * FROM analytics.events WHERE toDate(event_time) = toDate('${DAY}') FORMAT Parquet" | gzip -9 >"$ARCHIVE"
|
||||
[ -s "$ARCHIVE" ] || fail "не удалось выгрузить архив ${DAY}"
|
||||
vps_ch --param_day="$DAY" --query "SELECT * FROM analytics.events WHERE toDate(event_time) = toDate({day:String}) FORMAT Parquet" |
|
||||
gzip -9 >"${ARCHIVE}.part"
|
||||
[ -s "${ARCHIVE}.part" ] || fail "не удалось выгрузить архив ${DAY}"
|
||||
mv "${ARCHIVE}.part" "$ARCHIVE"
|
||||
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 домашнего сервера"
|
||||
ROWS_REMOTE="$("${SSH[@]}" \
|
||||
"BACKUP_DIR='${BACKUP_DIR}' CLICKHOUSE_HOST='${REMOTE_CLICKHOUSE_HOST}' CLICKHOUSE_PORT='${REMOTE_CLICKHOUSE_PORT}' \
|
||||
CLICKHOUSE_USER='${REMOTE_CLICKHOUSE_USER}' CLICKHOUSE_PASSWORD='${REMOTE_CLICKHOUSE_PASSWORD}' \
|
||||
'${REMOTE_IMPORT_SCRIPT}' '${DAY}'" | tail -n1 | tr -d '[:space:]')"
|
||||
log "На домашнем сервере строк за ${DAY}: ${ROWS_REMOTE}"
|
||||
ROWS_HOME="$(BACKUP_DIR="$BACKUP_DIR" SCHEMA_FILE="$SCHEMA_FILE" "$IMPORT_SCRIPT" "$DAY" | tail -n1 | tr -d '[:space:]')"
|
||||
log "На домашнем сервере строк за ${DAY}: ${ROWS_HOME}"
|
||||
|
||||
[ "$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}"
|
||||
OLDER="$(ch --query "SELECT DISTINCT partition FROM system.parts WHERE database='analytics' AND table='events' AND active AND partition < '${GRACE_CUTOFF}'")"
|
||||
if [ -z "$OLDER" ]; then
|
||||
DROPPED="$(vps_ch --query "SELECT DISTINCT partition FROM system.parts WHERE database='analytics' AND table='events' AND active AND partition < '${GRACE_CUTOFF}'")"
|
||||
if [ -z "$DROPPED" ]; then
|
||||
log "Удалять нечего"
|
||||
else
|
||||
for partition in $OLDER; do
|
||||
for partition in $DROPPED; do
|
||||
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
|
||||
fi
|
||||
|
||||
log "Готово: события за ${DAY} в архиве, на VPS остались агрегаты и последние ${BACKUP_GRACE_DAYS} дней сырых событий"
|
||||
log "Готово: события за ${DAY} в архиве ${ARCHIVE}, на VPS остались агрегаты и последние ${BACKUP_GRACE_DAYS} дней сырых событий"
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
#!/usr/bin/env bash
|
||||
# Импорт дневного архива событий в ClickHouse домашнего сервера.
|
||||
#
|
||||
# Запускается на домашнем сервере (обычно по ssh из scripts/clickhouse_backup.sh).
|
||||
# Рядом должны лежать этот скрипт и канонический DDL кликхаус-схемы
|
||||
# (clickhouse/init/001_events.sql из репозитория).
|
||||
# Запускается на домашнем сервере; обычно вызывается из scripts/clickhouse_backup.sh,
|
||||
# но можно и вручную — например, чтобы повторно залить архив после сбоя.
|
||||
#
|
||||
# Использование: ./clickhouse_import.sh 2026-01-01
|
||||
# Использование:
|
||||
# ./scripts/clickhouse_import.sh 2026-01-01
|
||||
# В stdout печатается количество строк загруженного дня (для сверки), диагностика — в stderr.
|
||||
#
|
||||
# Настройки (окружение):
|
||||
# BACKUP_DIR каталог, куда складываются архивы events_YYYY-MM-DD.parquet.gz
|
||||
# SCHEMA_FILE путь к DDL схемы (по умолчанию ./001_events.sql рядом со скриптом)
|
||||
# BACKUP_DIR каталог с архивами events_YYYY-MM-DD.parquet.gz
|
||||
# SCHEMA_FILE DDL схемы (по умолчанию clickhouse/init/001_events.sql рядом с репозиторием)
|
||||
# CLICKHOUSE_CLIENT бинарь клиента (по умолчанию clickhouse-client)
|
||||
# CLICKHOUSE_HOST/PORT/USER/PASSWORD доступ к ClickHouse домашнего сервера
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ PARTITION="${DAY//-/}"
|
|||
ARCHIVE_DIR="${BACKUP_DIR:-.}"
|
||||
ARCHIVE="${ARCHIVE_DIR}/events_${DAY}.parquet.gz"
|
||||
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}"
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ ch() {
|
|||
exit 1
|
||||
}
|
||||
[ -f "$SCHEMA_FILE" ] || {
|
||||
log "нет файла схемы ${SCHEMA_FILE} (скопируйте clickhouse/init/001_events.sql на домашний сервер)"
|
||||
log "нет файла схемы ${SCHEMA_FILE} (канонический DDL — clickhouse/init/001_events.sql)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
|
@ -55,4 +55,4 @@ log "Импортирую ${ARCHIVE} в analytics.events"
|
|||
gzip -dc "$ARCHIVE" | ch --query "INSERT INTO analytics.events FORMAT Parquet"
|
||||
|
||||
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})"
|
||||
|
|
|
|||
|
|
@ -7,4 +7,4 @@ from common import __version__
|
|||
|
||||
def test_version_is_set():
|
||||
assert __version__
|
||||
assert __version__ == "0.3.6"
|
||||
assert __version__ == "0.3.7"
|
||||
|
|
|
|||
Loading…
Reference in New Issue