Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🚀 Subscription Service

REST API сервис для управления онлайн-подписками пользователей. Сервис предоставляет полный CRUDL функционал для работы с подписками и расчет их стоимости.

📋 Содержание

🎯 Функциональность

Основные возможности:

  • 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)

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

1. Предварительные требования

  • Docker 20.10+
  • Docker Compose 2.0+

2. Клонирование и запуск

# Клонируйте репозиторий (если нужно)
# git clone <repository-url>
# cd subscription-service

# Запустите все сервисы
docker-compose up -d

# Проверьте статус
docker-compose ps

3. Проверка работы

# Проверка здоровья сервиса
curl http://localhost:8080/health

# Результат:
# {"status":"healthy","timestamp":"2024-01-01T10:00:00Z"}

📡 API Endpoints

Health Check

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"
}

Получение подписки по ID

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
}

🗄️ Структура данных

База данных PostgreSQL

Таблица: 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 - оптимизация временных запросов

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

Файлы конфигурации

config.yaml - основная конфигурация

port: "8080"
log_level: "info"

database:
  host: "postgres"
  port: "5432"
  user: "postgres"
  password: "postgres"
  name: "subscriptions"
  ssl_mode: "disable"

.env - переменные окружения (опционально)

PORT=8080
LOG_LEVEL=debug
DB_HOST=postgres
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=subscriptions
DB_SSL_MODE=disable

Docker Compose конфигурация

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 команды

# Запуск в фоновом режиме
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

🔧 Разработка

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

# Установка зависимостей
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               # Этот файл

Тестирование API

# 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}

🧪 Примеры использования

Сценарий 1: Учет подписок пользователя

# Добавление подписок
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}

Сценарий 2: Мониторинг подписок компании

# Получение всех активных подписок на 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

🚨 Устранение неполадок

Проблема: "404 page not found" на корневом URL

Решение: Используйте правильные эндпоинты:

  • /health - проверка здоровья
  • /api/v1/subscriptions - управление подписками

Проблема: "Connection refused" к базе данных

Решение:

# Проверьте статус PostgreSQL
docker-compose ps

# Проверьте логи PostgreSQL
docker-compose logs postgres

# Убедитесь, что healthcheck проходит
# Дождитесь статуса (healthy)

Проблема: Пустой ответ от API

Решение:

  1. Проверьте, есть ли данные в БД:

    docker exec subscription-postgres psql -U postgres -d subscriptions -c "SELECT COUNT(*) FROM subscriptions;"
    
  2. Проверьте конфигурацию подключения к БД

  3. Проверьте логи приложения на ошибки

Проблема: Ошибка миграции

Решение: Удалите томы и перезапустите:

docker-compose down -v
docker-compose up -d

📊 Swagger документация

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 - генерация уникальных идентификаторов

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages