All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 2m23s
170 lines
5.0 KiB
Markdown
170 lines
5.0 KiB
Markdown
# Go Backend Blueprint (Iteration Draft)
|
|
|
|
## Chosen Stack
|
|
|
|
- **Framework:** Gin
|
|
- **Migrations:** Goose (SQL-only)
|
|
- **DB Access:** SQLC (no ORM), package per bounded context
|
|
- **PostgreSQL Driver/Pool:** pgx/v5 + pgxpool
|
|
- **Logging:** Uber Zap (structured logs)
|
|
- **Health Probes:** liveness/readiness endpoints
|
|
- **API Docs:** OpenAPI (for frontend TypeScript type generation)
|
|
- **Deployment:** Docker Compose on self-hosted hardware
|
|
|
|
---
|
|
|
|
## Architecture Direction
|
|
|
|
### Layering
|
|
|
|
- `cmd/api` - application entrypoint and dependency wiring
|
|
- `internal/http` - Gin router, handlers, middleware
|
|
- `internal/service` - business logic + transaction boundaries
|
|
- `internal/db/<context>` - SQLC-generated code by bounded context
|
|
- `internal/store` - shared DB/Tx helpers
|
|
- `internal/auth` - JWT validation + role guards
|
|
- `internal/config` - env configuration loading
|
|
- `migrations/` - Goose SQL migration files
|
|
- `api/openapi/` - OpenAPI spec + generated artifacts
|
|
|
|
### Transaction Strategy
|
|
|
|
- Handlers stay thin.
|
|
- Service layer owns DB transactions.
|
|
- SQLC queries are called with either pool or tx using `DBTX` interfaces.
|
|
- No transaction logic in handlers.
|
|
|
|
---
|
|
|
|
## API and Runtime
|
|
|
|
### API Shape
|
|
|
|
- REST JSON API
|
|
- Possible future WebSocket support for interactive features
|
|
- Suggested versioning: `/api/v1`
|
|
|
|
### Health Endpoints
|
|
|
|
- `GET /health/live` - process is alive
|
|
- `GET /health/ready` - DB ping succeeds (and optionally migration version check)
|
|
|
|
### Logging
|
|
|
|
- Zap JSON logs
|
|
- Uber Zap logger will be initialized in `cmd/api/main.go` and injected into services/middleware (no global loggers).
|
|
- Logs will be written directly to a file from the application, with log rotation implemented via `lumberjack`.
|
|
- Correlation/request ID in middleware
|
|
- Structured error logging from middleware and service boundaries
|
|
|
|
---
|
|
|
|
## Database and Migrations
|
|
|
|
### Goose
|
|
|
|
- SQL-only migrations
|
|
- Keep up/down migration scripts
|
|
- Run on startup in non-prod optional, required in CI/CD/deploy step
|
|
- Migrations are securely bundled into the binary using Go's `embed.FS` from a dedicated `migrations` package to isolate them from `internal` db logic.
|
|
|
|
### SQLC
|
|
|
|
- Generate one package per bounded context (similar to Spring repository modules)
|
|
- Keep SQL in context directories (`query.sql`, `models.sql` style)
|
|
- Service layer composes multiple repositories when needed
|
|
|
|
### Work in Progress Snapshot
|
|
|
|
- `sqlc.yaml` is now configured for PostgreSQL with schema from `migrations/*.sql`
|
|
- First bounded context added: `internal/db/users`
|
|
- Current users SQLC artifacts generated:
|
|
- `db.go`, `models.go`, `queries.sql.go`, `querier.go`
|
|
- Current SQLC generation options in use:
|
|
- `sql_package: pgx/v5`
|
|
- `emit_interface: true` (generated `Querier` interface)
|
|
- `emit_json_tags: false` (can be revisited if API structs are returned directly)
|
|
- Initial queries implemented for users: `GetUser`, `CreateUser`, `DeleteUser`
|
|
- **Goose startup migrations** have been wired into `cmd/api/main.go`, utilizing the `embed.FS` strategy and logging via Zap adapter.
|
|
- DB pool is successfully wired in `cmd/api`.
|
|
- Environment-aware Zap logger is configured (development vs production).
|
|
- **Next Planned:** Implement application-level file logging with rotation (using `lumberjack`), and build initial Gin API routes for health checks.
|
|
|
|
---
|
|
|
|
## Testing Approach (Beginner-Friendly)
|
|
|
|
### Phase 1 (Recommended Start)
|
|
|
|
- Unit tests for pure service logic (no DB)
|
|
- Integration tests for SQLC repositories with real Postgres via Docker
|
|
|
|
### DB Interface Testing (via SQLC `Querier`)
|
|
|
|
- Treat generated SQLC interfaces (e.g. `usersdb.Querier`) as service dependencies
|
|
- For service unit tests, provide a fake/mock implementation of `Querier`
|
|
- Focus unit tests on business rules, branching, and error mapping (not SQL behavior)
|
|
- Keep SQL correctness in integration tests against real Postgres
|
|
- This split gives fast unit tests plus high-confidence DB integration coverage
|
|
|
|
### Phase 2
|
|
|
|
- HTTP handler tests with `httptest`
|
|
- Auth middleware tests
|
|
|
|
### Phase 3
|
|
|
|
- Minimal end-to-end happy path tests
|
|
|
|
---
|
|
|
|
## OpenAPI + Frontend Type Generation
|
|
|
|
- Keep spec in repo at `api/openapi/openapi.yaml`
|
|
- Generate frontend TypeScript types from OpenAPI (e.g. `openapi-typescript`)
|
|
- Optionally serve Swagger UI from backend
|
|
|
|
---
|
|
|
|
## Deployment
|
|
|
|
- Docker Compose for app + postgres
|
|
- Healthcheck in compose should target readiness endpoint
|
|
- Env-based configuration (`.env`, `.env.example`)
|
|
|
|
---
|
|
|
|
## Pending Decisions
|
|
|
|
1. JWT signing:
|
|
- HS256 shared secret (simple)
|
|
- RS256 keypair (better long-term)
|
|
|
|
2. Token model:
|
|
- Access token only
|
|
- Access + refresh token
|
|
|
|
3. Initial roles:
|
|
- USER / ADMIN
|
|
- USER / MODERATOR / ADMIN
|
|
|
|
4. OpenAPI workflow:
|
|
- Contract-first (spec first)
|
|
- Code-first annotations
|
|
|
|
5. CORS policy:
|
|
- Allowed frontend origins in dev/prod
|
|
|
|
6. Schema strategy:
|
|
- Single schema (`public`) confirmation
|
|
|
|
7. Initial bounded contexts:
|
|
- e.g. `auth`, `users`, `rooms` (or your domain names)
|
|
|
|
---
|
|
|
|
## Iteration Notes
|
|
|
|
- This file is intentionally a working draft.
|
|
- We will refine decisions and turn this into a concrete implementation checklist.
|