Skip to content
yandex-development-1-teamPublic

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

439 Commits

Folders and files

Repository files navigation

Backend Service

Сервис для многофункционального телеграм бота для аккаунтов из Яндекс Staff, предоставляющего бизнес-функции для внутреннних заказчиков и их внешних партнеров. Поверх сценариев бота доступны HTTP API на Gin (префикс /api/v1), JWT-авторизация, сессии в Redis, файлы в S3-совместном хранилище (MinIO), SMTP для писем сброса пароля, приём вебхуков Яндекс Форм и фоновая очистка «осиротевших» файлов.

Поддерживаемый функционал:

  1. Авторизация через Staff аккаунт Яндекса с использованием ролевой модели;
  2. Преоставляет перечень коробочных решений по посещению мероприятий с возможностью выбора свободных дат и времени;
  3. Скачивание гайда по посещению мероприятий;
  4. Запрос спецпроекта;
  5. Просмотр примеров спец.проектов;
  6. Просмотр справочной информации о сервисе;
  7. Связь с поддержкой;
  8. HTTP API для админки и интеграций (/api/v1): регистрация и вход, refresh-токены, выход, запрос и сброс пароля по e-mail (SMTP из конфига);
  9. Коробочные решения в API: список, карточка, создание, изменение, удаление, загрузка изображения, смена статуса; проверка ролей и отдельных прав (создание/редактирование/удаление коробок);
  10. Спецпроекты в API: список, создание, просмотр, обновление, удаление с разграничением прав;
  11. Заявки на спецпроекты: список, создание оператором, просмотр, смена статуса, удаление;
  12. Бронирования: список, просмотр по id, смена статуса, удаление; отдельные права на просмотр/редактирование/удаление;
  13. Настройки сервиса: тексты сообщений бота; чтение и изменение матрицы прав по ролям (админ);
  14. Аналитика: выгрузка (эндпоинт export) при наличии права на просмотр аналитики;
  15. Страницы ресурсов (контент разделов бота — о сервисе, гайд, примеры, полезные ссылки, заявка на спецпроект): список, получение по slug, правка, загрузка файла к странице, удаление ссылок и страницы;
  16. Загрузка файлов через API (POST /files/upload) в объектное хранилище; публичная выдача контента страницы ресурса без JWT (GET /api/v1/public/resources/:slug);
  17. Пользователи Staff: список и карточка (админ); создание, обновление, смена статуса учётной записи; дашборд для роли менеджер/админ;
  18. Интеграция с Яндекс Формами: публичный POST /api/v1/public/applications/ принимает тело ответа формы; сверяются заголовки X-Webhook-Token (секрет из конфига) и X-Form-Answer-Id;
  19. Сессии бота и связанные сценарии в Redis; ограничение частоты обработки апдейтов и внешних вызовов (rate limiting в боте);
  20. MinIO (или другое S3-совместное API) для медиа и вложений; при старте создаётся bucket; фоновый воркер удаляет объекты в хранилище, на которые больше нет ссылок в БД (параметры file_gc / FILE_GC_*);
  21. Режим API_ONLY: один процесс поднимает API, миграции, метрики и health без запуска Telegram-бота (удобно для разработки фронта);
  22. CORS для браузерного фронта, метрики Prometheus и middleware на стороне Gin; маршруты собраны в internal/api/server/routes.go.

Содержание

  • Введение
  • Структура проекта
  • Требования
  • Конфигурация
  • Быстрый старт
  • Запуск (локально и Docker)
  • HTTP API (/api/v1)
  • Миграции базы данных
  • Makefile цели
  • Логи и метрики
  • Разработка
  • Тесты и линтинг
  • Точки здоровья (health/endpoints)
  • Траблшутинг

Введение

Сервис написан на Go, включает HTTP API, работу с БД и миграциями, логирование, метрики и процесс Telegram-бота. Фактически один исполняемый модуль собирается из cmd/bot: при старте выполняются миграции goose, подключаются PostgreSQL и Redis, инициализируется клиент к объектному хранилищу, поднимается Gin-сервер с CORS и JWT-middleware, отдельный HTTP-сервер для /metrics и /health на порту prometheus_port, опционально запускается бот и воркер очистки файлов. Конфигурация читается через Viper из config/config.yaml с переопределением из переменных окружения; для локальной разработки используйте .env.example → .env.

Запуск возможен локально, в Docker и через docker-compose, в том числе целями make run-local (полный стек, порты на 127.0.0.1) и make run-local-api (инфраструктура на localhost для go run на хосте).


