REST API сервис для агрегации пользовательских онлайн-подписок.
- Go
- chi
- PostgreSQL
- pgx
- slog
- cleanenv
- golang-migrate
- swaggo
- Docker Compose
- Скопируйте пример переменных окружения:
cp .env.example .env-
Убедитесь, что PostgreSQL доступен на
localhost:5432. -
Запустите сервис:
make runДля локального запуска DATABASE_URL должен указывать на localhost.
make docker-upДля Docker Compose DATABASE_URL использует host postgres (имя сервиса в сети compose) и задан прямо в docker-compose.yml.
Остановка:
make docker-downОстановка с удалением volume:
make docker-down-vAPP_ENV=local
HTTP_ADDR=localhost:8080
DATABASE_URL=postgres://postgres:postgres@localhost:5432/subscriptions?sslmode=disable
SHUTDOWN_TIMEOUT=10smake run
make docker-up
make docker-down
make migrate-up
make migrate-down
make swagger
make fmt
make tidyМиграции лежат в директории migrations/ и применяются через golang-migrate.
Первая миграция создает таблицу subscriptions с индексами и базовыми ограничениями:
price >= 0end_date >= start_date(еслиend_dateзадан)
Применить миграции:
make migrate-upОткатить последнюю миграцию:
make migrate-downУстановка CLI:
go install github.com/swaggo/swag/cmd/swag@latestГенерация документации:
swag init -g ./cmd/app/main.go -o ./docsSwagger UI:
http://localhost:8080/swagger/index.html
Используется GitHub Actions.
Проверяется:
- build (
go build ./...) - tests (
go test ./...) - formatting (
test -z "$(gofmt -l .)")
GET /healthPOST /subscriptionsGET /subscriptionsGET /subscriptions/totalGET /subscriptions/{id}PUT /subscriptions/{id}DELETE /subscriptions/{id}GET /swagger/index.html
Пример ответа для health:
{
"status": "ok"
}end_dateопционален при создании подписки.- Если
end_dateне указан, подписка считается активной (без даты окончания). - При
update:- чтобы изменить дату окончания, передайте
"end_date": "MM-YYYY"; - если
end_dateне передан, текущее значение не изменяется; - очистка
end_dateчерезnullсейчас не поддерживается, так как это не требуется по ТЗ.
- чтобы изменить дату окончания, передайте
Поднять Docker Compose:
make docker-upПрименить миграции:
make migrate-upHealth:
curl http://localhost:8080/healthCreate subscription:
curl -X POST http://localhost:8080/subscriptions \
-H "Content-Type: application/json" \
-d '{
"service_name": "Yandex Plus",
"price": 400,
"user_id": "60601fee-2bf1-4721-ae6f-7636e79a0cba",
"start_date": "07-2025"
}'List subscriptions:
curl http://localhost:8080/subscriptionsList with filters:
curl "http://localhost:8080/subscriptions?user_id=60601fee-2bf1-4721-ae6f-7636e79a0cba&service_name=Yandex%20Plus&limit=20&offset=0"Get by id:
curl http://localhost:8080/subscriptions/<subscription-id>Update:
curl -X PUT http://localhost:8080/subscriptions/<subscription-id> \
-H "Content-Type: application/json" \
-d '{
"price": 500,
"end_date": "12-2025"
}'Delete:
curl -X DELETE http://localhost:8080/subscriptions/<subscription-id>Total cost:
curl "http://localhost:8080/subscriptions/total?from=07-2025&to=12-2025&user_id=60601fee-2bf1-4721-ae6f-7636e79a0cba&service_name=Yandex%20Plus"Пояснение для GET /subscriptions/total:
fromиtoобязательны и передаются в форматеMM-YYYY;- период считается включительно по месяцам;
end_date = NULLозначает активную подписку без даты окончания.