SaveOps — микросервисная платформа для управления накопительными счетами, целями накопления, округлением покупок, начислением процентов, аудитом и mock-уведомлениями.
Проект показывает Java backend-навыки: Spring Boot 3, Java 21, gRPC, RabbitMQ, Redis, PostgreSQL, Flyway, Docker Compose, Prometheus, Grafana, Testcontainers и базовые SRE-практики.
- Открытие накопительного счета, баланс, пополнение и списание.
- Ledger операций без возврата entity наружу.
- Цели накопления и расчет прогресса через баланс счета.
- Симуляция покупки и округление до 10/50/100 рублей.
- Асинхронные доменные события через RabbitMQ.
- Mock-уведомления с retry и dead-letter queue.
- Append-only audit log по
aggregateId. - Redis rate limiting, balance cache, idempotency keys, distributed lock.
- Метрики Actuator/Micrometer в Prometheus и dashboard в Grafana.
Java 21, Spring Boot 3.x, Spring Web, Spring Data JPA, PostgreSQL, Flyway, RabbitMQ, Redis, gRPC, Maven, Docker Compose, Spring Boot Actuator, Micrometer, Prometheus, Grafana, JUnit 5, Testcontainers.
flowchart LR
Client[Клиент] --> Gateway[api-gateway]
Gateway -->|gRPC| Account[account-service]
Gateway -->|gRPC| Goal[goal-service]
Goal -->|gRPC GetBalance| Account
Gateway -->|HTTP| Simulator[transaction-simulator-service]
Gateway -->|HTTP| Audit[audit-service]
Simulator -->|purchase.rounded-up| Rabbit[(RabbitMQ saveops.events)]
Account -->|account.*, money.transferred| Rabbit
Interest[interest-service] -->|interest.accrued| Rabbit
Rabbit --> Account
Rabbit --> Notification[notification-service]
Rabbit --> Audit
Rabbit --> Interest
Account --> PgAccount[(PostgreSQL account)]
Goal --> PgGoal[(PostgreSQL goal)]
Interest --> PgInterest[(PostgreSQL interest)]
Audit --> PgAudit[(PostgreSQL audit)]
Gateway --> Redis[(Redis)]
Account --> Redis
Interest --> Redis
Prometheus --> Gateway
Prometheus --> Account
Grafana --> Prometheus
Подробности: docs/architecture.md.
api-gateway— REST API, Redis rate limiting, correlation-id, gRPC-клиенты.account-service— счета, balance cache, ledger, idempotency, RabbitMQ events, gRPC server.goal-service— цели накопления, PostgreSQL/Flyway, gRPC server и account gRPC client.transaction-simulator-service— симуляция покупок и событиеPurchaseRoundedUp.interest-service— scheduled начисление процентов, Redis lock, история начислений.notification-service— consumer событий, mock-уведомления, retry queue и DLQ.audit-service— append-only audit log и поиск поaggregateId.contracts—.protoконтракты и генерация Java gRPC-кода.common— общий envelope событий, correlation-id, error DTO.
saveops/
├── services/
│ ├── api-gateway/
│ ├── account-service/
│ ├── goal-service/
│ ├── transaction-simulator-service/
│ ├── interest-service/
│ ├── notification-service/
│ └── audit-service/
├── contracts/
├── common/
├── docker/
├── docs/
├── docker-compose.yml
├── Makefile
└── README.md
make build
make upСсылки:
- Gateway:
http://localhost:8080 - RabbitMQ Management:
http://localhost:15672(saveops/saveops) - Prometheus:
http://localhost:9090 - Grafana:
http://localhost:3000(admin/admin)
Остановка:
make downcurl -X POST http://localhost:8080/api/accounts \
-H 'Content-Type: application/json' \
-H 'X-Correlation-Id: demo-1' \
-d '{"ownerId":"user-1","currency":"RUB"}'
curl -X POST http://localhost:8080/api/goals \
-H 'Content-Type: application/json' \
-d '{"ownerId":"user-1","accountId":"<accountId>","name":"Подушка","targetAmount":100000,"currency":"RUB"}'
curl -X POST http://localhost:8080/api/purchases/simulate \
-H 'Content-Type: application/json' \
-d '{"userId":"user-1","accountId":"<accountId>","amount":187.30,"roundTo":100}'
curl http://localhost:8080/api/accounts/<accountId>/balance
curl http://localhost:8080/api/audit/<accountId>POST /api/accountsGET /api/accounts/{accountId}/balancePOST /api/accounts/{accountId}/depositPOST /api/accounts/{accountId}/withdrawPOST /api/goalsGET /api/goals/{goalId}GET /api/goals/{goalId}/progressPOST /api/purchases/simulateGET /api/audit/{aggregateId}
account-service предоставляет:
GetBalanceCreateAccountDepositMoneyWithdrawMoneyListAccounts
goal-service предоставляет создание цели, получение цели и прогресс. Gateway и goal-service используют deadline 2 секунды; gateway делает короткий retry для UNAVAILABLE и DEADLINE_EXCEEDED.
Exchange: saveops.events.
Routing keys:
account.openedaccount.closedmoney.transferredpurchase.rounded-upinterest.accruednotification.failed
Envelope события: eventId, eventType, aggregateId, occurredAt, correlationId, payload.
api-gateway: rate limiting по IP.account-service: idempotency key для денежных операций и cache balance read model.interest-service: distributed lock для scheduled начисления процентов.
Все сервисы публикуют /actuator/health, /actuator/health/readiness, /actuator/prometheus.
Бизнес-метрики:
saveops_accounts_created_totalsaveops_money_transfers_totalsaveops_interest_accrued_totalsaveops_notifications_sent_totalsaveops_notification_failures_total
Prometheus config: docker/prometheus/prometheus.yml. Dashboard: docker/grafana/dashboards/saveops-overview.json.
SLI/SLO и alerting описаны в docs/sre.md.
Runbooks:
make build
make test
make up
make down
make logs service=account-service- Добавить OpenAPI спецификацию gateway.
- Добавить outbox pattern для надежной публикации событий.
- Добавить отдельные users/profile сервисы.
- Добавить policy-based rate limiting по пользователю.
- Добавить алерты Prometheus Alertmanager.