Skip to content

netology-code/golps

Repository files navigation

FinOps Microservice

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

Требования

  • Go 1.20+
  • PostgreSQL 12+
  • Docker и Docker Compose (для запуска в контейнерах)

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

.
├── cmd/server/           # Точка входа приложения
├── internal/
│   ├── api/             # HTTP handlers
│   ├── config/          # Конфигурация приложения
│   ├── db/              # Инициализация БД
│   ├── middleware/      # HTTP middleware (логирование, recovery)
│   ├── models/          # Модели данных
│   ├── pkg/errors/      # Кастомные ошибки
│   ├── processor/       # Асинхронная обработка транзакций
│   ├── repositories/    # Уровень доступа к данным
│   └── services/        # Бизнес-логика
├── migrations/          # SQL миграции БД
├── tests/              # Unit и integration тесты
├── Dockerfile          # Docker конфигурация
└── docker-compose.yml  # Orchestration для локальной разработки

Переменные окружения

Приложение поддерживает следующие переменные окружения:

  • DATABASE_URL или DB_DSN - строка подключения к PostgreSQL (default: postgres://user:pass@db:5432/finops?sslmode=disable)
  • PORT - порт для запуска API (default: 8080)

Локальный запуск

Подготовка

  1. Установите зависимости:
go mod download
  1. Подготовьте PostgreSQL БД:
createdb finops
psql -d finops -f migrations/init.sql
  1. Установите переменные окружения:
export DATABASE_URL="postgres://user:pass@localhost:5432/finops?sslmode=disable"
export PORT=8080
  1. Запустите сервер:
go run cmd/server/main.go

Запуск через Docker Compose

Это рекомендуемый способ для локальной разработки и тестирования:

# Или используйте docker-compose напрямую:
docker-compose up --build
docker-compose down

При использовании Docker Compose:

  • API доступен на http://localhost:8080
  • PostgreSQL доступна на localhost:5432 (user: user, password: pass, database: finops)
  • Миграции БД запускаются автоматически

API Эндпоинты

Получить баланс пользователя

GET /users/{user_id}/balance

Response:
{
  "id": 1,
  "balance": "1000.00"
}

Создать транзакцию

POST /transactions

Request:
{
  "user_id": 1,
  "amount": "100.50",
  "type": "deposit"  # или "withdraw"
}

Response (201):
{
  "id": 1,
  "user_id": 1,
  "amount": "100.50",
  "type": "deposit",
  "timestamp": "2024-01-04T12:34:56Z",
  "processed": false
}

Получить информацию о транзакции

GET /transactions/{transaction_id}

Response:
{
  "id": 1,
  "user_id": 1,
  "amount": "100.50",
  "type": "deposit",
  "timestamp": "2024-01-04T12:34:56Z",
  "processed": true
}

Обновить транзакцию

PUT /transactions/{transaction_id}

Request:
{
  "amount": "50.00",
  "type": "withdraw"
}

Response (204): No Content

Удалить транзакцию

DELETE /transactions/{transaction_id}

Response (204): No Content

Проверка здоровья сервиса

GET /health

Response (200):
ok

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

# Создать транзакцию пополнения
curl -X POST http://localhost:8080/transactions \
  -H "Content-Type: application/json" \
  -d '{"user_id":1,"amount":"100.00","type":"deposit"}'

# Получить баланс пользователя
curl -X GET http://localhost:8080/users/1/balance

# Получить информацию о транзакции
curl -X GET http://localhost:8080/transactions/1

# Обновить транзакцию
curl -X PUT http://localhost:8080/transactions/1 \
  -H "Content-Type: application/json" \
  -d '{"amount":"50.00","type":"withdraw"}'

# Удалить транзакцию
curl -X DELETE http://localhost:8080/transactions/1

# Проверить здоровье сервиса
curl -X GET http://localhost:8080/health

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

Запуск всех тестов

# Unit тесты
go test ./tests -v

# Проверка race conditions
go test -race ./tests -v

# Анализ кода
go vet ./...

Результаты тестирования

Все тесты проходят успешно:

  • Unit тесты: JSON сериализация, валидация, конкурентность (15 тестов)
  • Проверка race conditions: go test -race ./tests -v - PASS (0 гонок)
  • Код анализ: go vet ./... - без проблем

Архитектура и оптимизации

Многоуровневая архитектура

Проект реализован с использованием чистой архитектуры:

  • Handlers - HTTP слой обработки запросов
  • Services - слой бизнес-логики и валидации
  • Repositories - слой доступа к данным БД
  • Middleware - логирование и обработка паник

Обработка конкурентности

  • Асинхронная обработка: Транзакции помещаются в очередь и обрабатываются worker goroutines (5 работников по умолчанию)
  • User-level мьютексы: Каждый пользователь имеет свой мьютекс для защиты от race conditions при изменении баланса
  • Атомарные БД транзакции: Все операции с БД используют транзакции для обеспечения консистентности

Оптимизация производительности

  • Индекс на user_id: Ускоряет запросы по пользователям в таблице транзакций
  • Буферизованные каналы: Канал с буфером из 100 элементов для асинхронной очереди
  • Connection pooling: pgxpool для управления соединениями с БД

Безопасность

  • Валидация input: Проверка сумм, типов транзакций, ID пользователей
  • Обработка ошибок: Структурированные ошибки и правильные HTTP статусы
  • Recovery middleware: Перехват паник для предотвращения падения сервера

Профилирование

Приложение поддерживает profiling через pprof:

# CPU профиль (по умолчанию на :6060)
go tool pprof http://localhost:6060/debug/pprof/profile

# Memory профиль
go tool pprof http://localhost:6060/debug/pprof/heap

# Горутины
curl http://localhost:6060/debug/pprof/goroutine

# Мьютексы
curl http://localhost:6060/debug/pprof/mutex

Разработка

Добавление новых endpoint'ов

  1. Определите модель в internal/models/
  2. Реализуйте business logic в internal/services/
  3. Добавьте методы в internal/repositories/
  4. Создайте handler в internal/api/handlers.go
  5. Зарегистрируйте route в cmd/server/main.go
  6. Добавьте тесты в tests/

Работа с БД

Все операции с БД должны использовать контекст и транзакции:

dbTx, err := pool.Begin(ctx)
if err != nil {
    return err
}
defer dbTx.Rollback(ctx)

// Выполнить операции
err = dbTx.Exec(ctx, "UPDATE users SET balance = $1 WHERE id = $2", balance, userID)
if err != nil {
    return err
}

return dbTx.Commit(ctx)

Troubleshooting

Ошибка подключения к БД

Убедитесь, что:

  • PostgreSQL запущена и доступна по адресу из DATABASE_URL
  • База данных finops существует
  • Миграции выполнены: psql -d finops -f migrations/init.sql

Healthcheck не проходит

При использовании Docker Compose проверьте:

  • Что сервис app запущен: docker-compose ps
  • Логи сервиса: docker-compose logs app
  • Логи БД: docker-compose logs db

Тесты не проходят

Очистите состояние и переберите:

go clean -testcache
go test -race ./tests -v

Ссылки

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published