Структура проекта


├── main.go                 # Точка входа HTTP-сервиса (API)
├── cmd/
│   └── bot/
│       └── main.go         # Точка входа отдельного процесса бота
├── internal/
│   ├── bot/                # Логика бота: обработчики, клиенты, воркеры
│   ├── handlers/           # HTTP-обработчики (роуты, контроллеры)
│   ├── models/             # Доменные модели и DTO
│   ├── database/           # Подключение к БД, репозитории
│   ├── config/             # Чтение и валидация конфигурации
│   ├── logger/             # Инициализация и обертки логирования
│   └── metrics/            # Метрики
├── migrations/             # SQL/скрипты миграций базы данных
├── config/
│   └── config.yaml         # Основной конфигурационный файл
├── Dockerfile              # Сборка Docker-образа приложения
├── docker-compose.yml      # Сценарий запуска сервиса и зависимостей (БД и т.д.)
├── Makefile                # Сценарии автоматизации (build, run, test, lint, migrate)
└── go.mod / go.sum         # Модули и зависимости Go

В актуальной ветке main.go в корне может отсутствовать; единая точка входа — cmd/bot/main.go. Дополнительно в дереве кода:

  • internal/api/ — Gin: server, handlers, middleware (аутентификация по JWT, CORS, метрики, проверка ролей);
  • internal/repository/postgres, internal/repository/redis — доступ к данным и сессиям;
  • internal/storage/minio — загрузка и удаление объектов в бакете;
  • internal/worker/ — фоновые задачи (очистка файлов);
  • internal/service/ и internal/dto/ — бизнес-логика и контракты API/бота;
  • scripts/ — обёртки ./scripts/run, ./scripts/stop над make;
  • docker-compose.infra.yml, docker-compose.local.infra.yml, docker-compose.local.app.yml — база, Redis, MinIO и публикация портов для локальной разработки;
  • .env.example — шаблон переменных для compose и хоста.

Требования

  • Go 1.26+ — на компе нужна актуальная версия. Проверка: go version. Установка: go.dev/dl. Для автоматической подстановки тулчейна: в go.env или окружении задать GOTOOLCHAIN=auto. Версия модуля в репозитории смотрите в go.mod.
  • Docker 24+ и Docker Compose (для контейнерного запуска)
  • Доступ к СУБД (например, PostgreSQL)
  • Redis (сессии и сопутствующая логика)
  • S3-совместное хранилище (в compose по умолчанию MinIO)

Конфигурация

Базовая конфигурация хранится в config/config.yaml. Значения могут переопределяться через переменные окружения.

Пример содержимого config/config.yaml:

server:
  port: 8080
  readTimeout: 5s
  writeTimeout: 5s

database:
  maxOpenConns: 20
  maxIdleConns: 5
  connMaxLifetime: 30m

logger:
  level: info
  format: json

metrics:
  enabled: true
  endpoint: /metrics

bot:
  enabled: true
  token: "${BOT_TOKEN}"     # можно переопределить через окружение

Переменные окружения (примеры):

  • APP_ENV=local|dev|prod
  • BOT_TOKEN=...
  • DB_DSN=... (доступ к БД, ссылка на запись в защищённом хранилище)
  • LOG_LEVEL=debug|info|warn|error

Загрузчик конфигурации читает config.yaml, затем применяет ENV-опции.

В коде загрузка реализована через Viper (internal/config/config.go). Имеют значение, в частности:

  • параметры PostgreSQL (db.* / POSTGRES_*, DB_HOST_PORT);
  • Redis (redis.* / REDIS_ADDR, REDIS_PASSWORD, REDIS_DB);
  • JWT и TTL токенов (auth_config / JWT_SECRET);
  • MinIO: endpoint, ключи, имя бакета, public_base_url (MINIO_*);
  • SMTP и базовый URL для ссылок в письмах (email.* / SMTP_*, EMAIL_*);
  • yandex_forms.webhook_token / YANDEX_FORMS_WEBHOOK_TOKEN (обязателен при старте приложения);
  • file_gc — включение воркера, интервал, «период милосердия» для сирот, размер батча;
  • api_only, cors, лимиты msg_rps / api_rps, session.ttl, port, prometheus_port, migrations_dir.

Удобный старт для Docker и хоста: скопировать .env.example в .env и заполнить секреты.


