RepoPulse — backend-сервис на Go для отслеживания статистики публичных GitHub-репозиториев.
Сервис хранит репозитории и историю их статистики в PostgreSQL, выполняет синхронизацию через фоновые задания и обрабатывает их ограниченным пулом worker'ов.
Go · PostgreSQL · pgx · chi · Docker · GitHub REST API
- REST API для управления отслеживаемыми репозиториями.
- Durable sync jobs в PostgreSQL.
- Параллельная обработка через bounded worker pool.
- Получение статистики через GitHub REST API.
- Retry для временных ошибок и rate limit.
- История snapshots.
- Graceful shutdown и context cancellation.
- Unit, HTTP и PostgreSQL integration tests.
- Docker Compose и GitHub Actions CI.
flowchart LR
Client[Client] --> API[HTTP API]
API --> Service[Service]
Service --> DB[(PostgreSQL)]
DB --> Jobs[Sync jobs]
Jobs --> Workers[Worker pool]
Workers --> GitHub[GitHub REST API]
GitHub --> Workers
Workers --> Snapshots[Snapshots]
Snapshots --> DB
HTTP API отвечает за создание и чтение отслеживаемых репозиториев, а также за постановку заданий на синхронизацию. Sync jobs сохраняются в PostgreSQL и не зависят от памяти процесса.
Worker'ы конкурентно получают доступные задания через FOR UPDATE SKIP LOCKED. Запрос к GitHub выполняется вне DB transaction, а успешный результат сохраняется как snapshot вместе с завершением задания.
Обычный сценарий:
queued → running → succeeded
При временной ошибке:
running → retry_wait → running
После исчерпания попыток:
running → failed
Retry применяется для сетевых ошибок, timeout, ответов GitHub 5xx и rate limit. Постоянные ошибки, например отсутствие репозитория в GitHub, повторно не выполняются.
GET /healthz
GET /readyz
POST /repositories
GET /repositories
GET /repositories/{id}
POST /repositories/{id}/sync-jobs
GET /sync-jobs/{id}
GET /repositories/{id}/dashboard
GET /repositories/{id}/snapshots
Создать отслеживаемый репозиторий:
curl -X POST http://localhost:8080/repositories \
-H "Content-Type: application/json" \
-d '{"owner":"golang","name":"go"}'Запустить синхронизацию:
curl -X POST http://localhost:8080/repositories/1/sync-jobsПолное описание контрактов API находится в docs/openapi.yaml.
Требования:
- Docker
- Docker Compose
git clone https://github.com/maxhnuknex/repopulse.git
cd repopulse
cp .env.example .env
docker compose up --buildПосле запуска API доступен на http://localhost:8080.
Проверка состояния сервиса:
curl http://localhost:8080/healthz
curl http://localhost:8080/readyzDocker Compose поднимает PostgreSQL, migrations, RepoPulse API и локальный fake-github service. Fake GitHub используется для воспроизводимых локальных сценариев без зависимости от внешнего API.
Чтобы направить RepoPulse на локальный fake GitHub, задайте:
GITHUB_BASE_URL=http://fake-github:18080Для работы с реальным GitHub API:
GITHUB_BASE_URL=https://api.github.com
GITHUB_TOKEN=Полный пример конфигурации находится в .env.example.
go fmt ./...
go vet ./...
go test ./...
go test -race ./...
go test -tags=integration ./...
go build ./cmd/repopulse| Уровень | Что проверяется |
|---|---|
| HTTP | REST contract, validation, errors, health/readiness |
| GitHub client | 200, 404, rate limit, 5xx, timeout |
| Service | retry policy |
| Worker | success, retry, failure, cancellation, concurrency |
| PostgreSQL | migrations, constraints, jobs, snapshots, transactions |
| Race detector | конкурентный Go-код |
В каталоге load/ находятся локальные k6-сценарии:
smoke.js
job_burst.js
slow_github.js
error_burst.js
Они проверяют базовую нагрузку, серии sync jobs, работу с медленным upstream и поведение при ошибках внешнего API.
cmd/
├── repopulse/
└── fakegithub/
internal/
├── domain/
├── github/
├── httpapi/
├── repository/
├── service/
└── worker/
migrations/
docs/
load/
Основной HTTP flow:
handler → service → repository / GitHub client
Фоновая обработка:
worker → PostgreSQL / GitHub client
docs/openapi.yaml— REST API.docs/adr/ADR-001-migrations.md— решение по миграциям.docs/adr/ADR-002-job-claiming.md— очередь и получение sync jobs.