Entertainment content catalog REST API built with Go. Manages movies, series, and episodes with PostgreSQL storage, Redis caching, and Prometheus observability.
Request flow: Client → Middleware → Handler → Service → Cache / Repository → PostgreSQL
| Layer | Responsibility |
|---|---|
| Middleware | Recovery, Request ID, Logging (slog), Prometheus metrics |
| Handler | HTTP routing (Go 1.22+ ServeMux), JSON encode/decode, error mapping |
| Service | Business logic, validation, cache-aside orchestration |
| Cache | Redis (primary) or in-memory (fallback), TTL-based expiry |
| Repository | PostgreSQL via pgx/v5/stdlib, SQL migrations at startup |
Key patterns:
- Repository pattern with interface-driven DI
- Cache-aside: check Redis → on miss query PG → populate Redis
- Middleware chain: recovery → request ID → logging → metrics
- Go 1.22+ ServeMux for zero-dependency HTTP routing
# Start PostgreSQL + Redis + API server
docker compose up -d
# Or run locally (requires PG + Redis running)
make build && ./bin/cine-server# Create a genre
curl -s -X POST http://localhost:8080/v1/genres \
-H 'Content-Type: application/json' \
-d '{"name":"Action"}' | jq
# Create a movie
curl -s -X POST http://localhost:8080/v1/titles \
-H 'Content-Type: application/json' \
-d '{
"title": "The Matrix",
"kind": "movie",
"description": "A computer hacker discovers the true nature of reality.",
"release_year": 1999,
"rating": 8.7,
"duration_min": 136,
"genre_ids": ["<genre-id>"]
}' | jq
# List movies sorted by rating
curl -s 'http://localhost:8080/v1/titles?kind=movie&sort=rating' | jq
# Search titles
curl -s 'http://localhost:8080/v1/titles?search=matrix' | jq
# Create a series
curl -s -X POST http://localhost:8080/v1/titles \
-H 'Content-Type: application/json' \
-d '{
"title": "Breaking Bad",
"kind": "series",
"release_year": 2008,
"rating": 9.5
}' | jq
# Add an episode
curl -s -X POST http://localhost:8080/v1/titles/<title-id>/episodes \
-H 'Content-Type: application/json' \
-d '{
"season": 1,
"number": 1,
"name": "Pilot",
"duration_min": 58,
"air_date": "2008-01-20T00:00:00Z"
}' | jq
# List episodes (filter by season)
curl -s 'http://localhost:8080/v1/titles/<title-id>/episodes?season=1' | jq
# Health checks
curl -s http://localhost:8080/healthz | jq
curl -s http://localhost:8080/readyz | jq
# Prometheus metrics
curl -s http://localhost:8080/metrics| Method | Path | Description |
|---|---|---|
GET |
/v1/titles |
List titles (filters: kind, genre, year_min, year_max, search, sort, page, per_page) |
POST |
/v1/titles |
Create a title |
GET |
/v1/titles/{id} |
Get a title by ID |
PUT |
/v1/titles/{id} |
Update a title |
DELETE |
/v1/titles/{id} |
Delete a title |
GET |
/v1/titles/{id}/episodes |
List episodes (filter: season) |
POST |
/v1/titles/{id}/episodes |
Create an episode |
GET |
/v1/titles/{id}/episodes/{episode_id} |
Get an episode |
PUT |
/v1/titles/{id}/episodes/{episode_id} |
Update an episode |
DELETE |
/v1/titles/{id}/episodes/{episode_id} |
Delete an episode |
GET |
/v1/genres |
List genres |
POST |
/v1/genres |
Create a genre |
GET |
/healthz |
Liveness probe |
GET |
/readyz |
Readiness probe |
GET |
/metrics |
Prometheus metrics |
| Variable | Default | Description |
|---|---|---|
CINE_HTTP_ADDR |
:8080 |
HTTP listen address |
CINE_DATABASE_URL |
postgres://cine:cine@localhost:5432/cine_catalog?sslmode=disable |
PostgreSQL connection string |
CINE_REDIS_ADDR |
localhost:6379 |
Redis address |
CINE_REDIS_PASS |
(empty) | Redis password |
CINE_CACHE_TTL |
5m |
Cache TTL duration |
CINE_SHUTDOWN_WAIT |
10s |
Graceful shutdown timeout |
make build # Compile binary
make test-short # Unit tests only
make test # All tests (requires PG)
make lint # golangci-lint
make bench # BenchmarksPrometheus metrics exposed at /metrics:
| Metric | Type | Labels |
|---|---|---|
cine_http_requests_total |
Counter | method, path, status |
cine_http_request_duration_seconds |
Histogram | method, path |
cine_cache_operations_total |
Counter | operation, result |
cine_db_query_duration_seconds |
Histogram | operation |
Structured logging via log/slog (JSON to stdout).
| Component | Choice |
|---|---|
| Language | Go 1.22+ |
| HTTP | net/http ServeMux |
| Database | PostgreSQL 17 via pgx/v5/stdlib |
| Cache | Redis 7 via go-redis/v9 |
| Metrics | prometheus/client_golang |
| Logging | log/slog (stdlib) |
| Testing | testing, httptest, table-driven |