Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a098282
imdb: Added project Requirements doc
icemc Jul 5, 2026
d0a35f2
imdb: Added product design document
icemc Jul 5, 2026
e51f260
Updated LLD to contain all require modules for our Spring Boot applic…
icemc Jul 5, 2026
4752f46
Added dependent services and configurations using docker-compose.yaml…
icemc Jul 5, 2026
73d0f01
imdb: Generated spring boot starter application
icemc Jul 5, 2026
e80491d
Updated LLD doc as we will be using the onion architecture during imp…
icemc Jul 6, 2026
6e500ee
imdb: Implemented all domain layer code
icemc Jul 6, 2026
31fcc36
imdb: Implemented all application layer code
icemc Jul 6, 2026
130dc26
imdb: Implemented all infrastructure layer code
icemc Jul 6, 2026
8b0d383
imdb: Implemented all presentation layer code
icemc Jul 6, 2026
ae6f352
Added Dockerfile and Tests
icemc Jul 7, 2026
d33c75a
Fixed caching bug, tracing and monitoring system
icemc Jul 9, 2026
9c94a01
Fix 6-degree sql implementation
icemc Jul 9, 2026
05ba284
Added structured json logging with sanitation
icemc Jul 10, 2026
4d46e91
Added Github action ci file
icemc Jul 10, 2026
6880f6b
Restructured integration tests and added e2e test using postman/newman
icemc Jul 11, 2026
94a7347
Fixed grafana dashboards
icemc Jul 11, 2026
96f1173
Added readme to imdb project
icemc Jul 11, 2026
5997f2b
Add CRUD expansion design doc for imdb
icemc Jul 12, 2026
1b54d37
Add implementation plan for the imdb CRUD expansion
icemc Jul 13, 2026
bc8ad20
Add JWT auth, user accounts, and profile/admin user management to imdb.
icemc Jul 13, 2026
0655121
Add admin id sequences and version/soft-delete columns to core tables.
icemc Jul 13, 2026
d008940
Add admin CRUD for titles with versioning, soft delete, and cache evi…
icemc Jul 13, 2026
d2d5b67
Add admin CRUD for people with versioning and soft delete.
icemc Jul 13, 2026
c6dd4d7
Add admin CRUD for cast and crew credits with six-degrees cache evict…
icemc Jul 13, 2026
8cb92a2
Add watchlist feature with public/private visibility and ownership ch…
icemc Jul 13, 2026
d210cdf
Add reviews feature and surface aggregate user ratings on title detail.
icemc Jul 13, 2026
ffc4c41
Add custom lists feature with ownership and visibility rules.
icemc Jul 13, 2026
d5d31cd
Wire auth into the e2e stack and extend Postman coverage for CRUD exp…
icemc Jul 13, 2026
6988ca0
Add design doc for adding Swagger UI and Redoc to the API.
icemc Jul 14, 2026
1589ca1
Add implementation plan for Swagger UI and Redoc.
icemc Jul 14, 2026
49f6562
Add Swagger UI via springdoc-openapi with a public API docs endpoint.
icemc Jul 14, 2026
1a1961c
Add a public Redoc page reading the same generated OpenAPI document.
icemc Jul 14, 2026
a4fe547
Document the new Swagger UI and Redoc endpoints in the README.
icemc Jul 14, 2026
7b4b026
Decorate all 48 endpoints with proper OpenAPI names and full document…
icemc Jul 14, 2026
a36dbc0
Map six-degrees query timeouts to 504 instead of a misleading 500.
icemc Jul 14, 2026
9498eba
Add a combined all-endpoints k6 load test and fix five bugs it found:…
icemc Jul 15, 2026
269a0d5
Add end-to-end request tracing: fix a real MDC traceId gap and instru…
icemc Jul 15, 2026
82f7f01
Add real screenshots of Swagger UI, Grafana dashboards, and a live Te…
icemc Jul 15, 2026
01f3147
Add a Projects section to the root README with teasers for imdb and v…
icemc Jul 15, 2026
e6e2a4a
Fix a real JWT bug from code review: refresh tokens could authenticat…
icemc Jul 15, 2026
ec2c3d2
Move every REST request/response DTO into application.rest, including…
icemc Jul 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .github/workflows/imdb-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
name: imdb CI