Быстрый старт

  • Убедитесь, что корректно заполнен config/config.yaml
  • Запустите сервис:
    • Локально: go run ./main.go
    • В Docker: docker compose up --build
  • Для полного локального стека из репозитория: cp .env.example .env, заполните токены и пароли, затем make run-local или ./scripts/run
  • Чтобы поднять только Postgres, Redis и MinIO на 127.0.0.1 и гонять API на машине разработчика: make run-local-api, далее экспорт переменных из .env (в т.ч. DB_HOST_PORT, REDIS_ADDR, переменные MinIO) и go run ./cmd/bot/*.go — см. комментарии в .env.example

Запуск

Локально (без Docker)

  • Запуск API:
    go run ./main.go
  • Запуск бота:
    go run ./cmd/bot/main.go

Сейчас типичный запуск API и бота одной командой:

go run ./cmd/bot/*.go

или make run. Только HTTP API и метрики без бота: задайте API_ONLY=true (и при необходимости пустой BOT_TOKEN не используется в этом режиме согласно логике конфига).

Docker

  • Собрать образ:
    docker build -t backend-service:latest .
  • Запустить контейнер:
    docker run --rm -p 8080:8080 \
      -e APP_ENV=prod \
      -e BOT_TOKEN=... \
      backend-service:latest

Docker Compose

  • Запуск сервиса и зависимостей:
    docker compose up --build
  • Остановка:
    docker compose down

Для этого репозитория удобно пользоваться make run-local (инфра из docker-compose.infra.yml + приложение, порты проброшены на 127.0.0.1 через overlay-файлы), make stop-local или ./scripts/stop, make run-local-api — только инфраструктура на localhost. Подробности в Makefile и scripts/README.md.

Скрипты run/stop и токен бота через .env

Чтобы поднимать весь бэкенд (postgres, redis, bot) одной командой и задавать токен бота через файл:

  1. Скопируйте пример env-файла и укажите токен:
    cp .env .env
    # отредактируйте .env: BOT_TOKEN=ваш_токен_от_BotFather
  2. Запуск:
    ./scripts/run
  3. Остановка:
    ./scripts/stop

Скрипт run проверяет наличие .env и непустого BOT_TOKEN перед запуском. Логи бота: docker compose logs -f bot.

Примечание: убедитесь, что в docker-compose.yml настроены сервисы (например, db) и корректные переменные окружения. В полном стеке также поднимаются Redis, MinIO и сервис приложения с зависимостями по healthcheck.


HTTP API (/api/v1)

  • Без JWT: группа /api/v1/auth — логин, регистрация, обновление и инвалидация сессии (refresh/logout), восстановление и смена пароля.
  • С JWT: защищённые группы с проверкой ролей Staff и набора прав (см. модели прав в internal/models):
    • /boxes — коробочные решения;
    • /special-projects — спецпроекты;
    • /applications — заявки;
    • /bookings — бронирования;
    • /settings — сообщения и права;
    • /analytics — в т.ч. выгрузка;
    • /resources — страницы ресурсов и файлы к ним;
    • /files/upload — загрузка файла в хранилище;
    • /users — список/карточка (админ) и отдельные админские маршруты создания/обновления/статуса;
    • /dashboard — сводка для менеджеров и администраторов.
  • Публично: GET /api/v1/public/resources/:slug, POST /api/v1/public/applications/ (вебхук форм; ответы сервиса не раскрывают ошибки валидации наружу).

Полный перечень методов и путей — в internal/api/server/routes.go.


Миграции базы данных

Для управления миграциями используется goose. Миграции автоматически применяются при запуске приложения.

  • Создание миграции:

    make migration-create NAME=название
    make migration-create NAME=create_users_table
  • Откат последней миграции:

    make migration-rollback DB_DSN="postgres://user:pass@localhost:5432/db?sslmode=disable"
  • Структура файла миграции:

-- +goose Up CREATE TABLE ...;

-- +goose Down DROP TABLE ...;

  • Команды Makefile:

    • make migration — справка
    • make migration-create NAME= — создать миграцию
    • make migration-rollback DB_DSN= — откатить последнюю
  • Логи при запуске:

    • Current database version: 20240321120000
    • Found 2 pending migration(s)
    • Applied 2 migration(s)
    • Database version: 20240321120000 → 20240322123456

Makefile цели

Помимо сборки и запуска:

  • build — бинарь в ./bin/app из cmd/bot;
  • run — go run того же модуля;
  • test — тесты с подробным выводом и покрытием;
  • fmt / fix — форматирование и группировка импортов (goimports + gofmt);
  • vet, lint, lint-fix — статический анализ;
  • migration, migration-create, migration-rollback — миграции goose;
  • run-local, run-local-api, stop-local — Docker compose для локальной разработки;
  • run-frontend, run-frontend-local-api — npm-скрипты внешнего фронта (FRONTEND_DIR=...);
  • generate-mocks — генерация моков;
  • help — краткая справка по целям.

Логи и метрики

  • Логи:

    • Конфигурируются через internal/logger и config.yaml.
    • Уровни логирования: debug, info, error.
  • Метрики:

    • Экспорт метрик Prometheus включается через metrics.enabled.
    • Эндпоинт метрик задаётся metrics.endpoint (например, /metrics).
    • В internal/metrics обычно находятся регистраторы, middleware и хэндлеры.

Отдельно от основного API на порту PROMETHEUS_PORT (например, 9090) поднят mux с GET /metrics (Prometheus) и GET /health (пинг БД и проверка доступности Telegram API с кэшем). Основной REST API слушает SERVER_PORT (маршруты под /api/v1/...).


Разработка

  • Структура кода следует стандарту Go Modules.
  • Бизнес‑логика и инфраструктурный код разделены по пакетам внутри internal/.
  • Новые HTTP‑маршруты добавляйте в internal/handlers.
  • Новые модели — в internal/models.
  • Работу с БД (репозитории/ORM) — в internal/database.
  • Конфиги и валидация — в internal/config.

Для веб-API админки используйте internal/api/handlers и регистрацию в internal/api/server/routes.go; реализации доступа к данным — internal/repository/postgres, сессии — internal/repository/redis.

Рекомендации:

  • Соблюдайте контракты интерфейсов для удобства тестирования.
  • Используйте контекст context.Context во всех внешних вызовах.
  • Оборачивайте ошибки и логируйте с полями (structured logging).

Тесты и линтинг

  • Запуск тестов:
    go test ./... -race -cover
  • Линтинг (пример с golangci-lint):
    golangci-lint run
  • Форматирование:
    gofmt -w .
    go mod tidy

Те же задачи можно вызывать через make test, make lint, make lint-fix, make fmt.


Точки здоровья (health / readiness / liveness)

Рекомендуется:

  • /healthz — liveness probe (проверка, что процесс жив).
  • /readyz — readiness probe (проверка готовности зависимостей, например БД).
  • /metrics — метрики (если включено).

Порты и пути настраиваются через config.yaml.

В текущей реализации процесса приложения на порту prometheus_port доступны /health (JSON со статусом БД и Telegram) и /metrics; см. cmd/bot/main.go и internal/api/health.go.


Траблшутинг

  • Проблема запуска:
    • Проверьте config/config.yaml и переменные окружения.
    • Убедитесь, что БД доступна и DSN корректен.
    • Проверьте YANDEX_FORMS_WEBHOOK_TOKEN: пустое значение не пройдёт валидацию конфига при старте.
  • Ошибки миграций:
    • Удостоверьтесь, что инструмент миграций установлен.
    • Сверьте права пользователя БД.
  • Нет метрик:
    • Проверьте metrics.enabled и путь metrics.endpoint.
    • Убедитесь, что порт PROMETHEUS_PORT не занят другим процессом; проверка: curl на http://127.0.0.1:${PROMETHEUS_PORT}/health.
  • Логи пустые или слишком многословные:
    • Настройте logger.level и logger.format.
  • Ошибки Redis или MinIO:
    • В Docker используйте хосты сервисов из compose (redis, minio); при go run на хосте — 127.0.0.1 и порты из docker-compose.local.infra.yml (5432, 6379, 9000, консоль MinIO 9001).
  • 401/403 в API:
    • Проверьте заголовок авторизации, срок JWT и роль пользователя в Staff относительно требуемых прав маршрута.

Профилирование (pprof)

pprof доступен на отдельном порту только локально.

Локально:

# Снять CPU профиль под нагрузкой (30 секунд)
go tool pprof 'http://localhost:6060/debug/pprof/profile?seconds=30'

# Heap (память)
go tool pprof -http=:8091 'http://localhost:6060/debug/pprof/heap'

# Горутины
go tool pprof -http=:8091 'http://localhost:6060/debug/pprof/goroutine'

На проде — только через SSH туннель:

ssh -L 6060:localhost:6060 user@server
# затем локально:
go tool pprof 'http://localhost:6060/debug/pprof/profile?seconds=30'

Порт 6060 проброшен только на 127.0.0.1 — снаружи недоступен.


About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages