Это шаблон микросервиса для обработки финансовых операций. Вам предоставлена готовая архитектура и каркас кода — ваша задача реализовать недостающие методы.
cmd/server/main.go ← Точка входа (заполнить)
internal/
api/handlers.go ← HTTP обработчики (заполнить)
config/config.go ← Конфигурация (готово)
db/db.go ← Подключение БД (заполнить)
middleware/middleware.go ← Логирование (заполнить)
models/models.go ← Структуры данных (готово)
processor/processor.go ← Асинхронная обработка (заполнить)
repositories/ ← Доступ к БД (заполнить)
services/ ← Бизнес-логика (заполнить)
migrations/init.sql ← Схема БД (готово)
tests/ ← Тесты (заполнить)
go mod download
docker-compose up -d dbinternal/db/db.go — функция NewPool(dsn)
- Создать пул подключений pgxpool
- Проверить подключение через Ping()
- Вернуть пул или ошибку
internal/repositories/user_repo.go — методы интерфейса
GetBalance(ctx, userID)— SELECT баланс пользователяUpdateBalance(ctx, userID, amount, tx)— UPDATE баланс (используйте переданную транзакцию tx!)
internal/repositories/transaction_repo.go — методы интерфейса
CreateTransaction(ctx, tx, dbTx)— INSERT новую транзакцию, вернуть IDGetTransaction(ctx, id)— SELECT транзакцию по IDUpdateTransaction(ctx, id, newTx)— UPDATE поля транзакцииDeleteTransaction(ctx, id)— DELETE транзакцию
internal/services/user_service.go
GetBalance()— делегировать в репозиторий
internal/services/transaction_service.go (КРИТИЧНО!)
-
CreateTransaction()— самый важный метод:- Валидировать amount > 0 и type ∈ {deposit, withdraw}
- Начать БД транзакцию (
pool.Begin()) - Убедиться, что пользователь существует
- Для withdraw проверить баланс пользователя
- Вызвать
txRepo.CreateTransaction()иuserRepo.UpdateBalance()с переданной транзакцией - Коммитить транзакцию
-
GetTransaction()— получение транзакции -
UpdateTransaction()— обновление (проверить processed == false) -
DeleteTransaction()— удаление с реверсом баланса если processed == true
internal/api/handlers.go — реализовать все обработчики:
CreateTransactionHandler()— POST /transactions (201 Created)GetTransactionHandler()— GET /transactions/{id} (200 или 404)UpdateTransactionHandler()— PUT /transactions/{id} (204 No Content)DeleteTransactionHandler()— DELETE /transactions/{id} (204 No Content)GetUserBalanceHandler()— GET /users/{user_id}/balance (200 OK)HealthCheckHandler()— GET /health (200 OK)
internal/middleware/middleware.go
LoggingMiddleware()— логировать метод, путь, время выполненияRecoveryMiddleware()— перехватить panic, логировать, вернуть 500
cmd/server/main.go
- Загрузить конфигурацию
- Создать пул БД
- Инициализировать репозитории, сервисы
- Создать HTTP маршруты
- Запустить сервер с обработкой сигналов завершения
go run cmd/server/main.go
curl http://localhost:8080/health # Должен вернуть 200
curl -X POST http://localhost:8080/transactions \
-H "Content-Type: application/json" \
-d '{"user_id":1,"amount":"100","type":"deposit"}'
go test ./tests -vinternal/processor/processor.go
-
NewProcessor(pool, numWorkers)— создать процессор с worker горутинами- Инициализировать buffered канал jobs (размер 100)
- Запустить numWorkers горутин через worker()
-
Submit(tx)— отправить транзакцию в очередь обработки -
worker()(приватный) — цикл обработки из канала jobs -
process(tx)(приватный) — обработка одной транзакции:- Получить или создать мьютекс для пользователя (защитить RWMutex)
- Заблокировать мьютекс пользователя
- Начать БД транзакцию
- Получить баланс, проверить его для withdraw
- Обновить баланс в БД
- Установить processed = true
- Коммитить транзакцию
-
Close()— закрыть канал для graceful shutdown
В cmd/server/main.go:
- Создать Processor:
proc := processor.NewProcessor(pool, 5) - Передавать
procв обработчики - Вызывать
proc.Submit()после создания транзакции
tests/api_test.go, tests/concurrency_test.go, tests/integration_test.go
- Unit тесты JSON сериализации и валидации
- Тесты конкурентности и race conditions
- Интеграционные тесты эндпоинтов
go test ./tests -v
go test -race ./tests -v # КРИТИЧНО: не должно быть data races!На основе Dockerfile.template:
- Build stage: собрать Go приложение
- Runtime stage: минимальный alpine образ
В docker-compose.yml раскомментировать и заполнить сервис app:
app:
build: .
ports:
- "8080:8080"
environment:
DATABASE_URL: postgres://user:pass@db:5432/finops?sslmode=disable
PORT: 8080
depends_on:
db:
condition: service_healthyДобавить pprof в main.go для анализа производительности.
docker-compose up --build
curl http://localhost:8080/health
docker-compose downОР1: REST API и БД
- ✅ Приложение запускается без ошибок
- ✅ Все CRUD операции работают
- ✅ Health check возвращает 200
- ✅ Валидация входных данных работает
ОР2: Конкурентная обработка
- ✅
go test ./tests -vпроходит все тесты - ✅
go test -race ./tests -v— ноль race conditions - ✅ Транзакции обрабатываются асинхронно (processed флаг меняется)
ОР3: Контейнеризация
- ✅
docker-compose upзапускает оба сервиса - ✅ Приложение работает в контейнере
- ✅ API доступен на localhost:8080
# Запустить БД
docker-compose up -d db
# Запустить приложение
go run cmd/server/main.go
# Запустить тесты
go test ./tests -v
# Запустить с проверкой race conditions
go test -race ./tests -v
# Запустить приложение и БД
docker-compose up
# Остановить все
docker-compose down
# Просмотреть логи
docker-compose logs -f db
docker-compose logs -f app- ACID транзакции — используйте
pool.Begin()для гарантии консистентности при параллельных операциях - Parameterized queries — всегда используйте
$1, $2вместо конкатенации строк - Синхронизация — используйте мьютексы для защиты баланса каждого пользователя
- Тестирование —
go test -raceобязателен для проверки гонок данных - Context — передавайте context.Context везде для отмены и таймаутов
- Комментарии
// TODOв коде указывают, что нужно реализовать - Интерфейсы в
internal/repositories/interfaces.goпоказывают контракт методов