on:
push:
paths:
- 'imdb/**'
- '.github/workflows/imdb-ci.yml'
pull_request:
paths:
- 'imdb/**'
- '.github/workflows/imdb-ci.yml'

jobs:
unit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven

- name: Run unit tests
working-directory: imdb
run: mvn -B test

# Testcontainers-based (real Postgres/Redis/Grafana LGTM stack) - kept out of the unit stage
# deliberately, since they need Docker and take real time, not because they're less important.
integration:
needs: unit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '21'
cache: maven

- name: Run integration tests
working-directory: imdb
run: mvn -B failsafe:integration-test failsafe:verify

# Contract/e2e: a really-running imdb-service against a lightweight, deterministic seed (plain
# postgres:17 + our own Flyway migrations + the same fixture-data.sql the integration tests use),
# not the real abanda/imdb-postgresql image - that one's ~20-30 minute dataset import is fine for
# local dev but not something every push should pay for.
e2e:
needs: integration
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

# Explicit -p/project name here matches docker-compose.e2e.yaml's own `name: imdb-e2e` - keeps
# this stage's containers/network fully isolated from anything else that might be running on
# the same runner under the default directory-derived project name.
- name: Bring up the e2e stack
working-directory: imdb
run: docker compose -f docker-compose.e2e.yaml -p imdb-e2e up -d --build

- name: Wait for imdb-service to be healthy
run: |
for i in $(seq 1 30); do
if curl -sf http://localhost:8080/actuator/health >/dev/null 2>&1; then
echo "imdb-service is up"
exit 0
fi
sleep 5
done
echo "imdb-service never became healthy" >&2
exit 1

- name: Wait for the seed job to finish loading fixture data
run: |
for i in $(seq 1 20); do
status=$(docker inspect --format='{{.State.Status}}' imdb-e2e-seed-1 2>/dev/null || echo "missing")
if [ "$status" = "exited" ]; then
code=$(docker inspect --format='{{.State.ExitCode}}' imdb-e2e-seed-1)
if [ "$code" != "0" ]; then
echo "seed job failed with exit code $code" >&2
docker logs imdb-e2e-seed-1 >&2
exit 1
fi
echo "seed job completed"
exit 0
fi
sleep 3
done
echo "seed job never finished" >&2
exit 1

- name: Run Postman/Newman e2e tests
working-directory: imdb
run: npx --yes newman run postman/imdb-e2e.postman_collection.json --env-var baseUrl=http://localhost:8080

- name: Show logs on failure
if: failure()
working-directory: imdb
run: docker compose -f docker-compose.e2e.yaml -p imdb-e2e logs

- name: Tear down
if: always()
working-directory: imdb
run: docker compose -f docker-compose.e2e.yaml -p imdb-e2e down -v
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,37 @@ Each subproject targets a different corner of the JVM world on purpose, so the e
- **Bare-metal Java** — framework-free exercises touching concurrency, the memory model, and JVM internals directly
- **Cross-JVM exploration** — the same problems occasionally revisited in other JVM languages (e.g. Scala) to compare idioms and trade-offs

## Projects

### [imdb](imdb/) — production-shaped REST API over the real IMDb dataset

