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)
- Установите зависимости:
go mod download- Подготовьте PostgreSQL БД:
createdb finops
psql -d finops -f migrations/init.sql- Установите переменные окружения:
export DATABASE_URL="postgres://user:pass@localhost:5432/finops?sslmode=disable"
export PORT=8080- Запустите сервер:
go run cmd/server/main.goЭто рекомендуемый способ для локальной разработки и тестирования:
# Или используйте docker-compose напрямую:
docker-compose up --build
docker-compose downПри использовании Docker Compose:
- API доступен на
http://localhost:8080 - PostgreSQL доступна на
localhost:5432(user:user, password:pass, database:finops) - Миграции БД запускаются автоматически
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 ContentDELETE /transactions/{transaction_id}
Response (204): No ContentGET /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- Определите модель в
internal/models/ - Реализуйте business logic в
internal/services/ - Добавьте методы в
internal/repositories/ - Создайте handler в
internal/api/handlers.go - Зарегистрируйте route в
cmd/server/main.go - Добавьте тесты в
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)Убедитесь, что:
- PostgreSQL запущена и доступна по адресу из
DATABASE_URL - База данных
finopsсуществует - Миграции выполнены:
psql -d finops -f migrations/init.sql
При использовании Docker Compose проверьте:
- Что сервис
appзапущен:docker-compose ps - Логи сервиса:
docker-compose logs app - Логи БД:
docker-compose logs db
Очистите состояние и переберите:
go clean -testcache
go test -race ./tests -v