REST API сервис для управления онлайн-подписками пользователей. Сервис предоставляет полный CRUDL функционал для работы с подписками и расчет их стоимости.
- Функциональность
- Быстрый старт
- API Endpoints
- Структура данных
- Конфигурация
- Развертывание
- Разработка
- Примеры использования
- Мониторинг и логирование
- Устранение неполадок
- Swagger документация
- Технологии
- ✅ CRUDL операции над записями о подписках
- ✅ Расчет суммарной стоимости подписок за период с фильтрацией
- ✅ Фильтрация по пользователю и названию сервиса
- ✅ Логирование всех операций
- ✅ Конфигурация через YAML и переменные окружения
- ✅ Docker контейнеризация с Docker Compose
- ✅ Автоматические миграции базы данных
- ✅ Health check эндпоинт
- ✅ Swagger документация API
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| service_name | string | Да | Название сервиса подписки |
| price | integer | Да | Стоимость в рублях (без копеек) |
| user_id | UUID | Да | Идентификатор пользователя |
| start_date | string | Да | Дата начала (формат: MM-YYYY) |
| end_date | string | Нет | Дата окончания (формат: MM-YYYY) |
- Docker 20.10+
- Docker Compose 2.0+
# Клонируйте репозиторий (если нужно)
# git clone <repository-url>
# cd subscription-service
# Запустите все сервисы
docker-compose up -d
# Проверьте статус
docker-compose ps
# Проверка здоровья сервиса
curl http://localhost:8080/health
# Результат:
# {"status":"healthy","timestamp":"2024-01-01T10:00:00Z"}
GET /health
Проверка доступности сервиса и подключения к БД.
POST /api/v1/subscriptions
Content-Type: application/json
Пример тела запроса:
{
"service_name": "Yandex Plus",
"price": 400,
"user_id": "60601fee-2bf1-4721-ae6f-7636e79a0cba",
"start_date": "07-2025",
"end_date": "12-2025"
}
GET /api/v1/subscriptions/{id}
PUT /api/v1/subscriptions/{id}
Content-Type: application/json
Пример тела запроса:
{
"service_name": "Новое название",
"price": 500,
"end_date": "12-2025"
}
DELETE /api/v1/subscriptions/{id}
GET /api/v1/subscriptions
Query параметры:
limit(default: 10) - количество записейoffset(default: 0) - смещениеuser_id- фильтр по пользователюservice_name- фильтр по названию сервиса
GET /api/v1/subscriptions/total-cost
Query параметры:
start_date(required) - начало периода (MM-YYYY)end_date(required) - конец периода (MM-YYYY)user_id(optional) - фильтр по пользователюservice_name(optional) - фильтр по сервису
Пример:
GET /api/v1/subscriptions/total-cost?start_date=01-2024&end_date=12-2024&user_id=60601fee-2bf1-4721-ae6f-7636e79a0cba
Ответ:
{
"total_cost": 12000
}
Таблица: subscriptions
CREATE TABLE subscriptions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
service_name VARCHAR(255) NOT NULL,
price INTEGER NOT NULL CHECK (price > 0),
user_id UUID NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
Индексы:
idx_subscriptions_user_id- поиск по пользователюidx_subscriptions_service_name- поиск по сервисуidx_subscriptions_dates- оптимизация временных запросов
port: "8080"
log_level: "info"
database:
host: "postgres"
port: "5432"
user: "postgres"
password: "postgres"
name: "subscriptions"
ssl_mode: "disable"
PORT=8080
LOG_LEVEL=debug
DB_HOST=postgres
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=subscriptions
DB_SSL_MODE=disable
version: '3.8'
services:
postgres:
image: postgres:15-alpine
container_name: subscription-postgres
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: subscriptions
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./internal/migrations:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
app:
build: .
container_name: subscription-app
ports:
- "8080:8080"
environment:
- DB_HOST=postgres
depends_on:
postgres:
condition: service_healthy
volumes:
postgres_data:
# Запуск в фоновом режиме
docker-compose up -d
# Остановка сервисов
docker-compose down
# Остановка с удалением данных
docker-compose down -v
# Просмотр логов
docker-compose logs -f app
docker-compose logs -f postgres
# Перезапуск
docker-compose restart app
# Статус сервисов
docker-compose ps
# Подключиться к PostgreSQL
docker exec -it subscription-postgres psql -U postgres -d subscriptions
# Просмотр таблиц
\dt
# Просмотр данных
SELECT * FROM subscriptions LIMIT 10;
# Выход
\q
# Установка зависимостей
go mod download
# Запуск PostgreSQL
docker-compose up postgres -d
# Запуск приложения
go run main.go
# Выполнение тестов
go test ./...
subscription-service/
├── api/ # API спецификации
├── internal/
│ ├── config/ # Конфигурация
│ │ └── config.go
│ ├── domain/ # Модели данных
│ │ └── subscription.go
│ ├── handlers/ # HTTP обработчики
│ │ └── subscription.go
│ ├── migrations/ # Миграции БД
│ │ └── 001_create_subscriptions.sql
│ ├── repository/ # Слой данных
│ │ └── subscription_repository.go
│ └── service/ # Бизнес-логика
│ └── subscription_service.go
├── pkg/
│ ├── database/ # Подключение к БД
│ │ └── postgres.go
│ └── logger/ # Логирование
│ └── logger.go
├── .env.example # Пример переменных окружения
├── .gitignore
├── config.yaml # Конфигурация приложения
├── docker-compose.yml # Docker Compose
├── Dockerfile # Docker образ
├── go.mod # Go модули
├── go.sum
├── main.go # Точка входа
└── README.md # Этот файл
# 1. Создание подписки
curl -X POST http://localhost:8080/api/v1/subscriptions \
-H "Content-Type: application/json" \
-d '{
"service_name": "Netflix",
"price": 1000,
"user_id": "11111111-1111-1111-1111-111111111111",
"start_date": "01-2024"
}'
# 2. Получение списка
curl "http://localhost:8080/api/v1/subscriptions?limit=5"
# 3. Расчет стоимости
curl "http://localhost:8080/api/v1/subscriptions/total-cost?start_date=01-2024&end_date=12-2024"
# 4. Обновление подписки (замените {id})
curl -X PUT http://localhost:8080/api/v1/subscriptions/{id} \
-H "Content-Type: application/json" \
-d '{"price": 1200}'
# 5. Удаление подписки (замените {id})
curl -X DELETE http://localhost:8080/api/v1/subscriptions/{id}
# Добавление подписок
curl -X POST http://localhost:8080/api/v1/subscriptions \
-H "Content-Type: application/json" \
-d '{
"service_name": "Yandex Plus",
"price": 400,
"user_id": "60601fee-2bf1-4721-ae6f-7636e79a0cba",
"start_date": "01-2024",
"end_date": "12-2024"
}'
curl -X POST http://localhost:8080/api/v1/subscriptions \
-H "Content-Type: application/json" \
-d '{
"service_name": "Netflix",
"price": 1000,
"user_id": "60601fee-2bf1-4721-ae6f-7636e79a0cba",
"start_date": "01-2024"
}'
# Расчет годовых расходов
curl "http://localhost:8080/api/v1/subscriptions/total-cost?start_date=01-2024&end_date=12-2024&user_id=60601fee-2bf1-4721-ae6f-7636e79a0cba"
# Ответ: {"total_cost": 16800}
# Получение всех активных подписок на Netflix
curl "http://localhost:8080/api/v1/subscriptions?service_name=Netflix&limit=100"
# Суммарные расходы на Netflix за год
curl "http://localhost:8080/api/v1/subscriptions/total-cost?start_date=01-2024&end_date=12-2024&service_name=Netflix"
debug- детальная отладочная информацияinfo- информационные сообщения (по умолчанию)warn- предупрежденияerror- ошибки
# Логи приложения
docker-compose logs app --tail=50
# Логи базы данных
docker-compose logs postgres --tail=50
# Логи в реальном времени
docker-compose logs -f app
Решение: Используйте правильные эндпоинты:
/health- проверка здоровья/api/v1/subscriptions- управление подписками
Решение:
# Проверьте статус PostgreSQL
docker-compose ps
# Проверьте логи PostgreSQL
docker-compose logs postgres
# Убедитесь, что healthcheck проходит
# Дождитесь статуса (healthy)
Решение:
-
Проверьте, есть ли данные в БД:
docker exec subscription-postgres psql -U postgres -d subscriptions -c "SELECT COUNT(*) FROM subscriptions;" -
Проверьте конфигурацию подключения к БД
-
Проверьте логи приложения на ошибки
Решение: Удалите томы и перезапустите:
docker-compose down -v
docker-compose up -d
Swagger UI доступен по адресу (если настроен):
http://localhost:8080/swagger/index.html
Для генерации Swagger документации используйте:
# Установите swag
go install github.com/swaggo/swag/cmd/swag@latest
# Сгенерируйте документацию
swag init
- Go 1.21+ - основной язык программирования
- Gin - высокопроизводительный HTTP фреймворк
- PostgreSQL 15 - реляционная база данных
- pgx - драйвер PostgreSQL для Go
- Docker & Docker Compose - контейнеризация
- Zap - структурированное логирование
- Viper - управление конфигурацией
- UUID - генерация уникальных идентификаторов