The most recent, and most complete, project in this repo. A Spring Boot 4.1 / Java 21 API over the full, untruncated [IMDb Non-Commercial Dataset](https://www.imdb.com/interfaces/) - millions of titles, tens of millions of cast/crew credits - not a sample or a toy CRUD example. Started as four read-only endpoints (fuzzy search, top-rated by genre, and a generalized "Six Degrees of Kevin Bacon" graph query), then grew into a 48-endpoint API with JWT auth, admin CRUD, and a full user-content layer (watchlists, reviews, custom lists).

- **A real algorithm, not a toy one**: Six Degrees is a genuine bidirectional BFS, hand-rolled in PL/pgSQL after a first, CTE-based version passed review and its own tests, then failed under real data - a silent wrong-answer bug, plus a hub-to-hub query that took 3+ minutes and spilled to disk. The fix: **29-44ms and a correct answer** on the exact pathological pair that broke the original.
- **Full observability, not a metrics endpoint**: structured JSON logs, Prometheus metrics, and OpenTelemetry distributed tracing, correlated in one Grafana instance - down to individual SQL statements and Redis commands as their own spans in a real trace waterfall, and every log line carrying the trace ID that produced it.
- **Load-tested against itself**: k6 scripts exercise every endpoint in isolation, then all 48 simultaneously; the combined run found and fixed five real bugs (HikariCP pool exhaustion, three schema drifts between the test and real database, and an id sequence colliding with orphaned imported rows) rather than just producing a green checkmark.
- **Interactive, fully-documented API** (Swagger UI) - every endpoint carries a real summary, description, and per-status-code response doc, not auto-generated `delete_3`-style operationIds.
- **Three-tier CI pipeline**: unit → Testcontainers integration → Postman/Newman e2e against the real built Docker image, not a mocked slice.

<img src="imdb/assets/swagger-ui.png" alt="Swagger UI showing grouped, fully-documented imdb endpoints" width="800">

<img src="imdb/assets/6-degree-dashboard.png" alt="Grafana dashboard breaking down Six Degrees latency against the other three endpoints" width="800">

<img src="imdb/assets/tempo-datasource-grafana-queries.png" alt="A real distributed trace in Tempo, opened directly from Grafana" width="800">

Full README, with the complete architecture, all four dashboards, and a live trace shape: [imdb/README.md](imdb/README.md).

### [votee](votee/) — exact-arithmetic vote-counting library

A Java 21 port of [votee-scala](votee-scala/), an existing Scala 3 library of mine, implementing nine vote-counting algorithms (Majority, Super Majority, Approval, Veto, Borda Count, Baldwin, Contingent Vote, Coombs' Method, Exhaustive Ballot) behind one shared, generic `Election<C, B, W>` contract.

- **Correctness over convenience**: every vote weight and score is tracked as an exact `Rational` (`BigInteger` numerator/denominator, reduced to lowest terms), not a `double` - tallies never drift from floating-point rounding, no matter how many rounds an election runs.
- **Ported for behavioral parity, not just API shape**: every algorithm is checked against the same JSON fixtures the Scala reference's own test suite uses; every place this port deliberately diverges from that reference is called out and reasoned about individually, not silently different.
- **Genuinely extensible**: bring your own `Candidate`/`Ballot`/`Winner` types by implementing the library's contracts directly - every algorithm is generic over `<C extends Candidate, B extends Ballot<C, B>>`, so a custom domain type works with zero changes to the algorithm classes themselves.
- **46 tests**, published to a private GitHub Packages Maven registry under Early SemVer.

Full README, including the algorithm table, extension guide, and every documented deviation from the Scala reference: [votee/README.md](votee/README.md).

## How this repo is organized

This is a monorepo: every top-level directory is a self-contained project with its own build tooling, tests, and README. This root README intentionally stays high-level — open a project's folder for details on its stack, design decisions, and how to run it.
Expand Down
2 changes: 2 additions & 0 deletions imdb/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf
33 changes: 33 additions & 0 deletions imdb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
HELP.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/
3 changes: 3 additions & 0 deletions imdb/.mvn/wrapper/maven-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.16/apache-maven-3.9.16-bin.zip
19 changes: 19 additions & 0 deletions imdb/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# syntax=docker/dockerfile:1

FROM eclipse-temurin:21-jdk AS build
WORKDIR /build

COPY .mvn/ .mvn/
COPY mvnw pom.xml ./
RUN chmod +x mvnw && ./mvnw -q dependency:go-offline

COPY src/ src/
RUN ./mvnw -q -DskipTests package && \
mv target/imdb-*.jar target/app.jar

FROM eclipse-temurin:21-jre
WORKDIR /app
COPY --from=build /build/target/app.jar app.jar

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Loading
Loading