From a0982824855a06793960a4175c7ac0be8dd9ce3e Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sun, 5 Jul 2026 14:50:51 +0200 Subject: [PATCH 01/42] imdb: Added project Requirements doc --- imdb/docs/REQUIREMENTS.md | 77 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 imdb/docs/REQUIREMENTS.md diff --git a/imdb/docs/REQUIREMENTS.md b/imdb/docs/REQUIREMENTS.md new file mode 100644 index 0000000..f181ea6 --- /dev/null +++ b/imdb/docs/REQUIREMENTS.md @@ -0,0 +1,77 @@ +# IMDb Copycat - Requirements + +Part of a personal return to Java after a couple of years spent primarily in other stacks (see the +[root README](../../README.md)) - a deliberate exercise in building a production-grade REST API with +Spring Boot against a real, large, publicly available dataset rather than a toy example. The dataset is +IMDb's own [Non-Commercial Dataset](https://www.imdb.com/interfaces/), which offers rich, realistic +movie/TV/people data at real scale (millions of rows) - exactly the kind of data volume where "does the +indexing strategy actually hold up" and "does the algorithm choice actually scale" stop being academic +questions. + +See [`product-design.md`](product-design.md) for the full design rationale and +[`low-level-design.md`](low-level-design.md) for schema, endpoint contracts, and implementation detail. + +## Guidelines + +- Treat this as a real production service, not a toy: project structure, code quality, readability, + documentation, tests, CI. +- Java / Spring Boot for the API layer; the rest of the stack is chosen to fit the domain - see the design + docs for what and why. +- Don't truncate the dataset. It's feasible to hold all of it on a single machine; working against the + real data volume is the point of the exercise. + +## The Requirements + +### Requirement #1 (easy): Title search + +Search by a movie's primary title or original title. The result should include related information, +including cast and crew. + +### Requirement #2 (easy): Top-rated movies by genre + +Given a genre, return the top-rated movies in that genre. + +### Requirement #3 (difficult): Six Degrees of Kevin Bacon, generalized + +[Six degrees of Kevin +Bacon](https://en.wikipedia.org/wiki/Six_Degrees_of_Kevin_Bacon): given two people (e.g. actors), +determine their degree of separation. Generalized to any two people rather than fixed to Kevin Bacon +specifically (see `product-design.md` §9 for why), bounded to a maximum of 7 degrees. + +## Data Source & Setup + +This implementation uses a personal Docker image, [`abanda/imdb-postgresql`](https://github.com/icemc/imdb-postgresql), +which loads the **full** IMDb Non-Commercial Dataset (including TV episodes) into PostgreSQL 17 across +seven tables (`name_basics`, `title_basics`, `title_ratings`, `title_crew`, `title_episode`, +`title_principals`, `title_akas`). Connection details: + +``` +JDBC URL = jdbc:postgresql://localhost:5432/imdb +Username = imdb +Password = password +``` + +IDs (`tconst`/`nconst`) are stored as plain integers in this schema (the `tt`/`nm` prefix and leading +zeros are stripped on import); the API translates between IMDb-style string IDs and these internal +integers at the boundary - see the low-level design for details. + +### Running it + +1. Run `docker-compose up` from the `imdb/` directory. This brings up PostgreSQL (seeded via + `abanda/imdb-postgresql`), Redis, and the full observability stack (Prometheus, Loki, Tempo, Grafana, + Grafana Alloy, plus Postgres/Redis exporters) - see `docker-compose.yaml` and the `observability/` + directory. The first run takes 20-30 minutes while Postgres imports the dataset; `docker-compose logs -f postgres` + shows import progress. +2. The Spring Boot application (`imdb-service`, Java 21 / Maven, scaffolded via + [start.spring.io](https://start.spring.io/)) starts as part of the same `docker-compose up` once the + project exists in this directory - see the low-level design for module layout and dependencies. +3. Grafana is available at `http://localhost:3000` (anonymous admin access, local-only) with Prometheus, + Loki, and Tempo pre-provisioned as datasources with trace/log/metric correlation wired up. +4. Load tests live under `imdb/k6/`, one script per endpoint. They are not part of `docker-compose up` by + default (`k6` is behind the `load-test` compose profile) and are run one at a time, e.g.: + `docker-compose --profile load-test run k6 run /scripts/six-degrees.js`. + +### Scope + +Four read-only REST endpoints cover the three requirements above. No authentication, no write endpoints - +see the product design document's Non-Goals section for the full list of deliberate exclusions. From d0a35f2541eef17325b5a1fd2903f90ecd4db625 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sun, 5 Jul 2026 15:24:07 +0200 Subject: [PATCH 02/42] imdb: Added product design document --- imdb/docs/product-design.md | 216 ++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 imdb/docs/product-design.md diff --git a/imdb/docs/product-design.md b/imdb/docs/product-design.md new file mode 100644 index 0000000..962b154 --- /dev/null +++ b/imdb/docs/product-design.md @@ -0,0 +1,216 @@ +# IMDb Copycat API - Product Design Document + +| | | +|---|---| +| **Author** | Ludovic Temgoua Abanda | +| **Status** | Draft | +| **Date** | 2026-07-05 | +| **Related docs** | `imdb/docs/low-level-design.md` (follow-up), `imdb/docs/REQUIREMENTS.md` (requirements + concrete setup) | +| **Data source** | [`abanda/imdb-postgresql`](https://github.com/icemc/imdb-postgresql) (full IMDb Non-Commercial Dataset in PostgreSQL 17) | + +## 1. Overview + +`imdb` is a production-shaped Spring Boot REST API over the IMDb Non-Commercial Dataset, covering title +search with cast/crew, top-rated movies by genre, and the "Six Degrees of Kevin Bacon" graph problem. Like +`votee` (see `votee/docs/product-design.md`), this is a revision exercise as part of a deliberate return +to the Java ecosystem (see the [root README](../../README.md)) - the point isn't just to satisfy the three +functional requirements, but to do so the way a real production service would: proper indexing instead of +full table scans, a defensible algorithm choice for the graph problem instead of "whatever is simplest," +caching, and full observability (metrics/logs/traces) rather than bolt-on logging. + +This document defines *what* is being built and *why*. The follow-up Low-Level Design document defines +*how* - schema mapping, endpoint contracts, the recursive-CTE SQL, docker-compose topology, and the test +plan. + +## 2. Background + +A common approach to sourcing the IMDb dataset locally truncates it (e.g. dropping `tvEpisodes`) to speed +up import - but the requirements (`imdb/docs/REQUIREMENTS.md`) deliberately call for working against the +real, untruncated data volume, since that's where indexing and algorithm choices actually get tested. This +implementation uses a personal Docker image, `abanda/imdb-postgresql`, which loads the **full** dataset +(including TV episodes) across seven tables: `name_basics`, `title_basics`, `title_ratings`, `title_crew`, `title_episode`, +`title_principals`, `title_akas`. A notable schema detail that shapes several downstream decisions: IDs +are stored as plain `INTEGER`, not IMDb's public `tt`/`nm` string format - the loader strips the prefix +and leading zeros on import (`tt0111161` -> `111161`). No indexes beyond primary keys exist out of the +box, and referential integrity between `title_principals` and `name_basics`/`title_basics` is not +enforced by the loader. + +The three requirements sit on the same underlying co-occurrence data (people, titles, and their +relationships) but stress genuinely different parts of the stack: requirement 1 is a search/read problem, +requirement 2 is a ranking problem, and requirement 3 is a graph-traversal problem at a scale (millions of +people, tens of millions of co-star edges) where the naive approach breaks down under load. That last +point is why this document spends real space on comparing algorithms rather than just picking one. + +## 3. Goals + +- Three read endpoints (plus one supporting search endpoint) that fully satisfy the three functional + requirements against the real, unmodified dataset - no synthetic subset, per the requirements' own + guideline against truncating data. +- A **defensible, literature-grounded** algorithm choice for Six Degrees of Kevin Bacon that holds up under + load for arbitrary person-to-person queries (not just "distance to Kevin Bacon" - see §9), bounded to a + configurable maximum of 7 degrees. +- Full observability: metrics, structured logs, and distributed traces correlated in a single Grafana + instance, not just `println`-style logging. +- A demonstrated, load-tested understanding of where this design's performance risk actually lives (the + graph-traversal endpoint), backed by k6 results per endpoint. +- A fully containerized local environment (`docker-compose up`) that brings up the database, cache, + application, and the entire observability stack with no manual setup steps beyond that one command. + +## 4. Non-Goals + +- Authentication/authorization. This is a read-only public API for the purposes of this exercise; see §12. +- Write endpoints of any kind. The dataset is seeded once via the Docker image; there is nothing to + mutate. +- General-purpose graph database infrastructure (e.g. Neo4j) as a *running* dependency. It's evaluated and + documented as an alternative in §9 but not built, since it isn't justified at this dataset's scale. +- A UI. This is an API-only deliverable, consistent with the requirements' "endpoint" framing. +- Exact production-grade horizontal scalability (sharding, read replicas, multi-region). The design is + production-*shaped* - correct indexing, caching, observability, load-tested - but scoped to a + single-node deployment appropriate for a revision project. + +## 5. Target Users & Use Cases + +A single consumer persona: a client application (or a developer exercising the API directly via HTTP) +wanting to: +look up a movie by title and see who was in it and who made it; find the best-reviewed movies in a genre; +and find out how closely connected two people in the film industry are - the classic "Six Degrees" party +game, generalized to any two people rather than fixed to Kevin Bacon. + +## 6. Functional Requirements + +### 6.1 Data model (mapped from the seeded schema) + +| Table | Responsibility | +|---|---| +| `title_basics` | Core title data: type, primary/original title, years, runtime, genres | +| `title_ratings` | Average rating and vote count per title | +| `title_crew` | Directors and writers per title | +| `title_principals` | Cast/crew billing per title (person, ordering, category, job, character) | +| `title_episode` | TV episode -> parent series linkage (out of scope for this pass; see §12) | +| `title_akas` | Localized alternate titles (out of scope for this pass; see §12) | +| `name_basics` | Person data: name, birth/death year, professions, known-for titles | + +None of these are modified by the application. Additions on top (indexes, a materialized co-star-edge +view) are described in the low-level design. + +### 6.2 Endpoints + +| # | Endpoint | Requirement | Summary | +|---|---|---|---| +| 1 | `GET /api/v1/titles/search` | #1 | Fuzzy search by primary or original title; paginated list of lightweight matches | +| 2 | `GET /api/v1/titles/{titleId}` | #1 | Full title detail: metadata, rating, directors/writers, top-billed cast | +| 3 | `GET /api/v1/genres/{genre}/top-rated` | #2 | Top-rated movies in a genre, ranked by weighted (Bayesian) rating, not raw average | +| 4 | `GET /api/v1/people/six-degrees` | #3 | Degree of separation between any two people (name or ID), bounded to a configurable max (default and hard cap: 7) | + +Endpoint 2 exists because requirement 1 explicitly asks for "related information...including cast and +crew," which doesn't fit in a search-result list item without making every search response expensive; a +search-then-detail split is the standard REST shape for this. Full contracts (request/response DTOs, +error shapes) are in the low-level design, §5. + +## 7. Non-Functional Requirements + +- **Correctness under load, not just correctness**: every endpoint must remain within its latency + threshold under the k6 load profiles in the low-level design, not just return the right answer for a + single request. +- **No unbounded queries**: search is paginated; top-rated has a `limit`; six-degrees has a hard-capped + traversal depth. Nothing in this API can trigger an unbounded table scan or unbounded graph walk. +- **Read-mostly caching**: since the underlying data only changes when the Docker image is reloaded (no + write path), aggressive Redis caching is a legitimate default, not a premature optimization. +- **Observability by default**: every request is traceable end-to-end (HTTP -> service -> DB/cache) via + correlated metrics, logs, and traces - not added after the fact. +- **ID stability at the API boundary**: the API exposes IMDb-style `tt`/`nm` string IDs, never the + internal integer PKs, so the public contract doesn't leak a storage detail that's specific to this one + Docker image's schema choices. + +## 8. High-Level Architecture + +- **Application**: Spring Boot 3, Java 21, Maven (consistent with `votee`'s build-tool choice elsewhere in + this monorepo). +- **Database**: PostgreSQL 17 via `abanda/imdb-postgresql`, read-only from the application's perspective. +- **Cache**: Redis, cache-aside pattern via Spring's cache abstraction, in front of all four endpoints. +- **Observability**: Prometheus (metrics) + Loki (logs, shipped via Grafana Alloy) + Tempo (traces, via + OTLP) + Grafana (single pane of glass, datasources provisioned with trace/log/metric correlation), plus + Postgres and Redis Prometheus exporters so database- and cache-level behavior is visible alongside + application metrics. +- **Load testing**: Grafana k6, one script per endpoint, results pushed to Prometheus so a load-test run + is visible in the same Grafana instance as the application's own telemetry for that time window. +- **Local orchestration**: a single `docker-compose.yaml` brings up the entire stack (database, cache, + application, observability, and an opt-in `load-test` profile for k6). + +``` +Client -> imdb-service (Spring Boot) + |-- reads/caches --> Redis + |-- queries --------> PostgreSQL (abanda/imdb-postgresql) + |-- metrics --------> Prometheus <-- postgres-exporter, redis-exporter + |-- logs (stdout) --> Grafana Alloy --> Loki + |-- traces (OTLP) --> Tempo + \ + --> Grafana (dashboards, correlated across all three) + +k6 (one script per endpoint, run in isolation) --> imdb-service, results --> Prometheus +``` + +## 9. Key Design Decisions & Rationale + +| Decision | Chosen approach | Alternatives considered | Rationale | +|---|---|---|---| +| Six Degrees algorithm | Bidirectional recursive CTE in Postgres (two capped `WITH RECURSIVE` queries, one from each person, meeting in the middle), plus Redis-cached results | (a) One-sided recursive CTE from a fixed Kevin-Bacon root; (b) precomputed single-source BFS from Kevin Bacon; (c) in-memory bidirectional BFS in the JVM; (d) Pruned Landmark Labeling (PLL); (e) dedicated graph database (Neo4j) | The requirement isn't fixed to Kevin Bacon - any two people can be queried - which rules out precomputing from one root. A naive one-sided traversal risks combinatorial blowup through high-degree "hub" actors; meeting in the middle halves the exponent and, combined with the max-7-degree cap (so each side only expands ~4 hops), keeps worst-case cost bounded without new infrastructure. PLL (Akiba et al., SIGMOD 2013) is the literature's actual state-of-the-art for this class of problem - hub-labeling with microsecond exact queries at hundreds-of-millions-of-edges scale - but it's a bespoke indexing engine, disproportionate to build for this exercise; documented as the answer if this had to serve real production query volume. Neo4j is the standard "just use a graph database" answer but adds a second datastore to operate and keep in sync for no benefit at this data size. | +| Result caching | Redis, cache-aside, keyed by unordered person pair, storing the **true shortest distance up to the absolute 7-degree cap** regardless of the caller's requested max | Cache per (pair, requested-max) combination | A distance of, say, 5 is a fact independent of whether the caller asked for `maxDegree=3` or `maxDegree=7`; caching the true distance once lets every future request for that pair reuse it and simply filter against its own bound, instead of fragmenting the cache by request parameter. | +| Top-rated ranking | IMDb-style weighted (Bayesian) rating: `WR = (v/(v+m))*R + (m/(v+m))*C` | Sort by raw `average_rating` | A raw-average sort lets a movie with 3 votes at 10/10 outrank one with 500,000 votes at 8.9. The weighted formula is IMDb's own published approach for exactly this reason, and demonstrates the same ranking-under-uncertainty thinking the Six Degrees decision does. | +| Title search | PostgreSQL `pg_trgm` fuzzy/similarity search over `primary_title`/`original_title`, GIN-indexed | Exact/prefix `ILIKE` match | Users don't reliably know a title's exact casing/wording; trigram similarity tolerates typos and partial matches while still being index-backed (not a sequential scan), which matters given `title_basics` has millions of rows. | +| API ID format | Public API uses IMDb-style `tt`/`nm` string IDs; translated to the internal integer PK at the repository boundary | Expose the internal integer IDs directly | The integer PK is an artifact of this specific Docker image's import script, not a stable public contract. Consumers of an "IMDb copycat" API expect IMDb's own ID format. | +| Caching layer | Redis (new dependency) | In-process cache (e.g. Caffeine) | The load-testing goal explicitly requires observing cache behavior (hit/miss ratio) as a first-class signal via a Redis Prometheus exporter, and a shared external cache is the realistic production shape if this API ever ran more than one instance. | +| Build tool | Maven | Gradle | Consistent with `votee` elsewhere in this monorepo. | +| Six Degrees scope | Generalized: `personA`/`personB` are both arbitrary query inputs | Literal brief wording: fixed target = Kevin Bacon | Once a bidirectional traversal is the implementation (required regardless, to bound hub-actor blowup - see the algorithm row above), accepting two arbitrary people costs nothing extra - a Kevin-Bacon-fixed version would just be this same endpoint with one side pre-filled. Generalizing is strictly more capable for the same engineering cost, so there's no reason to artificially narrow it back to the literal brief wording. | + +## 10. Success Criteria + +- All three functional requirements are satisfied against the full (untruncated) dataset via the four + endpoints in §6.2. +- The Six Degrees endpoint correctly computes degrees of separation between arbitrary people (not just + relative to Kevin Bacon), respects the caller's `maxDegree` bound, and returns within its k6-tested + latency threshold even for high-degree "hub" actors. +- `docker-compose up` brings up the full stack (database, cache, application, full observability stack) + with no manual steps beyond that one command (excluding the one-time 20-30 minute dataset import). +- Every endpoint has a Grafana-visible trace, and its k6 load-test run is visible in the same Grafana + instance correlated against application/DB/cache metrics for that time window. +- Integration tests pass in CI against a lightweight fixture dataset (not the full 20GB image - see the + low-level design's test plan for why). + +## 11. Risks & Open Questions + +- **Hub-actor blowup risk remains partially empirical**: the bidirectional-CTE mitigation is + literature-grounded, but its actual worst-case latency on this specific dataset's most prolific actors + (some have thousands of credits) is only proven by the k6 results, not by design alone. If load testing + reveals the recursive CTE still misbehaves at the extreme tail, the documented fallback is the + precomputed/in-memory BFS alternative from §9, promoted from "documented" to "implemented." +- **`title_principals` has no enforced foreign keys** (the loader's `add_references` step is not + consistently applied per its own source comments), so orphaned `nconst`/`tconst` references are + possible in principle; queries need to tolerate missing joins rather than assume referential integrity. +- **Open question**: whether the `co_star_edges` materialized view (low-level design §4) needs a + scheduled refresh in a longer-lived deployment, or whether "refresh once after the one-time data import" + is sufficient given there's no write path. Deferred - not required for this pass's success criteria. +- **Open question**: exact `minVotes` default for the weighted-rating formula on top-rated movies. Needs a + quick data-driven look at the vote-count distribution once the dataset is loaded, rather than guessing a + round number up front - flagged as an implementation-time task in the low-level design. + +## 12. Out of Scope / Future Work + +- `title_akas` (localized alternate titles) and `title_episode` (TV episode hierarchy) are loaded but not + surfaced by any endpoint in this pass. +- Authentication/authorization of any kind. +- Promoting Pruned Landmark Labeling or a dedicated graph database from "documented alternative" to + "implemented," should load testing prove the chosen bidirectional-CTE approach insufficient at real + production query volume. +- Multi-instance/horizontal scaling of the application tier (the design is cache/observability-ready for + it, but it isn't exercised here). + +## 13. References + +- Data source: [`abanda/imdb-postgresql`](https://github.com/icemc/imdb-postgresql) +- Requirements: [`REQUIREMENTS.md`](REQUIREMENTS.md) +- Akiba, Iwata, Yoshida, "Fast Exact Shortest-Path Distance Queries on Large Networks by Pruned Landmark + Labeling," SIGMOD 2013 - [arXiv:1304.4661](https://arxiv.org/abs/1304.4661) +- Goldberg et al., "Reach for A*: Efficient Point-to-Point Shortest Path Algorithms" - + [Microsoft Research](https://www.microsoft.com/en-us/research/wp-content/uploads/2006/01/tr-2005-132.pdf) +- Root repository context: [`/README.md`](../../README.md) From e51f260826690e299ecf6e46d1fa9623900bfed6 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sun, 5 Jul 2026 19:07:24 +0200 Subject: [PATCH 03/42] Updated LLD to contain all require modules for our Spring Boot application --- imdb/docs/low-level-design.md | 490 ++++++++++++++++++++++++++++++++++ 1 file changed, 490 insertions(+) create mode 100644 imdb/docs/low-level-design.md diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md new file mode 100644 index 0000000..c9e19ef --- /dev/null +++ b/imdb/docs/low-level-design.md @@ -0,0 +1,490 @@ +# IMDb Copycat API - Low-Level Design Document + +| | | +|---|---| +| Author | Ludovic Temgoua Abanda | +| Status | Draft | +| Date | 2026-07-05 | +| Related docs | `imdb/docs/product-design.md` (PDD, approved), `imdb/docs/REQUIREMENTS.md` | +| Data source | [`abanda/imdb-postgresql`](https://github.com/icemc/imdb-postgresql) | + +## 1. Purpose and Scope + +The PDD defines what is being built and why. This document defines how: schema additions on top of the +seeded database, endpoint contracts, the bidirectional-CTE SQL for Six Degrees, the caching strategy, +docker-compose topology, observability wiring, and the test plan. This is a design reference for manual +implementation, not generated production code - the Maven project itself (`pom.xml`, `src/`) does not yet +exist in this repository; scaffolding it via [start.spring.io](https://start.spring.io/) is the first +implementation step once this document is approved (see §11). + +## 2. Maven Module Layout (target state) + +``` +imdb/ + pom.xml + Dockerfile + docker-compose.yaml + docs/ + REQUIREMENTS.md + product-design.md + low-level-design.md + observability/ + prometheus/prometheus.yml + tempo/tempo.yaml + alloy/config.alloy + grafana/provisioning/ + datasources/datasources.yml + dashboards/dashboards.yml + dashboards/json/ # dashboard JSON models, authored during implementation + k6/ + search.js + title-detail.js + top-rated.js + six-degrees.js + data/sampled-people.csv # actor pool used by six-degrees.js to defeat caching + src/ + main/ + java/com/ludovictemgoua/imdb/ + ImdbApplication.java + config/ + CacheConfig.java + JdbcConfig.java + OpenApiConfig.java + web/ + TitleController.java + GenreController.java + PersonController.java + dto/ + TitleSummary.java + TitleDetail.java + RatingView.java + CastMember.java + CreditedPerson.java + GenreTopRatedItem.java + SixDegreesResult.java + PersonCandidate.java + service/ + TitleSearchService.java + TitleDetailService.java + TopRatedService.java + PersonResolutionService.java + SixDegreesService.java + repository/ + TitleRepository.java + PersonRepository.java + CoStarGraphRepository.java + graph/ + BidirectionalPathResult.java + PathStitcher.java + error/ + ApiExceptionHandler.java + NotFoundException.java + AmbiguousPersonException.java + resources/ + application.yml + db/migration/ + V1__extensions_and_search_indexes.sql + V2__co_star_edges_materialized_view.sql + test/ + java/com/ludovictemgoua/imdb/ + web/ (controller tests, MockMvc) + service/ (unit tests, mocked repositories) + integration/ (Testcontainers + fixture dataset) + resources/ + fixtures/ + fixture-schema.sql + fixture-data.sql +``` + +`application.yml`, not `.properties`: the config surface is more nested than a typical CRUD app - +`management.metrics.*`, `management.tracing.*`, and `management.otlp.*` (§7) sit several levels deep +alongside a custom `six-degrees.*` group (§5/§6), and YAML's multi-document `---` profiles let the +Testcontainers-backed integration tests (§10) override just the datasource block against the fixture +container instead of `docker-compose.yaml`'s Postgres, without duplicating everything else. + +## 3. Data Layer + +### 3.1 Why plain JDBC, not JPA/Hibernate + +Every query this API needs is a hand-tuned native query: trigram similarity search, GIN array containment +for genres, a Bayesian weighted-rating computation, and a recursive CTE for graph traversal. None of these +benefit from Hibernate's object-relational mapping or dirty-checking - there is no object graph being +mutated, only read projections. Introducing JPA here would mean fighting it (native `@Query` everywhere) +for zero benefit. The design instead uses Spring's `NamedParameterJdbcTemplate` with explicit `RowMapper`s +throughout, and Flyway for the two migrations below - one data-access style, not two. + +### 3.2 Migration V1: extensions and search indexes + +```sql +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +CREATE INDEX idx_title_basics_primary_title_trgm + ON title_basics USING gin (primary_title gin_trgm_ops); + +CREATE INDEX idx_title_basics_original_title_trgm + ON title_basics USING gin (original_title gin_trgm_ops); + +CREATE INDEX idx_title_basics_genres + ON title_basics USING gin (genres); + +CREATE INDEX idx_title_ratings_rank + ON title_ratings (average_rating DESC, num_votes DESC); + +CREATE INDEX idx_title_principals_nconst_acting + ON title_principals (nconst) + WHERE category IN ('actor', 'actress', 'self'); + +CREATE INDEX idx_name_basics_primary_name_trgm + ON name_basics USING gin (primary_name gin_trgm_ops); +``` + +### 3.3 Migration V2: the co-star edge view + +The recursive CTE in §5 needs to expand "who has this person co-starred with" on every hop. Doing that +directly against `title_principals` means a self-join over the full table (tens of millions of rows, +filtered twice) on every single hop of every query. Instead, a materialized view precomputes the edge list +once: + +```sql +CREATE MATERIALIZED VIEW co_star_edges AS +SELECT DISTINCT p1.nconst AS person_a, p2.nconst AS person_b +FROM title_principals p1 +JOIN title_principals p2 + ON p1.tconst = p2.tconst + AND p1.nconst <> p2.nconst +WHERE p1.category IN ('actor', 'actress', 'self') + AND p2.category IN ('actor', 'actress', 'self'); + +CREATE UNIQUE INDEX idx_co_star_edges_pk ON co_star_edges (person_a, person_b); +``` + +Note this is deliberately stored **directionally symmetric** (both `(a, b)` and `(b, a)` rows exist, +since the self-join naturally produces both orderings) rather than deduplicated with `LEAST`/`GREATEST`. +That trades roughly 2x storage for a simpler, single-direction lookup (`WHERE person_a = ?`) in the hot +path, instead of a `UNION ALL` on every hop of the recursive CTE. + +**Refresh strategy**: `REFRESH MATERIALIZED VIEW CONCURRENTLY co_star_edges` once after the one-time +dataset import completes (there is no write path afterward - see PDD §11's open question on this). A +`REFRESH ... CONCURRENTLY` requires the unique index above, which is already in place. + +### 3.4 ID translation at the boundary + +`tconst`/`nconst` are stored as plain `INTEGER`. The API never exposes these directly: + +```java +public final class ImdbIds { + public static int parseTitleId(String tt) { // "tt0111161" -> 111161 + return Integer.parseInt(requirePrefix(tt, "tt")); + } + public static int parsePersonId(String nm) { // "nm0000102" -> 102 + return Integer.parseInt(requirePrefix(nm, "nm")); + } + public static String formatTitleId(int tconst) { return "tt" + pad7(tconst); } + public static String formatPersonId(int nconst) { return "nm" + pad7(nconst); } +} +``` + +A malformed ID (wrong prefix, non-numeric suffix) is a `400` at the controller boundary via a +`@RequestParam`/`@PathVariable` converter, before it ever reaches a service or query. + +## 4. Endpoint Specifications + +### 4.1 `GET /api/v1/titles/search?title={q}&page=&size=` + +Trigram similarity search, ordered by match quality: + +```sql +SELECT tconst, primary_title, original_title, title_type, start_year, end_year, + similarity(primary_title, :query) AS score +FROM title_basics +WHERE primary_title % :query OR original_title % :query +ORDER BY score DESC +LIMIT :size OFFSET :offset; +``` + +(`%` is `pg_trgm`'s similarity operator, index-backed by the GIN indexes in §3.2.) Response: a +`Page` (`id`, `primaryTitle`, `originalTitle`, `titleType`, `startYear`, `endYear`). + +### 4.2 `GET /api/v1/titles/{titleId}` + +Three queries (title metadata + rating; directors/writers via `title_crew` joined to `name_basics`; +top-billed cast via `title_principals` joined to `name_basics`, ordered by `ordering`, capped at 20 with a +total count), composed into one `TitleDetail`: + +```json +{ + "id": "tt0111161", + "primaryTitle": "The Shawshank Redemption", + "originalTitle": "The Shawshank Redemption", + "titleType": "movie", + "startYear": 1994, + "runtimeMinutes": 142, + "genres": ["Drama"], + "rating": { "average": 9.3, "numVotes": 2900000 }, + "directors": [{ "id": "nm0001104", "name": "Frank Darabont" }], + "writers": [{ "id": "nm0001104", "name": "Frank Darabont" }], + "cast": [ + { "id": "nm0000209", "name": "Tim Robbins", "category": "actor", "characters": ["Andy Dufresne"], "ordering": 1 } + ], + "castTotalCount": 20 +} +``` + +`404` (via `NotFoundException` -> `ProblemDetail`) if `tconst` doesn't exist in `title_basics`. + +### 4.3 `GET /api/v1/genres/{genre}/top-rated?limit=&minVotes=` + +Restricted to `title_type = 'movie'`, ranked by weighted rating rather than raw average (PDD §9): + +```sql +WITH pool AS ( + SELECT tb.tconst, tb.primary_title, tb.start_year, tr.average_rating, tr.num_votes + FROM title_basics tb + JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.title_type = 'movie' + AND tb.genres @> ARRAY[:genre]::genre[] + AND tr.num_votes >= :minVotes +), +stats AS ( + SELECT AVG(average_rating) AS mean_rating FROM pool +) +SELECT p.tconst, p.primary_title, p.start_year, p.average_rating, p.num_votes, + (p.num_votes::numeric / (p.num_votes + :minVotes)) * p.average_rating + + (:minVotes::numeric / (p.num_votes + :minVotes)) * s.mean_rating AS weighted_rating +FROM pool p CROSS JOIN stats s +ORDER BY weighted_rating DESC +LIMIT :limit; +``` + +`minVotes` (the Bayesian `m`) defaults to a value chosen from the actual vote-count distribution once the +dataset is loaded (PDD §11 open question) rather than an arbitrary round number; `mean_rating` (the +Bayesian `C`) is computed live over the qualifying pool so it self-adjusts per genre rather than using a +single global constant. + +### 4.4 `GET /api/v1/people/six-degrees?personA=&personB=&maxDegree=` + +Accepts either `personId` (`nm...`) or `name` for each side. See §5 for the full algorithm; response +shape: + +```json +{ + "personA": { "id": "nm0000102", "name": "Kevin Bacon" }, + "personB": { "id": "nm0000158", "name": "Tom Hanks" }, + "degree": 2, + "withinRequestedMax": true, + "path": [ + { "id": "nm0000102", "name": "Kevin Bacon" }, + { "id": "nm0000129", "name": "Tom Cruise", "sharedTitle": { "id": "tt0100405", "primaryTitle": "A Few Good Men" } }, + { "id": "nm0000158", "name": "Tom Hanks", "sharedTitle": { "id": "tt0181689", "primaryTitle": "The Terminal", "note": "illustrative" } } + ] +} +``` + +If a `name` matches more than one person, the response is a disambiguation payload instead +(`{"requiresDisambiguation": true, "query": "...", "candidates": [...]}`, HTTP `200`) rather than an +error - it's an expected, common case (many people share a name), not a client mistake. `maxDegree` is +validated to `1..=7` (`400` outside that range). + +## 5. Six Degrees: Bidirectional Recursive CTE + +### 5.1 Why bidirectional, not the naive one-sided walk + +A one-sided recursive walk from person A, expanding until person B is found, pays the graph's full +branching factor for every hop - and this graph has extreme hub nodes (some credited actors have +thousands of co-stars). Meeting in the middle from both ends roughly squares down the search space +(`b^(d/2)` instead of `b^d`), and combined with the product's own 7-degree cap, each side only ever needs +to expand `⌈7/2⌉ = 4` hops. See PDD §9 for the full comparison against precomputed BFS, in-memory BFS, and +Pruned Landmark Labeling. + +### 5.2 The query + +```sql +WITH RECURSIVE forward(person, depth, path) AS ( + SELECT :personA::int, 0, ARRAY[:personA::int] + UNION ALL + SELECT nbr.person_b, f.depth + 1, f.path || nbr.person_b + FROM forward f + CROSS JOIN LATERAL ( + SELECT e.person_b + FROM co_star_edges e + WHERE e.person_a = f.person + ORDER BY e.person_b + LIMIT :fanOutCap + ) nbr + WHERE f.depth < :sideCap + AND NOT nbr.person_b = ANY(f.path) +), +backward(person, depth, path) AS ( + SELECT :personB::int, 0, ARRAY[:personB::int] + UNION ALL + SELECT nbr.person_b, b.depth + 1, b.path || nbr.person_b + FROM backward b + CROSS JOIN LATERAL ( + SELECT e.person_b + FROM co_star_edges e + WHERE e.person_a = b.person + ORDER BY e.person_b + LIMIT :fanOutCap + ) nbr + WHERE b.depth < :sideCap + AND NOT nbr.person_b = ANY(b.path) +) +SELECT f.depth + b.depth AS degree, f.path AS forward_path, b.path AS backward_path +FROM forward f +JOIN backward b ON b.person = f.person +WHERE f.depth + b.depth <= :absoluteMaxDegree +ORDER BY degree ASC +LIMIT 1; +``` + +- `:sideCap` = 4 (fixed at `⌈7/2⌉`) and `:absoluteMaxDegree` = 7, both independent of the caller's + requested `maxDegree` - see caching rationale in §6. The explicit `WHERE` matters: with `sideCap=4` on + each side, the two CTEs can meet at combined depth 8, one more than the product's absolute cap. Without + this filter that would surface as a spurious "degree 8" answer; with it, no matching row means the + service layer cleanly reports "no path found within 7 degrees" - a plain empty result, not a value that + needs post-hoc clipping. +- `:fanOutCap` (e.g. 200) bounds how many neighbors a single hub node contributes per hop. This is an + explicit, documented approximation: if a node's true shortest-path edge falls outside its top-200 + neighbors by `person_b` ordering, that path is missed. This is the practical trade-off that makes the + hub-blowup problem tractable in plain SQL; it is a config knob (`six-degrees.fan-out-cap`), not a hidden + magic number, so it can be tuned or disabled (`LIMIT NULL`-equivalent) if load testing shows it's overly + aggressive. +- `statement_timeout` is set per-query (e.g. `SET LOCAL statement_timeout = '2000ms'`) as a last-resort + circuit breaker on top of the two caps above. +- The application resolves the winning `forward_path`/`backward_path` into a single displayed path by + reversing `backward_path` and concatenating, dropping the duplicated meeting node - this stitching + happens in `PathStitcher`, not in SQL. +- `personA == personB` is special-cased in `SixDegreesService` to return degree `0` without running the + query at all. + +### 5.3 Person resolution + +`PersonResolutionService` resolves a `name` query against `name_basics` via the trigram index from §3.2. +Exactly one strong match (similarity above a threshold and no close runner-up) proceeds directly; multiple +plausible matches return the disambiguation payload from §4.4, including `birthYear` and a couple of +`knownForTitles` entries per candidate so a human can tell "Michael J. Fox" from another same-named person +at a glance. + +## 6. Caching Strategy + +Redis, cache-aside, via Spring's `@Cacheable`/`CacheManager`, one cache region per endpoint: + +| Cache | Key | TTL | Notes | +|---|---|---|---| +| `title-search` | `title, page, size` | 24h | Small enough result sets that full-parameter keying is fine | +| `title-detail` | `titleId` | 24h | Highest hit-rate cache; title detail is the most repeatable lookup | +| `top-rated` | `genre, limit, minVotes` | 24h | | +| `six-degrees` | `min(personA,personB):max(personA,personB)` (**not** including `maxDegree`) | 24h | Stores the true shortest distance up to the absolute 7-degree cap; a request with a smaller `maxDegree` is served from the same cache entry and simply reports "beyond requested max" without recomputation (PDD §9) | + +All TTLs are long because the underlying dataset only changes when the Docker image is reloaded - there +is no write path invalidating these entries mid-flight. A full `FLUSHDB` on redeploy is the accepted +invalidation strategy, documented rather than automated, since there's no signal in the running system +that would tell it the data changed underneath it. + +**Load-test interaction** (carried over from the PDD discussion): the `six-degrees` k6 script must draw a +different, pre-sampled person pair per iteration specifically so it exercises the bidirectional CTE +instead of just measuring a warm Redis round-trip after the first request - see §8. + +## 7. Observability Wiring + +- **Metrics**: `micrometer-registry-prometheus`, default HTTP/JVM metrics plus custom ones: a `Timer` per + endpoint's DB-query phase (so the six-degrees CTE's latency is visible as its own series, separate from + total request latency), and `Counter`s for cache hit/miss per cache region. +- **Tracing**: `micrometer-tracing-bridge-otel` + OTLP exporter to Tempo + (`management.otlp.tracing.endpoint=http://tempo:4318/v1/traces`, matching `docker-compose.yaml`). + `management.tracing.sampling.probability=1.0` for this exercise (full sampling; would be tuned down in + a real production deployment under real traffic volume). +- **Logging**: structured JSON via Spring Boot's built-in structured logging support, trace/span IDs + included automatically via Micrometer Tracing's MDC integration, shipped to Loki via Grafana Alloy + (already wired in `docker-compose.yaml` / `observability/alloy/config.alloy`) - no application-side + logging-shipper dependency needed. +- **Correlation**: `observability/grafana/provisioning/datasources/datasources.yml` already wires + Loki-derived-fields -> Tempo and Tempo -> Loki/Prometheus, so a trace opened in Grafana click-throughs to + its log lines and vice versa. +- **Dashboards**: provisioned via `observability/grafana/provisioning/dashboards/dashboards.yml`, pointing + at a `dashboards/json/` folder. Actual dashboard JSON models (HTTP overview, six-degrees CTE latency + breakdown, cache hit ratio, k6 load-test results) are authored during implementation, not shipped as + part of this design (see §11). + +## 8. k6 Load Testing Plan + +One script per endpoint under `imdb/k6/`, run one at a time (never concurrently) so each run's metrics +are attributable to a single endpoint: + +| Script | Pattern | Notes | +|---|---|---| +| `search.js` | Ramping VUs (0 -> 50 -> 100 -> 0), random query terms from a word list | | +| `title-detail.js` | Ramping VUs, random `tconst` sampled from a pre-fetched pool | | +| `top-rated.js` | Ramping VUs, cycles through all genre enum values | | +| `six-degrees.js` | Ramping VUs, **each iteration picks a distinct person pair** from `data/sampled-people.csv` (mix of ordinary and high-degree "hub" actors) | Deliberately defeats the Redis cache (§6) so the bidirectional CTE's real behavior under load is what gets measured, not cache round-trip time | + +Each script: `p(95) < ` and `error rate < 1%` thresholds, tuned per endpoint (the six-degrees +threshold is expected to be materially higher than the others - that gap *is* the finding). All four +output via `--out experimental-prometheus-rw` (`K6_PROMETHEUS_RW_SERVER_URL` already set in +`docker-compose.yaml`), so a load-test run is visible in Grafana alongside the application's own +traces/metrics for that time window. `k6` runs behind the `load-test` compose profile: + +``` +docker-compose --profile load-test run k6 run /scripts/six-degrees.js +``` + +## 9. Error Handling & API Conventions + +- All errors are RFC 7807 `ProblemDetail` (Spring Boot 3 built-in): `404` for unknown IDs, `400` for + malformed IDs / out-of-range `maxDegree` / missing required query params. +- Six-degrees disambiguation is `200`, not an error status - see §4.4. +- Pagination via Spring Data `Pageable` (`page`, `size`, default `sort`) on search and top-rated. +- `springdoc-openapi` for a self-serve Swagger UI. + +## 10. Test Plan + +The seeded `abanda/imdb-postgresql` image is ~20GB and takes 20-30 minutes to import - unusable as a CI +dependency. Testing splits accordingly: + +- **Unit tests**: service layer against mocked repositories (JUnit 5 + Mockito + AssertJ, matching + `votee`'s existing testing style in this monorepo). +- **Integration tests**: Testcontainers running a plain `postgres:17` image, migrated with the real + `V1`/`V2` migrations from §3 plus a small hand-authored fixture dataset + (`fixture-schema.sql`/`fixture-data.sql`) covering: a known multi-hop co-star chain (to exercise the + bidirectional CTE end-to-end, including a deliberate case where the true path requires more than one + hop on each side), a tied weighted-rating case, and an ambiguous shared name. Fast and deterministic. +- **Controller tests**: `MockMvc`, request validation and `ProblemDetail` error-shape contracts. +- **CI**: GitHub Actions, matching `votee`'s existing workflow pattern - unit + integration tests against + the lightweight fixture only. +- **Load tests**: k6 (§8), run manually against the fully-seeded stack, not part of the CI gate. + +## 11. Open Items for Implementation + +- Scaffold the Maven project via [start.spring.io](https://start.spring.io/): Java 21, Spring Boot 4.1.0, + group `com.ludovictemgoua`, artifact `imdb`. All dependencies below are selectable directly on + Initializr - no post-generation pom edits needed: + + | Dependency (Initializr label) | Include? | Why | + |---|---|---| + | Spring Web | Yes | REST controllers | + | JDBC API | Yes | `NamedParameterJdbcTemplate` access - **not** Spring Data JDBC, see §3.1 (avoids reintroducing a repository/entity abstraction) | + | PostgreSQL Driver | Yes | Connects to `abanda/imdb-postgresql` | + | Flyway Migration | Yes | Runs the `V1`/`V2` migrations from §3 | + | Spring Data Redis | Yes | Cache-aside layer, §6 | + | Validation | Yes | `maxDegree` range / malformed-ID checks at the controller boundary | + | Spring Boot Actuator | Yes | Health, `/actuator/prometheus` | + | Prometheus | Yes | Micrometer -> Prometheus format, scraped by the `prometheus` compose service | + | Distributed Tracing | Yes | Span/trace IDs in logs - log<->trace correlation, §7 | + | OpenTelemetry | Yes | Publishes traces via OTLP to Tempo, pairs with Distributed Tracing | + | springdoc-openapi | Yes | Swagger UI | + | Testcontainers | Yes | Backs the integration-test plan, §10 | + | datasource-micrometer | No | Its Initializr `versionRange` is `[3.5.0.RELEASE, 4.1.0.M1)` - not yet ported to the Boot 4.1 line. The gap is covered anyway: Spring Boot auto-binds HikariCP connection-pool metrics via Actuator/Micrometer with no extra dependency, and the one query worth watching closely (the six-degrees CTE) already gets a hand-rolled `Timer` per §7. | + | Lombok | No | This monorepo uses Java records for value types (see `votee`), not Lombok-generated boilerplate | + | Docker Compose (dev-tool) | No | Conflicts with our hand-authored `docker-compose.yaml`, which already includes the app itself as a service | + | Zipkin | No | Redundant trace backend - traces already go via OpenTelemetry/OTLP to Tempo | + | otlp-metrics | No | Redundant metrics path - metrics already go via Prometheus pull-scrape | +- Write the multi-stage `Dockerfile` (Maven build stage -> JRE runtime stage) referenced by + `docker-compose.yaml`'s `imdb-service.build`. +- Author the actual Grafana dashboard JSON models under `observability/grafana/provisioning/dashboards/json/`. +- Author the k6 scripts and the sampled-actor CSV under `imdb/k6/`. +- Pick the concrete `minVotes` default for the weighted-rating formula from the real vote-count + distribution once the dataset is loaded (PDD §11). +- Tune `fanOutCap` and `sideCap` in §5.2 against real k6 results; both are exposed as configuration, not + hardcoded, specifically so this tuning doesn't require a code change. +- Decide the `co_star_edges` refresh cadence (PDD §11 open question) if this ever moves beyond a + single-import deployment. From 4752f46e3813b8893e93179840322fa1ea9b86ac Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sun, 5 Jul 2026 19:08:33 +0200 Subject: [PATCH 04/42] Added dependent services and configurations using docker-compose.yaml file for our application --- imdb/docker-compose.yaml | 211 ++++++++++++++++++ imdb/observability/alloy/config.alloy | 15 ++ .../provisioning/dashboards/dashboards.yml | 10 + .../provisioning/datasources/datasources.yml | 38 ++++ imdb/observability/prometheus/prometheus.yml | 21 ++ imdb/observability/tempo/tempo.yaml | 23 ++ 6 files changed, 318 insertions(+) create mode 100644 imdb/docker-compose.yaml create mode 100644 imdb/observability/alloy/config.alloy create mode 100644 imdb/observability/grafana/provisioning/dashboards/dashboards.yml create mode 100644 imdb/observability/grafana/provisioning/datasources/datasources.yml create mode 100644 imdb/observability/prometheus/prometheus.yml create mode 100644 imdb/observability/tempo/tempo.yaml diff --git a/imdb/docker-compose.yaml b/imdb/docker-compose.yaml new file mode 100644 index 0000000..08af9ec --- /dev/null +++ b/imdb/docker-compose.yaml @@ -0,0 +1,211 @@ +networks: + imdb-net: + name: imdb-net + +volumes: + imdb_data: + redis_data: + prometheus_data: + loki_data: + tempo_data: + grafana_data: + alloy_data: + +services: + # --------------------------------------------------------------------- + # Data stores + # --------------------------------------------------------------------- + + postgres: + image: abanda/imdb-postgresql:latest + container_name: imdb-postgres + ports: + - "5432:5432" + volumes: + - imdb_data:/var/lib/postgresql/data + environment: + # MINIMAL_DATASET is honored by upstream image tooling for a faster, + # smaller import while iterating locally; unset/false loads the full dataset. + MINIMAL_DATASET: "false" + healthcheck: + test: ["CMD-SHELL", "pg_isready -U imdb -d imdb"] + interval: 10s + timeout: 5s + retries: 12 + start_period: 40m # first-run TSV import can take 20-30 minutes + networks: + - imdb-net + + redis: + image: redis:7-alpine + container_name: imdb-redis + ports: + - "6379:6379" + volumes: + - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + networks: + - imdb-net + + # --------------------------------------------------------------------- + # Application (built once the Spring Boot project is scaffolded) + # --------------------------------------------------------------------- + + imdb-service: + build: + context: . + dockerfile: Dockerfile + container_name: imdb-service + ports: + - "8080:8080" + environment: + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/imdb + SPRING_DATASOURCE_USERNAME: imdb + SPRING_DATASOURCE_PASSWORD: password + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: "6379" + MANAGEMENT_OTLP_TRACING_ENDPOINT: http://tempo:4318/v1/traces + MANAGEMENT_TRACING_SAMPLING_PROBABILITY: "1.0" + BACON_PERSON_NAME: "Kevin Bacon" + SIX_DEGREES_MAX_DEPTH: "7" + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + networks: + - imdb-net + + # --------------------------------------------------------------------- + # Metrics + # --------------------------------------------------------------------- + + prometheus: + image: prom/prometheus:latest + container_name: imdb-prometheus + command: + - --config.file=/etc/prometheus/prometheus.yml + - --storage.tsdb.path=/prometheus + - --enable-feature=remote-write-receiver # accepts k6's experimental-prometheus-rw output + ports: + - "9090:9090" + volumes: + - ./observability/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro + - prometheus_data:/prometheus + networks: + - imdb-net + + postgres-exporter: + image: quay.io/prometheuscommunity/postgres-exporter:latest + container_name: imdb-postgres-exporter + environment: + DATA_SOURCE_NAME: "postgresql://imdb:password@postgres:5432/imdb?sslmode=disable" + ports: + - "9187:9187" + depends_on: + postgres: + condition: service_healthy + networks: + - imdb-net + + redis-exporter: + image: oliver006/redis_exporter:latest + container_name: imdb-redis-exporter + environment: + REDIS_ADDR: "redis://redis:6379" + ports: + - "9121:9121" + depends_on: + redis: + condition: service_healthy + networks: + - imdb-net + + # --------------------------------------------------------------------- + # Logs + # --------------------------------------------------------------------- + + loki: + image: grafana/loki:latest + container_name: imdb-loki + ports: + - "3100:3100" + volumes: + - loki_data:/loki + networks: + - imdb-net + + grafana-alloy: + image: grafana/alloy:latest + container_name: imdb-alloy + command: run --server.http.listen-addr=0.0.0.0:12345 --storage.path=/var/lib/alloy/data /etc/alloy/config.alloy + volumes: + - ./observability/alloy/config.alloy:/etc/alloy/config.alloy:ro + - alloy_data:/var/lib/alloy/data + - /var/run/docker.sock:/var/run/docker.sock:ro + ports: + - "12345:12345" + depends_on: + - loki + networks: + - imdb-net + + # --------------------------------------------------------------------- + # Traces + # --------------------------------------------------------------------- + + tempo: + image: grafana/tempo:latest + container_name: imdb-tempo + command: -config.file=/etc/tempo.yaml + volumes: + - ./observability/tempo/tempo.yaml:/etc/tempo.yaml:ro + - tempo_data:/var/tempo + ports: + - "3200:3200" # Tempo query API + - "4317:4317" # OTLP gRPC receiver + - "4318:4318" # OTLP HTTP receiver + networks: + - imdb-net + + # --------------------------------------------------------------------- + # Dashboards + # --------------------------------------------------------------------- + + grafana: + image: grafana/grafana:latest + container_name: imdb-grafana + ports: + - "3000:3000" + environment: + GF_AUTH_ANONYMOUS_ENABLED: "true" + GF_AUTH_ANONYMOUS_ORG_ROLE: Admin + GF_AUTH_DISABLE_LOGIN_FORM: "true" + volumes: + - grafana_data:/var/lib/grafana + - ./observability/grafana/provisioning:/etc/grafana/provisioning:ro + depends_on: + - prometheus + - loki + - tempo + networks: + - imdb-net + + # --------------------------------------------------------------------- + # Load testing (opt-in: `docker compose --profile load-test run k6 run /scripts/.js`) + # --------------------------------------------------------------------- + + k6: + image: grafana/k6:latest + container_name: imdb-k6 + profiles: ["load-test"] + environment: + K6_PROMETHEUS_RW_SERVER_URL: http://prometheus:9090/api/v1/write + volumes: + - ./k6:/scripts:ro + networks: + - imdb-net diff --git a/imdb/observability/alloy/config.alloy b/imdb/observability/alloy/config.alloy new file mode 100644 index 0000000..9dd2086 --- /dev/null +++ b/imdb/observability/alloy/config.alloy @@ -0,0 +1,15 @@ +discovery.docker "containers" { + host = "unix:///var/run/docker.sock" +} + +loki.source.docker "default" { + host = "unix:///var/run/docker.sock" + targets = discovery.docker.containers.targets + forward_to = [loki.write.default.receiver] +} + +loki.write "default" { + endpoint { + url = "http://loki:3100/loki/api/v1/push" + } +} diff --git a/imdb/observability/grafana/provisioning/dashboards/dashboards.yml b/imdb/observability/grafana/provisioning/dashboards/dashboards.yml new file mode 100644 index 0000000..1f04fa5 --- /dev/null +++ b/imdb/observability/grafana/provisioning/dashboards/dashboards.yml @@ -0,0 +1,10 @@ +apiVersion: 1 + +providers: + - name: imdb + orgId: 1 + folder: IMDb + type: file + updateIntervalSeconds: 30 + options: + path: /etc/grafana/provisioning/dashboards/json diff --git a/imdb/observability/grafana/provisioning/datasources/datasources.yml b/imdb/observability/grafana/provisioning/datasources/datasources.yml new file mode 100644 index 0000000..c0c8458 --- /dev/null +++ b/imdb/observability/grafana/provisioning/datasources/datasources.yml @@ -0,0 +1,38 @@ +apiVersion: 1 + +datasources: + - name: Prometheus + uid: prometheus + type: prometheus + access: proxy + url: http://prometheus:9090 + isDefault: true + jsonData: + exemplarTraceIdDestinations: + - name: trace_id + datasourceUid: tempo + + - name: Loki + uid: loki + type: loki + access: proxy + url: http://loki:3100 + jsonData: + derivedFields: + - datasourceUid: tempo + matcherRegex: 'trace_id=(\w+)' + name: TraceID + url: "$${__value.raw}" + + - name: Tempo + uid: tempo + type: tempo + access: proxy + url: http://tempo:3200 + jsonData: + tracesToLogsV2: + datasourceUid: loki + tracesToMetrics: + datasourceUid: prometheus + serviceMap: + datasourceUid: prometheus diff --git a/imdb/observability/prometheus/prometheus.yml b/imdb/observability/prometheus/prometheus.yml new file mode 100644 index 0000000..2a20d0c --- /dev/null +++ b/imdb/observability/prometheus/prometheus.yml @@ -0,0 +1,21 @@ +global: + scrape_interval: 15s + evaluation_interval: 15s + +scrape_configs: + - job_name: prometheus + static_configs: + - targets: ["localhost:9090"] + + - job_name: imdb-service + metrics_path: /actuator/prometheus + static_configs: + - targets: ["imdb-service:8080"] + + - job_name: postgres + static_configs: + - targets: ["postgres-exporter:9187"] + + - job_name: redis + static_configs: + - targets: ["redis-exporter:9121"] diff --git a/imdb/observability/tempo/tempo.yaml b/imdb/observability/tempo/tempo.yaml new file mode 100644 index 0000000..cc24899 --- /dev/null +++ b/imdb/observability/tempo/tempo.yaml @@ -0,0 +1,23 @@ +server: + http_listen_port: 3200 + +distributor: + receivers: + otlp: + protocols: + grpc: + endpoint: 0.0.0.0:4317 + http: + endpoint: 0.0.0.0:4318 + +storage: + trace: + backend: local + local: + path: /var/tempo/traces + wal: + path: /var/tempo/wal + +compactor: + compaction: + block_retention: 48h From 73d0f01fd4af115560f8e2c3e08cd0dcd73a0cd8 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sun, 5 Jul 2026 22:08:02 +0200 Subject: [PATCH 05/42] imdb: Generated spring boot starter application --- imdb/.gitattributes | 2 + imdb/.gitignore | 33 ++ imdb/.mvn/wrapper/maven-wrapper.properties | 3 + imdb/mvnw | 295 ++++++++++++++++++ imdb/mvnw.cmd | 189 +++++++++++ imdb/pom.xml | 142 +++++++++ .../ludovictemgoua/imdb/ImdbApplication.java | 13 + imdb/src/main/resources/application.yaml | 3 + .../imdb/ImdbApplicationTests.java | 15 + .../imdb/TestImdbApplication.java | 11 + .../imdb/TestcontainersConfiguration.java | 32 ++ 11 files changed, 738 insertions(+) create mode 100644 imdb/.gitattributes create mode 100644 imdb/.gitignore create mode 100644 imdb/.mvn/wrapper/maven-wrapper.properties create mode 100644 imdb/mvnw create mode 100644 imdb/mvnw.cmd create mode 100644 imdb/pom.xml create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/ImdbApplication.java create mode 100644 imdb/src/main/resources/application.yaml create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/ImdbApplicationTests.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/TestImdbApplication.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java diff --git a/imdb/.gitattributes b/imdb/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/imdb/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/imdb/.gitignore b/imdb/.gitignore new file mode 100644 index 0000000..667aaef --- /dev/null +++ b/imdb/.gitignore @@ -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/ diff --git a/imdb/.mvn/wrapper/maven-wrapper.properties b/imdb/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..216df05 --- /dev/null +++ b/imdb/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/imdb/mvnw b/imdb/mvnw new file mode 100644 index 0000000..bd8896b --- /dev/null +++ b/imdb/mvnw @@ -0,0 +1,295 @@ +#!/bin/sh +# ---------------------------------------------------------------------------- +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# ---------------------------------------------------------------------------- + +# ---------------------------------------------------------------------------- +# Apache Maven Wrapper startup batch script, version 3.3.4 +# +# Optional ENV vars +# ----------------- +# JAVA_HOME - location of a JDK home dir, required when download maven via java source +# MVNW_REPOURL - repo url base for downloading maven distribution +# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output +# ---------------------------------------------------------------------------- + +set -euf +[ "${MVNW_VERBOSE-}" != debug ] || set -x + +# OS specific support. +native_path() { printf %s\\n "$1"; } +case "$(uname)" in +CYGWIN* | MINGW*) + [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")" + native_path() { cygpath --path --windows "$1"; } + ;; +esac + +# set JAVACMD and JAVACCMD +set_java_home() { + # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched + if [ -n "${JAVA_HOME-}" ]; then + if [ -x "$JAVA_HOME/jre/sh/java" ]; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACCMD="$JAVA_HOME/jre/sh/javac" + else + JAVACMD="$JAVA_HOME/bin/java" + JAVACCMD="$JAVA_HOME/bin/javac" + + if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then + echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2 + echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2 + return 1 + fi + fi + else + JAVACMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v java + )" || : + JAVACCMD="$( + 'set' +e + 'unset' -f command 2>/dev/null + 'command' -v javac + )" || : + + if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then + echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2 + return 1 + fi + fi +} + +# hash string like Java String::hashCode +hash_string() { + str="${1:-}" h=0 + while [ -n "$str" ]; do + char="${str%"${str#?}"}" + h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296)) + str="${str#?}" + done + printf %x\\n $h +} + +verbose() { :; } +[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; } + +die() { + printf %s\\n "$1" >&2 + exit 1 +} + +trim() { + # MWRAPPER-139: + # Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds. + # Needed for removing poorly interpreted newline sequences when running in more + # exotic environments such as mingw bash on Windows. + printf "%s" "${1}" | tr -d '[:space:]' +} + +scriptDir="$(dirname "$0")" +scriptName="$(basename "$0")" + +# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties +while IFS="=" read -r key value; do + case "${key-}" in + distributionUrl) distributionUrl=$(trim "${value-}") ;; + distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;; + esac +done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties" +[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" + +case "${distributionUrl##*/}" in +maven-mvnd-*bin.*) + MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ + case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in + *AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;; + :Darwin*x86_64) distributionPlatform=darwin-amd64 ;; + :Darwin*arm64) distributionPlatform=darwin-aarch64 ;; + :Linux*x86_64*) distributionPlatform=linux-amd64 ;; + *) + echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2 + distributionPlatform=linux-amd64 + ;; + esac + distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip" + ;; +maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;; +*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;; +esac + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}" +distributionUrlName="${distributionUrl##*/}" +distributionUrlNameMain="${distributionUrlName%.*}" +distributionUrlNameMain="${distributionUrlNameMain%-bin}" +MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}" +MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")" + +exec_maven() { + unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || : + exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD" +} + +if [ -d "$MAVEN_HOME" ]; then + verbose "found existing MAVEN_HOME at $MAVEN_HOME" + exec_maven "$@" +fi + +case "${distributionUrl-}" in +*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;; +*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;; +esac + +# prepare tmp dir +if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then + clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; } + trap clean HUP INT TERM EXIT +else + die "cannot create temp dir" +fi + +mkdir -p -- "${MAVEN_HOME%/*}" + +# Download and Install Apache Maven +verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +verbose "Downloading from: $distributionUrl" +verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +# select .zip or .tar.gz +if ! command -v unzip >/dev/null; then + distributionUrl="${distributionUrl%.zip}.tar.gz" + distributionUrlName="${distributionUrl##*/}" +fi + +# verbose opt +__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR='' +[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v + +# normalize http auth +case "${MVNW_PASSWORD:+has-password}" in +'') MVNW_USERNAME='' MVNW_PASSWORD='' ;; +has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;; +esac + +if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then + verbose "Found wget ... using wget" + wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl" +elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then + verbose "Found curl ... using curl" + curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl" +elif set_java_home; then + verbose "Falling back to use Java to download" + javaSource="$TMP_DOWNLOAD_DIR/Downloader.java" + targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName" + cat >"$javaSource" <<-END + public class Downloader extends java.net.Authenticator + { + protected java.net.PasswordAuthentication getPasswordAuthentication() + { + return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() ); + } + public static void main( String[] args ) throws Exception + { + setDefault( new Downloader() ); + java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() ); + } + } + END + # For Cygwin/MinGW, switch paths to Windows format before running javac and java + verbose " - Compiling Downloader.java ..." + "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java" + verbose " - Running Downloader.java ..." + "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")" +fi + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +if [ -n "${distributionSha256Sum-}" ]; then + distributionSha256Result=false + if [ "$MVN_CMD" = mvnd.sh ]; then + echo "Checksum validation is not supported for maven-mvnd." >&2 + echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + elif command -v sha256sum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then + distributionSha256Result=true + fi + elif command -v shasum >/dev/null; then + if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then + distributionSha256Result=true + fi + else + echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2 + echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2 + exit 1 + fi + if [ $distributionSha256Result = false ]; then + echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2 + echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2 + exit 1 + fi +fi + +# unzip and move +if command -v unzip >/dev/null; then + unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip" +else + tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar" +fi + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +actualDistributionDir="" + +# First try the expected directory name (for regular distributions) +if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then + if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then + actualDistributionDir="$distributionUrlNameMain" + fi +fi + +# If not found, search for any directory with the Maven executable (for snapshots) +if [ -z "$actualDistributionDir" ]; then + # enable globbing to iterate over items + set +f + for dir in "$TMP_DOWNLOAD_DIR"/*; do + if [ -d "$dir" ]; then + if [ -f "$dir/bin/$MVN_CMD" ]; then + actualDistributionDir="$(basename "$dir")" + break + fi + fi + done + set -f +fi + +if [ -z "$actualDistributionDir" ]; then + verbose "Contents of $TMP_DOWNLOAD_DIR:" + verbose "$(ls -la "$TMP_DOWNLOAD_DIR")" + die "Could not find Maven distribution directory in extracted archive" +fi + +verbose "Found extracted Maven distribution directory: $actualDistributionDir" +printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url" +mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME" + +clean || : +exec_maven "$@" diff --git a/imdb/mvnw.cmd b/imdb/mvnw.cmd new file mode 100644 index 0000000..92450f9 --- /dev/null +++ b/imdb/mvnw.cmd @@ -0,0 +1,189 @@ +<# : batch portion +@REM ---------------------------------------------------------------------------- +@REM Licensed to the Apache Software Foundation (ASF) under one +@REM or more contributor license agreements. See the NOTICE file +@REM distributed with this work for additional information +@REM regarding copyright ownership. The ASF licenses this file +@REM to you under the Apache License, Version 2.0 (the +@REM "License"); you may not use this file except in compliance +@REM with the License. You may obtain a copy of the License at +@REM +@REM http://www.apache.org/licenses/LICENSE-2.0 +@REM +@REM Unless required by applicable law or agreed to in writing, +@REM software distributed under the License is distributed on an +@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +@REM KIND, either express or implied. See the License for the +@REM specific language governing permissions and limitations +@REM under the License. +@REM ---------------------------------------------------------------------------- + +@REM ---------------------------------------------------------------------------- +@REM Apache Maven Wrapper startup batch script, version 3.3.4 +@REM +@REM Optional ENV vars +@REM MVNW_REPOURL - repo url base for downloading maven distribution +@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven +@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output +@REM ---------------------------------------------------------------------------- + +@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) +@SET __MVNW_CMD__= +@SET __MVNW_ERROR__= +@SET __MVNW_PSMODULEP_SAVE=%PSModulePath% +@SET PSModulePath= +@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( + IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) +) +@SET PSModulePath=%__MVNW_PSMODULEP_SAVE% +@SET __MVNW_PSMODULEP_SAVE= +@SET __MVNW_ARG0_NAME__= +@SET MVNW_USERNAME= +@SET MVNW_PASSWORD= +@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) +@echo Cannot start maven from wrapper >&2 && exit /b 1 +@GOTO :EOF +: end batch / begin powershell #> + +$ErrorActionPreference = "Stop" +if ($env:MVNW_VERBOSE -eq "true") { + $VerbosePreference = "Continue" +} + +# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties +$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl +if (!$distributionUrl) { + Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" +} + +switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { + "maven-mvnd-*" { + $USE_MVND = $true + $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" + $MVN_CMD = "mvnd.cmd" + break + } + default { + $USE_MVND = $false + $MVN_CMD = $script -replace '^mvnw','mvn' + break + } +} + +# apply MVNW_REPOURL and calculate MAVEN_HOME +# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ +if ($env:MVNW_REPOURL) { + $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } + $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" +} +$distributionUrlName = $distributionUrl -replace '^.*/','' +$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' + +$MAVEN_M2_PATH = "$HOME/.m2" +if ($env:MAVEN_USER_HOME) { + $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" +} + +if (-not (Test-Path -Path $MAVEN_M2_PATH)) { + New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null +} + +$MAVEN_WRAPPER_DISTS = $null +if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { + $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" +} else { + $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" +} + +$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" +$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' +$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" + +if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { + Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" + Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" + exit $? +} + +if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { + Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" +} + +# prepare tmp dir +$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile +$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" +$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null +trap { + if ($TMP_DOWNLOAD_DIR.Exists) { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } + } +} + +New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null + +# Download and Install Apache Maven +Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." +Write-Verbose "Downloading from: $distributionUrl" +Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" + +$webclient = New-Object System.Net.WebClient +if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { + $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) +} +[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 +$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null + +# If specified, validate the SHA-256 sum of the Maven distribution zip file +$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum +if ($distributionSha256Sum) { + if ($USE_MVND) { + Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." + } + Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash + if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { + Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." + } +} + +# unzip and move +Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null + +# Find the actual extracted directory name (handles snapshots where filename != directory name) +$actualDistributionDir = "" + +# First try the expected directory name (for regular distributions) +$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" +$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" +if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { + $actualDistributionDir = $distributionUrlNameMain +} + +# If not found, search for any directory with the Maven executable (for snapshots) +if (!$actualDistributionDir) { + Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { + $testPath = Join-Path $_.FullName "bin/$MVN_CMD" + if (Test-Path -Path $testPath -PathType Leaf) { + $actualDistributionDir = $_.Name + } + } +} + +if (!$actualDistributionDir) { + Write-Error "Could not find Maven distribution directory in extracted archive" +} + +Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" +Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null +try { + Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null +} catch { + if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { + Write-Error "fail to move MAVEN_HOME" + } +} finally { + try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } + catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } +} + +Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" diff --git a/imdb/pom.xml b/imdb/pom.xml new file mode 100644 index 0000000..a950123 --- /dev/null +++ b/imdb/pom.xml @@ -0,0 +1,142 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 4.1.0 + + + com.ludovictemgoua + imdb + 0.0.1-SNAPSHOT + + + + + + + + + + + + + + + + + 21 + + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter-flyway + + + org.springframework.boot + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-opentelemetry + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-webmvc + + + org.flywaydb + flyway-database-postgresql + + + + io.micrometer + micrometer-registry-prometheus + runtime + + + org.postgresql + postgresql + runtime + + + org.springframework.boot + spring-boot-starter-actuator-test + test + + + org.springframework.boot + spring-boot-starter-data-redis-test + test + + + org.springframework.boot + spring-boot-starter-flyway-test + test + + + org.springframework.boot + spring-boot-starter-jdbc-test + test + + + org.springframework.boot + spring-boot-starter-opentelemetry-test + test + + + org.springframework.boot + spring-boot-starter-validation-test + test + + + org.springframework.boot + spring-boot-starter-webmvc-test + test + + + org.springframework.boot + spring-boot-testcontainers + test + + + org.testcontainers + testcontainers-grafana + test + + + org.testcontainers + testcontainers-junit-jupiter + test + + + org.testcontainers + testcontainers-postgresql + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/ImdbApplication.java b/imdb/src/main/java/com/ludovictemgoua/imdb/ImdbApplication.java new file mode 100644 index 0000000..42a4579 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/ImdbApplication.java @@ -0,0 +1,13 @@ +package com.ludovictemgoua.imdb; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class ImdbApplication { + + public static void main(String[] args) { + SpringApplication.run(ImdbApplication.class, args); + } + +} diff --git a/imdb/src/main/resources/application.yaml b/imdb/src/main/resources/application.yaml new file mode 100644 index 0000000..d7a251e --- /dev/null +++ b/imdb/src/main/resources/application.yaml @@ -0,0 +1,3 @@ +spring: + application: + name: imdb diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/ImdbApplicationTests.java b/imdb/src/test/java/com/ludovictemgoua/imdb/ImdbApplicationTests.java new file mode 100644 index 0000000..b5d750f --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/ImdbApplicationTests.java @@ -0,0 +1,15 @@ +package com.ludovictemgoua.imdb; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +class ImdbApplicationTests { + + @Test + void contextLoads() { + } + +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/TestImdbApplication.java b/imdb/src/test/java/com/ludovictemgoua/imdb/TestImdbApplication.java new file mode 100644 index 0000000..91718f0 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/TestImdbApplication.java @@ -0,0 +1,11 @@ +package com.ludovictemgoua.imdb; + +import org.springframework.boot.SpringApplication; + +public class TestImdbApplication { + + public static void main(String[] args) { + SpringApplication.from(ImdbApplication::main).with(TestcontainersConfiguration.class).run(args); + } + +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java new file mode 100644 index 0000000..6b71356 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java @@ -0,0 +1,32 @@ +package com.ludovictemgoua.imdb; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.grafana.LgtmStackContainer; +import org.testcontainers.postgresql.PostgreSQLContainer; +import org.testcontainers.utility.DockerImageName; + +@TestConfiguration(proxyBeanMethods = false) +class TestcontainersConfiguration { + + @Bean + @ServiceConnection + LgtmStackContainer grafanaLgtmContainer() { + return new LgtmStackContainer(DockerImageName.parse("grafana/otel-lgtm:latest")); + } + + @Bean + @ServiceConnection + PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); + } + + @Bean + @ServiceConnection(name = "redis") + GenericContainer redisContainer() { + return new GenericContainer<>(DockerImageName.parse("redis:latest")).withExposedPorts(6379); + } + +} From e80491d50d9f90d8ec2fea6bad9f9ad682373834 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 6 Jul 2026 04:21:23 +0200 Subject: [PATCH 06/42] Updated LLD doc as we will be using the onion architecture during implementation --- imdb/docker-compose.yaml | 2 +- imdb/docs/low-level-design.md | 468 +++++++++++++++++++++++++--------- imdb/docs/product-design.md | 2 + 3 files changed, 352 insertions(+), 120 deletions(-) diff --git a/imdb/docker-compose.yaml b/imdb/docker-compose.yaml index 08af9ec..12d3db9 100644 --- a/imdb/docker-compose.yaml +++ b/imdb/docker-compose.yaml @@ -68,7 +68,7 @@ services: SPRING_DATASOURCE_PASSWORD: password SPRING_DATA_REDIS_HOST: redis SPRING_DATA_REDIS_PORT: "6379" - MANAGEMENT_OTLP_TRACING_ENDPOINT: http://tempo:4318/v1/traces + MANAGEMENT_OPENTELEMETRY_TRACING_EXPORT_OTLP_ENDPOINT: http://tempo:4318/v1/traces MANAGEMENT_TRACING_SAMPLING_PROBABILITY: "1.0" BACON_PERSON_NAME: "Kevin Bacon" SIX_DEGREES_MAX_DEPTH: "7" diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md index c9e19ef..15dda4d 100644 --- a/imdb/docs/low-level-design.md +++ b/imdb/docs/low-level-design.md @@ -4,20 +4,89 @@ |---|---| | Author | Ludovic Temgoua Abanda | | Status | Draft | -| Date | 2026-07-05 | +| Date | 2026-07-06 | | Related docs | `imdb/docs/product-design.md` (PDD, approved), `imdb/docs/REQUIREMENTS.md` | | Data source | [`abanda/imdb-postgresql`](https://github.com/icemc/imdb-postgresql) | ## 1. Purpose and Scope -The PDD defines what is being built and why. This document defines how: schema additions on top of the -seeded database, endpoint contracts, the bidirectional-CTE SQL for Six Degrees, the caching strategy, -docker-compose topology, observability wiring, and the test plan. This is a design reference for manual -implementation, not generated production code - the Maven project itself (`pom.xml`, `src/`) does not yet -exist in this repository; scaffolding it via [start.spring.io](https://start.spring.io/) is the first -implementation step once this document is approved (see §11). +The PDD defines what is being built and why. This document defines how: the onion-layered package +structure, schema additions on top of the seeded database, endpoint contracts, the bidirectional-CTE SQL +for Six Degrees, the caching strategy, docker-compose topology, observability wiring, and the test plan. +The Maven project has been scaffolded and the core layers (§2) are implemented and compiling; what +remains is tracked in §11 (dashboards, k6 scripts, the Dockerfile, and a handful of tuning decisions that +need real data/load-test results to answer responsibly). -## 2. Maven Module Layout (target state) +## 2. Architecture & Module Layout + +### 2.1 Onion layers and the dependency rule + +The initial pass at this codebase used a flat package structure (`repository`, `service`, `web`) where +every service directly `new`'d or `@Autowired` concrete JDBC/Redis classes. That worked, but it violated +the Dependency Inversion Principle badly enough to matter: nothing could be tested without a real +Postgres/Redis behind it, and swapping either one - say, to evaluate the Neo4j alternative from PDD §9 - +would have meant editing the use-case classes themselves. This section replaces that with a proper onion +architecture. + +**Layers, outermost to innermost**: `presentation` → `infrastructure` → `application` → `domain`, plus a +standalone `utils` layer with no dependencies at all. The dependency rule is enforced by import direction +alone (no build-tool module boundaries yet - see the open item in §11): + +| Layer | May import | Contains | +|---|---|---| +| `presentation` | `application`, `infrastructure`, `domain`, `utils` | Controllers, request validation, `ApiExceptionHandler` | +| `infrastructure` | `application`, `domain`, `utils` | JDBC repository implementations, Redis caching decorators, Spring `@Configuration` | +| `application` | `domain`, `utils` | Use-case interfaces + implementations, use-case-specific result types | +| `domain` | *(nothing)* | Entities/value objects, repository **interfaces**, domain exceptions | +| `utils` | *(nothing)* | `ImdbIds` - pure, framework-free helpers | + +Never: `domain` importing `application`/`infrastructure`; `application` importing `infrastructure`. The +second rule is the one that actually matters day to day - application code calls domain interfaces only, +and Spring's IoC container wires in the concrete infrastructure bean at runtime without a single +`application`-package `import` ever naming a JDBC or Redis class. + +**Where interfaces earn their keep**: every `domain.repository` interface has exactly one JDBC +implementation today, so on its own that's DIP for its own sake. The payoff shows up in `application`, +where every top-level use case a controller depends on is *also* an interface +(`TitleSearchUseCase`, `TitleDetailUseCase`, `TopRatedUseCase`, `SixDegreesUseCase`), each with a plain +`*Impl` and - where caching applies - an `infrastructure.cache` decorator implementing the same +interface, marked `@Primary`: + +``` +TitleSearchUseCase (interface, application) + ├─ TitleSearchUseCaseImpl (application) - plain orchestration, no caching + └─ CachingTitleSearchUseCase (infrastructure) - @Primary, @Cacheable, delegates to the Impl above +``` + +A controller depends on `TitleSearchUseCase` and never learns which one it got. Swapping cache +technology, or removing caching entirely, is a change to `infrastructure.cache` alone. Swapping Postgres +for something else is a new `infrastructure.persistence` class implementing the same `domain.repository` +interface - `application` and `presentation` are untouched either way. `PersonResolutionUseCase` is the +one exception: it's an internal collaborator used only by `SixDegreesUseCaseImpl`, never injected into a +controller or wrapped by a decorator, so it stays a concrete class - not every class needs an interface, +only the ones that are an actual seam. + +**Where caching attaches, and why it isn't uniform**: `CachingTitleSearchUseCase`, +`CachingTitleDetailUseCase`, and `CachingTopRatedUseCase` decorate the **use-case** interfaces. +`CachingCoStarGraphRepository` decorates the **repository** interface instead, one layer further in. The +reason is the shape of the work each one does: `TitleDetailUseCase.getDetail` fans out to five repository +calls and assembles one `TitleDetail` - caching the assembled result in one entry (matching the four +regions in §6) is both truer to the original design and cheaper than five separate repository-level cache +entries per title. `SixDegreesUseCase.compute`, on the other hand, takes raw query strings that might be +names needing disambiguation and a `maxDegree` that varies per request - a poor, fragile cache key. +`CoStarGraphRepository.findShortestPath(int, int)`, one level in, takes two clean integer ids and returns +the *true* shortest distance independent of any of that - exactly the key described in §6. This is also +why the domain interface returns a clean `GraphPath`, not the bidirectional search's raw forward/backward +arrays: see §5.2 for what that cleanup actually removed. + +**A caching bug that no longer needs remembering**: the original design's `DistanceCache` component +existed solely to work around a Spring AOP pitfall - `@Cacheable` uses a proxy, and a method calling +another method on `this` bypasses that proxy silently. Now that every cached method lives on a decorator +that is structurally a *different bean* from the thing it wraps, that failure mode isn't possible by +construction. Nobody has to remember not to call a cached method from within its own class, because there +is no such call anywhere in this codebase anymore. + +### 2.2 Package layout (current state) ``` imdb/ @@ -35,9 +104,9 @@ imdb/ grafana/provisioning/ datasources/datasources.yml dashboards/dashboards.yml - dashboards/json/ # dashboard JSON models, authored during implementation + dashboards/json/ # dashboard JSON models, still to author - see §11 k6/ - search.js + search.js # still to author - see §11 title-detail.js top-rated.js six-degrees.js @@ -46,59 +115,76 @@ imdb/ main/ java/com/ludovictemgoua/imdb/ ImdbApplication.java - config/ - CacheConfig.java - JdbcConfig.java - OpenApiConfig.java - web/ - TitleController.java - GenreController.java - PersonController.java - dto/ + utils/ + ImdbIds.java + domain/ + model/ TitleSummary.java + TitleCore.java TitleDetail.java RatingView.java CastMember.java CreditedPerson.java GenreTopRatedItem.java - SixDegreesResult.java + SharedTitle.java PersonCandidate.java - service/ - TitleSearchService.java - TitleDetailService.java - TopRatedService.java - PersonResolutionService.java - SixDegreesService.java - repository/ - TitleRepository.java - PersonRepository.java - CoStarGraphRepository.java - graph/ - BidirectionalPathResult.java - PathStitcher.java - error/ + PagedResult.java + GraphPath.java + PersonResolution.java + repository/ + TitleRepository.java # interface + PersonRepository.java # interface + CoStarGraphRepository.java # interface + exception/ + NotFoundException.java + application/ + TitleSearchUseCase.java # interface + TitleSearchUseCaseImpl.java + TitleDetailUseCase.java # interface + TitleDetailUseCaseImpl.java + TopRatedUseCase.java # interface + TopRatedUseCaseImpl.java + SixDegreesUseCase.java # interface + SixDegreesUseCaseImpl.java + PersonResolutionUseCase.java # concrete - internal collaborator, not a public seam + PersonRef.java + PathStep.java + SixDegreesResult.java + SixDegreesOutcome.java + infrastructure/ + persistence/ + JdbcTitleRepository.java + JdbcPersonRepository.java + JdbcCoStarGraphRepository.java + PathStitcher.java # package-private, JdbcCoStarGraphRepository-only + cache/ + CachingTitleSearchUseCase.java + CachingTitleDetailUseCase.java + CachingTopRatedUseCase.java + CachingCoStarGraphRepository.java + CacheConfig.java + presentation/ + TitleController.java + GenreController.java + PersonController.java ApiExceptionHandler.java - NotFoundException.java - AmbiguousPersonException.java resources/ - application.yml + application.yaml db/migration/ + V0__base_schema.sql V1__extensions_and_search_indexes.sql V2__co_star_edges_materialized_view.sql test/ java/com/ludovictemgoua/imdb/ - web/ (controller tests, MockMvc) - service/ (unit tests, mocked repositories) - integration/ (Testcontainers + fixture dataset) + (unit tests against domain interfaces, controller tests, Testcontainers integration tests - §10) resources/ fixtures/ - fixture-schema.sql fixture-data.sql ``` -`application.yml`, not `.properties`: the config surface is more nested than a typical CRUD app - -`management.metrics.*`, `management.tracing.*`, and `management.otlp.*` (§7) sit several levels deep -alongside a custom `six-degrees.*` group (§5/§6), and YAML's multi-document `---` profiles let the +`application.yaml`, not `.properties`: the config surface is more nested than a typical CRUD app - +`management.metrics.*`, `management.tracing.*`, and `management.opentelemetry.*` (§7) sit several levels +deep alongside a custom `six-degrees.*` group (§5/§6), and YAML's multi-document `---` profiles let the Testcontainers-backed integration tests (§10) override just the datasource block against the fixture container instead of `docker-compose.yaml`'s Postgres, without duplicating everything else. @@ -111,7 +197,12 @@ for genres, a Bayesian weighted-rating computation, and a recursive CTE for grap benefit from Hibernate's object-relational mapping or dirty-checking - there is no object graph being mutated, only read projections. Introducing JPA here would mean fighting it (native `@Query` everywhere) for zero benefit. The design instead uses Spring's `NamedParameterJdbcTemplate` with explicit `RowMapper`s -throughout, and Flyway for the two migrations below - one data-access style, not two. +throughout, and Flyway for the migrations below - one data-access style, not two. + +This is orthogonal to (and compatible with) the onion architecture in §2: `NamedParameterJdbcTemplate` is +an implementation detail entirely confined to `infrastructure.persistence`. Nothing in `domain` or +`application` knows JDBC exists - they see only the `TitleRepository`/`PersonRepository`/ +`CoStarGraphRepository` interfaces in `domain.repository`. ### 3.2 Migration V1: extensions and search indexes @@ -125,7 +216,7 @@ CREATE INDEX idx_title_basics_original_title_trgm ON title_basics USING gin (original_title gin_trgm_ops); CREATE INDEX idx_title_basics_genres - ON title_basics USING gin (genres); + ON title_basics USING gin ((genres::text[])); CREATE INDEX idx_title_ratings_rank ON title_ratings (average_rating DESC, num_votes DESC); @@ -138,6 +229,14 @@ CREATE INDEX idx_name_basics_primary_name_trgm ON name_basics USING gin (primary_name gin_trgm_ops); ``` +The `genres` index is built on the **expression** `(genres::text[])`, not the bare column. Production's +`genres` is a Postgres `GENRE` enum array, but the V0 test fixture (§3.4) simplifies it to plain +`TEXT[]`. Casting to `text[]` in the top-rated query (§4.3) lets one query run unmodified against both +schemas - but Postgres only matches a query's cast expression against an index built on that *same* +expression, not against a plain index on the uncast column. Indexing `(genres::text[])` directly (a +no-op cast in the test fixture, a real enum-to-text cast in production) keeps the index usable in both +places instead of silently falling back to a sequential scan in production. + ### 3.3 Migration V2: the co-star edge view The recursive CTE in §5 needs to expand "who has this person co-starred with" on every hop. Doing that @@ -167,9 +266,83 @@ path, instead of a `UNION ALL` on every hop of the recursive CTE. dataset import completes (there is no write path afterward - see PDD §11's open question on this). A `REFRESH ... CONCURRENTLY` requires the unique index above, which is already in place. -### 3.4 ID translation at the boundary +### 3.4 Migration V0: base schema for local/test parity (runs *before* V1, documented last) + +A gap surfaced while working out the test setup (§10): `V1`/`V2` above only add indexes and a view *on +top of* the seven base tables (`name_basics`, `title_basics`, `title_ratings`, `title_crew`, +`title_principals`, plus the two unused ones). Those base tables are created by the upstream Python +loader baked into `abanda/imdb-postgresql`, not by anything in this project - which is fine for +`docker-compose.yaml`'s Postgres, but a freshly-started Testcontainers `postgres:17` (used by the +integration tests and by the `TestcontainersConfiguration` Spring Initializr already generated) has none +of these tables, and `V1` would fail immediately trying to index them. + +The fix is a migration numbered `V0` - Flyway runs migrations in version order regardless of when they +were authored, so `V0__base_schema.sql` runs before `V1` even though it's documented after it here - that +creates the base tables **idempotently**: + +```sql +CREATE TABLE IF NOT EXISTS name_basics ( + nconst INTEGER PRIMARY KEY, + primary_name TEXT NOT NULL, + birth_year INTEGER, + death_year INTEGER, + primary_profession TEXT[], + known_for_titles INTEGER[] +); + +CREATE TABLE IF NOT EXISTS title_basics ( + tconst INTEGER PRIMARY KEY, + title_type TEXT NOT NULL, + primary_title TEXT NOT NULL, + original_title TEXT NOT NULL, + is_adult BOOLEAN NOT NULL DEFAULT FALSE, + start_year INTEGER, + end_year INTEGER, + runtime_minutes INTEGER, + genres TEXT[] +); + +CREATE TABLE IF NOT EXISTS title_ratings ( + tconst INTEGER PRIMARY KEY REFERENCES title_basics (tconst), + average_rating NUMERIC NOT NULL, + num_votes INTEGER NOT NULL +); + +CREATE TABLE IF NOT EXISTS title_crew ( + tconst INTEGER PRIMARY KEY REFERENCES title_basics (tconst), + directors INTEGER[], + writers INTEGER[] +); + +CREATE TABLE IF NOT EXISTS title_principals ( + tconst INTEGER NOT NULL REFERENCES title_basics (tconst), + ordering INTEGER NOT NULL, + nconst INTEGER NOT NULL REFERENCES name_basics (nconst), + category TEXT NOT NULL, + job TEXT, + characters TEXT[], + PRIMARY KEY (tconst, ordering) +); +``` + +Two deliberate simplifications versus the real schema, both safe because of how `IF NOT EXISTS` behaves: -`tconst`/`nconst` are stored as plain `INTEGER`. The API never exposes these directly: +- **Enum columns become `TEXT`/`TEXT[]`** (`title_type`, `genres`, `category`) instead of the real + Postgres `ENUM` types. Our own queries only ever compare these as strings/arrays, so behavior is + identical for anything this project does; only faithfully replicating the upstream loader's exact enum + constraints would need the real types, which isn't a goal here. +- **Foreign keys are always enforced here**, whereas the real loader's own comments note its + `add_references` step isn't consistently applied (PDD §11). Harmless for fixture data we control. +- Against `docker-compose.yaml`'s `abanda/imdb-postgresql` Postgres, every table already exists with the + real (enum-based) schema, so every `CREATE TABLE IF NOT EXISTS` above is a no-op - `V0` only ever does + real work against a blank Testcontainers instance. + +### 3.5 ID translation at the boundary + +`tconst`/`nconst` are stored as plain `INTEGER`. The API never exposes these directly. `ImdbIds` lives in +the standalone `utils` layer (§2.1) - pure string/int parsing, no dependency on anything else in the +codebase, usable from `infrastructure` (mapping JDBC rows) and `application` (formatting ids into result +records) alike: ```java public final class ImdbIds { @@ -185,7 +358,7 @@ public final class ImdbIds { ``` A malformed ID (wrong prefix, non-numeric suffix) is a `400` at the controller boundary via a -`@RequestParam`/`@PathVariable` converter, before it ever reaches a service or query. +`@RequestParam`/`@PathVariable` converter, before it ever reaches a use case or query. ## 4. Endpoint Specifications @@ -203,7 +376,9 @@ LIMIT :size OFFSET :offset; ``` (`%` is `pg_trgm`'s similarity operator, index-backed by the GIN indexes in §3.2.) Response: a -`Page` (`id`, `primaryTitle`, `originalTitle`, `titleType`, `startYear`, `endYear`). +`PagedResult` (`domain.model` - a small hand-rolled pagination wrapper, not Spring Data's +`Page`, consistent with §3.1's decision to keep Spring Data out of this codebase entirely) with `id`, +`primaryTitle`, `originalTitle`, `titleType`, `startYear`, `endYear` per item. ### 4.2 `GET /api/v1/titles/{titleId}` @@ -230,7 +405,8 @@ total count), composed into one `TitleDetail`: } ``` -`404` (via `NotFoundException` -> `ProblemDetail`) if `tconst` doesn't exist in `title_basics`. +`404` (via `domain.exception.NotFoundException` -> `ProblemDetail`, thrown by `TitleDetailUseCaseImpl` and +mapped by `presentation.ApiExceptionHandler`) if `tconst` doesn't exist in `title_basics`. ### 4.3 `GET /api/v1/genres/{genre}/top-rated?limit=&minVotes=` @@ -242,7 +418,7 @@ WITH pool AS ( FROM title_basics tb JOIN title_ratings tr ON tr.tconst = tb.tconst WHERE tb.title_type = 'movie' - AND tb.genres @> ARRAY[:genre]::genre[] + AND tb.genres::text[] @> ARRAY[:genre]::text[] AND tr.num_votes >= :minVotes ), stats AS ( @@ -296,7 +472,16 @@ thousands of co-stars). Meeting in the middle from both ends roughly squares dow to expand `⌈7/2⌉ = 4` hops. See PDD §9 for the full comparison against precomputed BFS, in-memory BFS, and Pruned Landmark Labeling. -### 5.2 The query +### 5.2 The query, and where it lives + +The bidirectional CTE below is entirely private to `infrastructure.persistence.JdbcCoStarGraphRepository`. +The `domain.repository.CoStarGraphRepository` interface it implements exposes exactly one method - +`Optional findShortestPath(int personA, int personB)` - where `GraphPath(degree, personIds)` +is already fully resolved into a single ordered chain. Nothing above the JDBC implementation ever sees +"forward path" or "backward path"; that split is an artifact of *this* algorithm, not a domain concept. +A future `Neo4jCoStarGraphRepository` (PDD §9's documented alternative) would implement the same interface +with a Cypher `shortestPath` call and no forward/backward anything, and nothing in `application` or +`presentation` would need to change. ```sql WITH RECURSIVE forward(person, depth, path) AS ( @@ -340,47 +525,63 @@ LIMIT 1; - `:sideCap` = 4 (fixed at `⌈7/2⌉`) and `:absoluteMaxDegree` = 7, both independent of the caller's requested `maxDegree` - see caching rationale in §6. The explicit `WHERE` matters: with `sideCap=4` on each side, the two CTEs can meet at combined depth 8, one more than the product's absolute cap. Without - this filter that would surface as a spurious "degree 8" answer; with it, no matching row means the - service layer cleanly reports "no path found within 7 degrees" - a plain empty result, not a value that - needs post-hoc clipping. + this filter that would surface as a spurious "degree 8" answer; with it, no matching row means + `findShortestPath` cleanly returns `Optional.empty()` - a plain empty result, not a value that needs + post-hoc clipping. - `:fanOutCap` (e.g. 200) bounds how many neighbors a single hub node contributes per hop. This is an explicit, documented approximation: if a node's true shortest-path edge falls outside its top-200 neighbors by `person_b` ordering, that path is missed. This is the practical trade-off that makes the hub-blowup problem tractable in plain SQL; it is a config knob (`six-degrees.fan-out-cap`), not a hidden magic number, so it can be tuned or disabled (`LIMIT NULL`-equivalent) if load testing shows it's overly aggressive. -- `statement_timeout` is set per-query (e.g. `SET LOCAL statement_timeout = '2000ms'`) as a last-resort - circuit breaker on top of the two caps above. -- The application resolves the winning `forward_path`/`backward_path` into a single displayed path by - reversing `backward_path` and concatenating, dropping the duplicated meeting node - this stitching - happens in `PathStitcher`, not in SQL. -- `personA == personB` is special-cased in `SixDegreesService` to return degree `0` without running the - query at all. +- A query timeout is set directly on the underlying `JdbcTemplate` inside `JdbcCoStarGraphRepository`'s + constructor (no declarative `spring.jdbc.template.query-timeout` property exists in Boot 4.1 - checked + against the reference docs directly) as a last-resort circuit breaker on top of the two caps above. +- The raw query result (`forward_path`/`backward_path` as parallel int arrays) is mapped to a + package-private `JdbcCoStarGraphRepository.RawMatch` record, then collapsed by the package-private + `PathStitcher.stitch(...)` (same package, same file neighborhood) into the `GraphPath` the interface + actually returns - reversing `backward_path` and concatenating, dropping the duplicated meeting node. + Both types are invisible outside `infrastructure.persistence`. +- `personA == personB` is special-cased in `SixDegreesUseCaseImpl` to return degree `0` without calling + the repository at all. ### 5.3 Person resolution -`PersonResolutionService` resolves a `name` query against `name_basics` via the trigram index from §3.2. -Exactly one strong match (similarity above a threshold and no close runner-up) proceeds directly; multiple -plausible matches return the disambiguation payload from §4.4, including `birthYear` and a couple of -`knownForTitles` entries per candidate so a human can tell "Michael J. Fox" from another same-named person -at a glance. +`PersonResolutionUseCase` (application layer, an internal collaborator of `SixDegreesUseCaseImpl` - see +§2.1) resolves a `name` query against `name_basics` via the trigram index from §3.2, through the +`domain.repository.PersonRepository` interface. Exactly one strong match (similarity above a threshold +and no close runner-up) proceeds directly; multiple plausible matches return the disambiguation payload +from §4.4, including `birthYear` and a couple of `knownForTitles` entries per candidate so a human can +tell "Michael J. Fox" from another same-named person at a glance. The result is the sealed +`domain.model.PersonResolution` (`Resolved` / `Ambiguous` / `NotFound`), matched exhaustively via a Java +21 `switch` in `SixDegreesUseCaseImpl`. ## 6. Caching Strategy -Redis, cache-aside, via Spring's `@Cacheable`/`CacheManager`, one cache region per endpoint: +Redis, cache-aside, via Spring's `@Cacheable`/`CacheManager` - but unlike a typical Spring tutorial, the +`@Cacheable` annotations never sit on the same classes that contain business logic. Per §2.1, caching is +implemented entirely as `infrastructure.cache` decorators around `application`-layer use-case interfaces +(three of the four regions) or a `domain.repository` interface (the fourth): -| Cache | Key | TTL | Notes | -|---|---|---|---| -| `title-search` | `title, page, size` | 24h | Small enough result sets that full-parameter keying is fine | -| `title-detail` | `titleId` | 24h | Highest hit-rate cache; title detail is the most repeatable lookup | -| `top-rated` | `genre, limit, minVotes` | 24h | | -| `six-degrees` | `min(personA,personB):max(personA,personB)` (**not** including `maxDegree`) | 24h | Stores the true shortest distance up to the absolute 7-degree cap; a request with a smaller `maxDegree` is served from the same cache entry and simply reports "beyond requested max" without recomputation (PDD §9) | +| Cache | Decorator | Key | TTL | Notes | +|---|---|---|---|---| +| `title-search` | `CachingTitleSearchUseCase` | `query, page, size` | 24h | Small enough result sets that full-parameter keying is fine | +| `title-detail` | `CachingTitleDetailUseCase` | `titleId` | 24h | One entry for the fully-assembled `TitleDetail`, even though the use case fans out to five repository calls to build it | +| `top-rated` | `CachingTopRatedUseCase` | `genre, limit, minVotes` | 24h | | +| `six-degrees` | `CachingCoStarGraphRepository` | `min(personA,personB)-max(personA,personB)` (**not** including `maxDegree`) | 24h | Stores the true shortest distance up to the absolute 7-degree cap; a request with a smaller `maxDegree` is served from the same cache entry and simply reports "beyond requested max" without recomputation (PDD §9). Cached at the repository level, not the use-case level - see §2.1 for why this one region breaks the pattern of the other three. | All TTLs are long because the underlying dataset only changes when the Docker image is reloaded - there is no write path invalidating these entries mid-flight. A full `FLUSHDB` on redeploy is the accepted invalidation strategy, documented rather than automated, since there's no signal in the running system that would tell it the data changed underneath it. +Each decorator is a Spring bean implementing the same interface as its plain counterpart, annotated +`@Primary` so it's what gets autowired everywhere the interface is requested; its constructor takes the +*concrete* plain implementation class (e.g. `CachingTitleSearchUseCase(TitleSearchUseCaseImpl delegate)`), +which is the one place `infrastructure` code names a specific implementation class rather than an +interface - unavoidable, since something has to construct the delegate unambiguously, and it's a +same-layer (`infrastructure` → `infrastructure`, effectively) reference, not a boundary violation. + **Load-test interaction** (carried over from the PDD discussion): the `six-degrees` k6 script must draw a different, pre-sampled person pair per iteration specifically so it exercises the bidirectional CTE instead of just measuring a warm Redis round-trip after the first request - see §8. @@ -389,11 +590,14 @@ instead of just measuring a warm Redis round-trip after the first request - see - **Metrics**: `micrometer-registry-prometheus`, default HTTP/JVM metrics plus custom ones: a `Timer` per endpoint's DB-query phase (so the six-degrees CTE's latency is visible as its own series, separate from - total request latency), and `Counter`s for cache hit/miss per cache region. -- **Tracing**: `micrometer-tracing-bridge-otel` + OTLP exporter to Tempo - (`management.otlp.tracing.endpoint=http://tempo:4318/v1/traces`, matching `docker-compose.yaml`). - `management.tracing.sampling.probability=1.0` for this exercise (full sampling; would be tuned down in - a real production deployment under real traffic volume). + total request latency), and `Counter`s for cache hit/miss per cache region. Both are instrumentation + concerns and belong in `infrastructure` (the repository/decorator classes), not `application`. +- **Tracing**: the `spring-boot-starter-opentelemetry` starter (Boot 4.1's unified tracing starter - + supersedes the Boot 3-era `micrometer-tracing-bridge-otel` + `opentelemetry-exporter-otlp` combo) + exports to Tempo via `management.opentelemetry.tracing.export.otlp.endpoint=http://tempo:4318/v1/traces` + - note this property lives under `management.opentelemetry.*`, not the old `management.otlp.*` + namespace, matching `docker-compose.yaml`. `management.tracing.sampling.probability=1.0` for this + exercise (full sampling; would be tuned down in a real production deployment under real traffic volume). - **Logging**: structured JSON via Spring Boot's built-in structured logging support, trace/span IDs included automatically via Micrometer Tracing's MDC integration, shipped to Loki via Grafana Alloy (already wired in `docker-compose.yaml` / `observability/alloy/config.alloy`) - no application-side @@ -430,61 +634,87 @@ docker-compose --profile load-test run k6 run /scripts/six-degrees.js ## 9. Error Handling & API Conventions -- All errors are RFC 7807 `ProblemDetail` (Spring Boot 3 built-in): `404` for unknown IDs, `400` for - malformed IDs / out-of-range `maxDegree` / missing required query params. +- All errors are RFC 7807 `ProblemDetail`: `404` for unknown IDs (`domain.exception.NotFoundException`, + thrown by `application` use cases, mapped by `presentation.ApiExceptionHandler`), `400` for malformed + IDs (`IllegalArgumentException` from `utils.ImdbIds`) / out-of-range `maxDegree` (handled automatically + by Spring MVC's built-in `HandlerMethodValidationException` support, no custom handler needed) / + missing required query params. - Six-degrees disambiguation is `200`, not an error status - see §4.4. -- Pagination via Spring Data `Pageable` (`page`, `size`, default `sort`) on search and top-rated. -- `springdoc-openapi` for a self-serve Swagger UI. +- Pagination via the hand-rolled `PagedResult` (§4.1), not Spring Data's `Page`. +- Swagger/OpenAPI UI is deferred - `springdoc-openapi` isn't yet available for Boot 4.1 (§11). ## 10. Test Plan The seeded `abanda/imdb-postgresql` image is ~20GB and takes 20-30 minutes to import - unusable as a CI -dependency. Testing splits accordingly: - -- **Unit tests**: service layer against mocked repositories (JUnit 5 + Mockito + AssertJ, matching - `votee`'s existing testing style in this monorepo). -- **Integration tests**: Testcontainers running a plain `postgres:17` image, migrated with the real - `V1`/`V2` migrations from §3 plus a small hand-authored fixture dataset - (`fixture-schema.sql`/`fixture-data.sql`) covering: a known multi-hop co-star chain (to exercise the - bidirectional CTE end-to-end, including a deliberate case where the true path requires more than one - hop on each side), a tied weighted-rating case, and an ambiguous shared name. Fast and deterministic. -- **Controller tests**: `MockMvc`, request validation and `ProblemDetail` error-shape contracts. -- **CI**: GitHub Actions, matching `votee`'s existing workflow pattern - unit + integration tests against - the lightweight fixture only. +dependency. Testing splits accordingly, and the onion split from §2 changes *what* "unit test" means here +for the better: use-case implementations are tested against mocked `domain.repository` **interfaces** +with plain Mockito, no Spring context and no Testcontainers required at all. + +- **Unit tests**: `application`-layer `*UseCaseImpl` classes against mocked `domain.repository` + interfaces (JUnit 5 + Mockito + AssertJ, matching `votee`'s existing testing style in this monorepo). + Because these are pure interface mocks, none of these tests touch Postgres, Redis, or Spring at all. +- **Decorator tests**: a small, separate test per `infrastructure.cache` decorator verifying it actually + delegates on a cache miss and doesn't re-invoke the delegate on a hit - previously moot (the old + `DistanceCache` design in §2.1 needed this reasoned about carefully to avoid the self-invocation + pitfall); now a simple, mechanical test against a mock delegate. +- **Integration tests**: Testcontainers running a plain `postgres:17` image, exercising the + `infrastructure.persistence` implementations directly against their `domain.repository` interface + contracts. Flyway runs `V0`/`V1`/`V2` from §3 automatically on context startup (`V0` is what actually + creates the base tables here - see §3.4), then a small hand-authored `fixture-data.sql` (loaded via + `@Sql` on the test class, which runs after the context - and therefore Flyway - is already up) seeds + rows covering: a known multi-hop co-star chain (to exercise the bidirectional CTE end-to-end, including + a deliberate case where the true path requires more than one hop on each side), a tied weighted-rating + case, and an ambiguous shared name. Fast and deterministic. +- **Controller tests**: `MockMvc` against mocked `application`-layer use-case interfaces (`@MockitoBean` - + the current replacement for the older `@MockBean`, checked against the Boot 4.1 testing reference docs + directly), covering request validation and `ProblemDetail` error-shape contracts. +- **CI**: GitHub Actions, matching `votee`'s existing workflow pattern - unit + decorator + integration + tests against the lightweight fixture only. - **Load tests**: k6 (§8), run manually against the fully-seeded stack, not part of the CI gate. ## 11. Open Items for Implementation -- Scaffold the Maven project via [start.spring.io](https://start.spring.io/): Java 21, Spring Boot 4.1.0, - group `com.ludovictemgoua`, artifact `imdb`. All dependencies below are selectable directly on - Initializr - no post-generation pom edits needed: - - | Dependency (Initializr label) | Include? | Why | - |---|---|---| - | Spring Web | Yes | REST controllers | - | JDBC API | Yes | `NamedParameterJdbcTemplate` access - **not** Spring Data JDBC, see §3.1 (avoids reintroducing a repository/entity abstraction) | - | PostgreSQL Driver | Yes | Connects to `abanda/imdb-postgresql` | - | Flyway Migration | Yes | Runs the `V1`/`V2` migrations from §3 | - | Spring Data Redis | Yes | Cache-aside layer, §6 | - | Validation | Yes | `maxDegree` range / malformed-ID checks at the controller boundary | - | Spring Boot Actuator | Yes | Health, `/actuator/prometheus` | - | Prometheus | Yes | Micrometer -> Prometheus format, scraped by the `prometheus` compose service | - | Distributed Tracing | Yes | Span/trace IDs in logs - log<->trace correlation, §7 | - | OpenTelemetry | Yes | Publishes traces via OTLP to Tempo, pairs with Distributed Tracing | - | springdoc-openapi | Yes | Swagger UI | - | Testcontainers | Yes | Backs the integration-test plan, §10 | - | datasource-micrometer | No | Its Initializr `versionRange` is `[3.5.0.RELEASE, 4.1.0.M1)` - not yet ported to the Boot 4.1 line. The gap is covered anyway: Spring Boot auto-binds HikariCP connection-pool metrics via Actuator/Micrometer with no extra dependency, and the one query worth watching closely (the six-degrees CTE) already gets a hand-rolled `Timer` per §7. | - | Lombok | No | This monorepo uses Java records for value types (see `votee`), not Lombok-generated boilerplate | - | Docker Compose (dev-tool) | No | Conflicts with our hand-authored `docker-compose.yaml`, which already includes the app itself as a service | - | Zipkin | No | Redundant trace backend - traces already go via OpenTelemetry/OTLP to Tempo | - | otlp-metrics | No | Redundant metrics path - metrics already go via Prometheus pull-scrape | +The Maven project itself (Java 21, Spring Boot 4.1.0, group `com.ludovictemgoua`, artifact `imdb`) is +scaffolded and the dependency set below is already in `pom.xml`, generated directly from Initializr with +no post-generation edits needed: + +| Dependency (Initializr label) | Include? | Why | +|---|---|---| +| Spring Web | Yes | REST controllers | +| JDBC API | Yes | `NamedParameterJdbcTemplate` access - **not** Spring Data JDBC, see §3.1 (avoids reintroducing a repository/entity abstraction) | +| PostgreSQL Driver | Yes | Connects to `abanda/imdb-postgresql` | +| Flyway Migration | Yes | Runs the `V0`/`V1`/`V2` migrations from §3 | +| Spring Data Redis | Yes | Cache-aside layer, §6 | +| Validation | Yes | `maxDegree` range / malformed-ID checks at the controller boundary | +| Spring Boot Actuator | Yes | Health, `/actuator/prometheus` | +| Prometheus | Yes | Micrometer -> Prometheus format, scraped by the `prometheus` compose service | +| Distributed Tracing | Yes | Span/trace IDs in logs - log<->trace correlation, §7 | +| OpenTelemetry | Yes | Publishes traces via OTLP to Tempo, pairs with Distributed Tracing - both selections resolve to the single unified `spring-boot-starter-opentelemetry` artifact on Boot 4.1 | +| springdoc-openapi | No | Its Initializr `versionRange` is `[3.5.0.RELEASE, 4.1.0.M1)` - the exact same cutoff as `datasource-micrometer` below, i.e. not yet ported to Boot 4.1. Swagger UI is deferred to whenever springdoc catches up (see PDD §12, Out of Scope); it isn't load-bearing for anything else in this design. | +| Testcontainers | Yes | Backs the integration-test plan, §10 | +| datasource-micrometer | No | Its Initializr `versionRange` is `[3.5.0.RELEASE, 4.1.0.M1)` - not yet ported to the Boot 4.1 line. The gap is covered anyway: Spring Boot auto-binds HikariCP connection-pool metrics via Actuator/Micrometer with no extra dependency, and the one query worth watching closely (the six-degrees CTE) already gets a hand-rolled timeout per §5.2. | +| Lombok | No | This monorepo uses Java records for value types (see `votee`), not Lombok-generated boilerplate | +| Docker Compose (dev-tool) | No | Conflicts with our hand-authored `docker-compose.yaml`, which already includes the app itself as a service | +| Zipkin | No | Redundant trace backend - traces already go via OpenTelemetry/OTLP to Tempo | +| otlp-metrics | No | Redundant metrics path - metrics already go via Prometheus pull-scrape | + +Remaining work: + - Write the multi-stage `Dockerfile` (Maven build stage -> JRE runtime stage) referenced by `docker-compose.yaml`'s `imdb-service.build`. - Author the actual Grafana dashboard JSON models under `observability/grafana/provisioning/dashboards/json/`. - Author the k6 scripts and the sampled-actor CSV under `imdb/k6/`. +- Write the test suite described in §10 - unit tests, decorator tests, integration tests, controller + tests - none of it exists yet. - Pick the concrete `minVotes` default for the weighted-rating formula from the real vote-count distribution once the dataset is loaded (PDD §11). - Tune `fanOutCap` and `sideCap` in §5.2 against real k6 results; both are exposed as configuration, not hardcoded, specifically so this tuning doesn't require a code change. - Decide the `co_star_edges` refresh cadence (PDD §11 open question) if this ever moves beyond a single-import deployment. +- The onion layering in §2 is enforced today only by convention (import direction) and code review, not + by a build-tool boundary. If this project grows past its current size, splitting `domain`/`application`/ + `infrastructure`/`presentation` into separate Maven modules would make the dependency rule + compiler-enforced instead of convention-enforced - not done now since a 4-module split is disproportionate + to this project's actual size, but the package structure is already shaped to make that split + mechanical later if it's ever worth it. diff --git a/imdb/docs/product-design.md b/imdb/docs/product-design.md index 962b154..b13ccd4 100644 --- a/imdb/docs/product-design.md +++ b/imdb/docs/product-design.md @@ -204,6 +204,8 @@ k6 (one script per endpoint, run in isolation) --> imdb-service, results --> Pro production query volume. - Multi-instance/horizontal scaling of the application tier (the design is cache/observability-ready for it, but it isn't exercised here). +- Swagger/OpenAPI documentation UI: `springdoc-openapi`'s Initializr `versionRange` doesn't yet cover + Spring Boot 4.1 (see low-level design §11). Revisit once springdoc ships 4.1 support. ## 13. References From 6e500ee2edce05c4b885f41079a77dcd7c710ca5 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 6 Jul 2026 04:34:18 +0200 Subject: [PATCH 07/42] imdb: Implemented all domain layer code --- .../domain/exception/NotFoundException.java | 7 ++++ .../imdb/domain/model/CastMember.java | 6 +++ .../imdb/domain/model/CreditedPerson.java | 4 ++ .../imdb/domain/model/GenreTopRatedItem.java | 5 +++ .../imdb/domain/model/GraphPath.java | 10 +++++ .../imdb/domain/model/PagedResult.java | 6 +++ .../imdb/domain/model/PersonCandidate.java | 6 +++ .../imdb/domain/model/PersonResolution.java | 12 ++++++ .../imdb/domain/model/RatingView.java | 4 ++ .../imdb/domain/model/SharedTitle.java | 4 ++ .../imdb/domain/model/TitleCore.java | 8 ++++ .../imdb/domain/model/TitleDetail.java | 10 +++++ .../imdb/domain/model/TitleSummary.java | 5 +++ .../repository/CoStarGraphRepository.java | 10 +++++ .../domain/repository/PersonRepository.java | 17 ++++++++ .../domain/repository/TitleRepository.java | 31 ++++++++++++++ imdb/src/main/resources/application.yaml | 33 +++++++++++++++ .../db/migration/V0__base_schema.sql | 42 +++++++++++++++++++ .../V1__extensions_and_search_indexes.sql | 20 +++++++++ .../V2__co_star_edges_materialized_view.sql | 10 +++++ 20 files changed, 250 insertions(+) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/exception/NotFoundException.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CastMember.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CreditedPerson.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GenreTopRatedItem.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GraphPath.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PagedResult.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonCandidate.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonResolution.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/RatingView.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/SharedTitle.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleCore.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleDetail.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleSummary.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/CoStarGraphRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/PersonRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java create mode 100644 imdb/src/main/resources/db/migration/V0__base_schema.sql create mode 100644 imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql create mode 100644 imdb/src/main/resources/db/migration/V2__co_star_edges_materialized_view.sql diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/exception/NotFoundException.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/exception/NotFoundException.java new file mode 100644 index 0000000..f03f5cf --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/exception/NotFoundException.java @@ -0,0 +1,7 @@ +package com.ludovictemgoua.imdb.domain.exception; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CastMember.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CastMember.java new file mode 100644 index 0000000..e2983d6 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CastMember.java @@ -0,0 +1,6 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record CastMember(String id, String name, String category, List characters, int ordering) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CreditedPerson.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CreditedPerson.java new file mode 100644 index 0000000..4c20e96 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/CreditedPerson.java @@ -0,0 +1,4 @@ +package com.ludovictemgoua.imdb.domain.model; + +public record CreditedPerson(String id, String name) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GenreTopRatedItem.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GenreTopRatedItem.java new file mode 100644 index 0000000..bb00081 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GenreTopRatedItem.java @@ -0,0 +1,5 @@ +package com.ludovictemgoua.imdb.domain.model; + +public record GenreTopRatedItem(String id, String primaryTitle, Integer startYear, double averageRating, + int numVotes, double weightedRating) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GraphPath.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GraphPath.java new file mode 100644 index 0000000..db2d678 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/GraphPath.java @@ -0,0 +1,10 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +// Deliberately algorithm-agnostic: just a degree and the ordered chain of person ids connecting the +// two endpoints. Nothing here leaks that today's implementation happens to compute this by meeting +// two searches in the middle - a future CoStarGraphRepository implementation (precomputed BFS, a +// graph database) returns the exact same shape without this type ever changing. +public record GraphPath(int degree, List personIds) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PagedResult.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PagedResult.java new file mode 100644 index 0000000..6af6b52 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PagedResult.java @@ -0,0 +1,6 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record PagedResult(List content, long totalElements, int page, int size) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonCandidate.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonCandidate.java new file mode 100644 index 0000000..720f3ab --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonCandidate.java @@ -0,0 +1,6 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record PersonCandidate(String id, String name, Integer birthYear, List knownFor) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonResolution.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonResolution.java new file mode 100644 index 0000000..f5b1b73 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PersonResolution.java @@ -0,0 +1,12 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public sealed interface PersonResolution { + record Resolved(int nconst, String name) implements PersonResolution { + } + record Ambiguous(List candidates) implements PersonResolution { + } + record NotFound() implements PersonResolution { + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/RatingView.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/RatingView.java new file mode 100644 index 0000000..fd3ce10 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/RatingView.java @@ -0,0 +1,4 @@ +package com.ludovictemgoua.imdb.domain.model; + +public record RatingView(double average, int numVotes) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/SharedTitle.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/SharedTitle.java new file mode 100644 index 0000000..3b24608 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/SharedTitle.java @@ -0,0 +1,4 @@ +package com.ludovictemgoua.imdb.domain.model; + +public record SharedTitle(String id, String primaryTitle) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleCore.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleCore.java new file mode 100644 index 0000000..c293a1e --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleCore.java @@ -0,0 +1,8 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record TitleCore(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, Double averageRating, Integer numVotes) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleDetail.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleDetail.java new file mode 100644 index 0000000..9e4d3af --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleDetail.java @@ -0,0 +1,10 @@ +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record TitleDetail(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, RatingView rating, + List directors, List writers, + List cast, int castTotalCount) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleSummary.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleSummary.java new file mode 100644 index 0000000..4abf0ec --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/TitleSummary.java @@ -0,0 +1,5 @@ +package com.ludovictemgoua.imdb.domain.model; + +public record TitleSummary(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/CoStarGraphRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/CoStarGraphRepository.java new file mode 100644 index 0000000..26cfd35 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/CoStarGraphRepository.java @@ -0,0 +1,10 @@ +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.GraphPath; + +import java.util.Optional; + +public interface CoStarGraphRepository { + + Optional findShortestPath(int personA, int personB); +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/PersonRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/PersonRepository.java new file mode 100644 index 0000000..597f033 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/PersonRepository.java @@ -0,0 +1,17 @@ +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface PersonRepository { + + List findByName(String name); + + Optional findNameById(int nconst); + + Map findNamesByIds(Collection nconsts); +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java new file mode 100644 index 0000000..19b324f --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java @@ -0,0 +1,31 @@ +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.CastMember; +import com.ludovictemgoua.imdb.domain.model.CreditedPerson; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.SharedTitle; +import com.ludovictemgoua.imdb.domain.model.TitleCore; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; + +import java.util.List; +import java.util.Optional; + +public interface TitleRepository { + + PagedResult search(String query, int page, int size); + + Optional findCore(int tconst); + + List findDirectors(int tconst); + + List findWriters(int tconst); + + List findTopCast(int tconst, int limit); + + int countCast(int tconst); + + List findTopRated(String genre, int limit, int minVotes); + + Optional findAnyCommonTitle(int personA, int personB); +} diff --git a/imdb/src/main/resources/application.yaml b/imdb/src/main/resources/application.yaml index d7a251e..aec6d24 100644 --- a/imdb/src/main/resources/application.yaml +++ b/imdb/src/main/resources/application.yaml @@ -1,3 +1,36 @@ spring: application: name: imdb + datasource: + url: jdbc:postgresql://localhost:5432/imdb + username: imdb + password: password + data: + redis: + host: localhost + port: 6379 + flyway: + enabled: true + +management: + endpoints: + web: + exposure: + include: health, prometheus + tracing: + sampling: + probability: 1.0 + opentelemetry: + tracing: + export: + otlp: + endpoint: http://localhost:4318/v1/traces + +six-degrees: + side-cap: 4 + absolute-max-degree: 7 + fan-out-cap: 200 + query-timeout-seconds: 2 + +top-rated: + default-min-votes: 1000 diff --git a/imdb/src/main/resources/db/migration/V0__base_schema.sql b/imdb/src/main/resources/db/migration/V0__base_schema.sql new file mode 100644 index 0000000..60de614 --- /dev/null +++ b/imdb/src/main/resources/db/migration/V0__base_schema.sql @@ -0,0 +1,42 @@ +CREATE TABLE IF NOT EXISTS name_basics ( + nconst INTEGER PRIMARY KEY, + primary_name TEXT NOT NULL, + birth_year INTEGER, + death_year INTEGER, + primary_profession TEXT[], + known_for_titles INTEGER[] +); + +CREATE TABLE IF NOT EXISTS title_basics ( + tconst INTEGER PRIMARY KEY, + title_type TEXT NOT NULL, + primary_title TEXT NOT NULL, + original_title TEXT NOT NULL, + is_adult BOOLEAN NOT NULL DEFAULT FALSE, + start_year INTEGER, + end_year INTEGER, + runtime_minutes INTEGER, + genres TEXT[] +); + +CREATE TABLE IF NOT EXISTS title_ratings ( + tconst INTEGER PRIMARY KEY REFERENCES title_basics (tconst), + average_rating NUMERIC NOT NULL, + num_votes INTEGER NOT NULL +); + +CREATE TABLE IF NOT EXISTS title_crew ( + tconst INTEGER PRIMARY KEY REFERENCES title_basics (tconst), + directors INTEGER[], + writers INTEGER[] +); + +CREATE TABLE IF NOT EXISTS title_principals ( + tconst INTEGER NOT NULL REFERENCES title_basics (tconst), + ordering INTEGER NOT NULL, + nconst INTEGER NOT NULL REFERENCES name_basics (nconst), + category TEXT NOT NULL, + job TEXT, + characters TEXT[], + PRIMARY KEY (tconst, ordering) +); diff --git a/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql b/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql new file mode 100644 index 0000000..f274bf8 --- /dev/null +++ b/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql @@ -0,0 +1,20 @@ +CREATE EXTENSION IF NOT EXISTS pg_trgm; + +CREATE INDEX idx_title_basics_primary_title_trgm + ON title_basics USING gin (primary_title gin_trgm_ops); + +CREATE INDEX idx_title_basics_original_title_trgm + ON title_basics USING gin (original_title gin_trgm_ops); + +CREATE INDEX idx_title_basics_genres + ON title_basics USING gin ((genres::text[])); + +CREATE INDEX idx_title_ratings_rank + ON title_ratings (average_rating DESC, num_votes DESC); + +CREATE INDEX idx_title_principals_nconst_acting + ON title_principals (nconst) + WHERE category IN ('actor', 'actress', 'self'); + +CREATE INDEX idx_name_basics_primary_name_trgm + ON name_basics USING gin (primary_name gin_trgm_ops); diff --git a/imdb/src/main/resources/db/migration/V2__co_star_edges_materialized_view.sql b/imdb/src/main/resources/db/migration/V2__co_star_edges_materialized_view.sql new file mode 100644 index 0000000..59e006c --- /dev/null +++ b/imdb/src/main/resources/db/migration/V2__co_star_edges_materialized_view.sql @@ -0,0 +1,10 @@ +CREATE MATERIALIZED VIEW co_star_edges AS +SELECT DISTINCT p1.nconst AS person_a, p2.nconst AS person_b +FROM title_principals p1 +JOIN title_principals p2 + ON p1.tconst = p2.tconst + AND p1.nconst <> p2.nconst +WHERE p1.category IN ('actor', 'actress', 'self') + AND p2.category IN ('actor', 'actress', 'self'); + +CREATE UNIQUE INDEX idx_co_star_edges_pk ON co_star_edges (person_a, person_b); From 31fcc36b84c556975c12c1808500dd5bf61cf5d9 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 6 Jul 2026 04:40:30 +0200 Subject: [PATCH 08/42] imdb: Implemented all application layer code --- .../imdb/application/PathStep.java | 6 ++ .../imdb/application/PersonRef.java | 4 + .../application/PersonResolutionUseCase.java | 41 +++++++++ .../imdb/application/SixDegreesResult.java | 7 ++ .../application/SixDegreesUseCaseImpl.java | 87 +++++++++++++++++++ .../application/TitleDetailUseCaseImpl.java | 38 ++++++++ .../application/TitleSearchUseCaseImpl.java | 22 +++++ .../imdb/application/TopRatedUseCaseImpl.java | 28 ++++++ .../contracts/SixDegreesOutcome.java | 15 ++++ .../contracts/SixDegreesUseCase.java | 6 ++ .../contracts/TitleDetailUseCase.java | 8 ++ .../contracts/TitleSearchUseCase.java | 9 ++ .../contracts/TopRatedUseCase.java | 10 +++ 13 files changed, 281 insertions(+) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImpl.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImpl.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleDetailUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleSearchUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TopRatedUseCase.java diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java new file mode 100644 index 0000000..d5733be --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java @@ -0,0 +1,6 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.SharedTitle; + +public record PathStep(String id, String name, SharedTitle sharedTitle) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java new file mode 100644 index 0000000..ac31063 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java @@ -0,0 +1,4 @@ +package com.ludovictemgoua.imdb.application; + +public record PersonRef(String id, String name) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCase.java new file mode 100644 index 0000000..0a7c085 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCase.java @@ -0,0 +1,41 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; +import com.ludovictemgoua.imdb.domain.model.PersonResolution; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +import java.util.List; + +// Not an interface: it's an internal collaborator used only by SixDegreesUseCaseImpl, not a seam any +// controller or infrastructure decorator needs to substitute. Interfaces earn their keep at the +// boundaries that actually get swapped or mocked in isolation (repositories, the top-level use cases +// below) - not by default on every class. +@Service +class PersonResolutionUseCase { + + private final PersonRepository personRepository; + + PersonResolutionUseCase(PersonRepository personRepository) { + this.personRepository = personRepository; + } + + PersonResolution resolve(String query) { + if (query.startsWith("nm")) { + int nconst = ImdbIds.parsePersonId(query); + return personRepository.findNameById(nconst) + .map(name -> new PersonResolution.Resolved(nconst, name)) + .orElseGet(PersonResolution.NotFound::new); + } + List candidates = personRepository.findByName(query); + return switch (candidates.size()) { + case 0 -> new PersonResolution.NotFound(); + case 1 -> { + PersonCandidate only = candidates.get(0); + yield new PersonResolution.Resolved(ImdbIds.parsePersonId(only.id()), only.name()); + } + default -> new PersonResolution.Ambiguous(candidates); + }; + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java new file mode 100644 index 0000000..3e26984 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java @@ -0,0 +1,7 @@ +package com.ludovictemgoua.imdb.application; + +import java.util.List; + +public record SixDegreesResult(PersonRef personA, PersonRef personB, Integer degree, + boolean withinRequestedMax, List path) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java new file mode 100644 index 0000000..43a88f8 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java @@ -0,0 +1,87 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; +import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase; +import com.ludovictemgoua.imdb.domain.model.GraphPath; +import com.ludovictemgoua.imdb.domain.model.PersonResolution; +import com.ludovictemgoua.imdb.domain.model.SharedTitle; +import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Service +public class SixDegreesUseCaseImpl implements SixDegreesUseCase { + + private final PersonResolutionUseCase personResolution; + private final CoStarGraphRepository graphRepository; + private final PersonRepository personRepository; + private final TitleRepository titleRepository; + + public SixDegreesUseCaseImpl(PersonResolutionUseCase personResolution, CoStarGraphRepository graphRepository, + PersonRepository personRepository, TitleRepository titleRepository) { + this.personResolution = personResolution; + this.graphRepository = graphRepository; + this.personRepository = personRepository; + this.titleRepository = titleRepository; + } + + @Override + public SixDegreesOutcome compute(String queryA, String queryB, int maxDegree) { + PersonResolution resolvedA = personResolution.resolve(queryA); + if (resolvedA instanceof PersonResolution.Ambiguous a) { + return new SixDegreesOutcome.Ambiguous(queryA, a.candidates()); + } + if (resolvedA instanceof PersonResolution.NotFound) { + return new SixDegreesOutcome.PersonNotFound(queryA); + } + PersonResolution resolvedB = personResolution.resolve(queryB); + if (resolvedB instanceof PersonResolution.Ambiguous b) { + return new SixDegreesOutcome.Ambiguous(queryB, b.candidates()); + } + if (resolvedB instanceof PersonResolution.NotFound) { + return new SixDegreesOutcome.PersonNotFound(queryB); + } + + var a = (PersonResolution.Resolved) resolvedA; + var b = (PersonResolution.Resolved) resolvedB; + PersonRef personA = new PersonRef(ImdbIds.formatPersonId(a.nconst()), a.name()); + PersonRef personB = new PersonRef(ImdbIds.formatPersonId(b.nconst()), b.name()); + + if (a.nconst() == b.nconst()) { + PathStep onlyStep = new PathStep(personA.id(), personA.name(), null); + return new SixDegreesOutcome.Found( + new SixDegreesResult(personA, personB, 0, true, List.of(onlyStep))); + } + + Optional match = graphRepository.findShortestPath(a.nconst(), b.nconst()); + if (match.isEmpty()) { + return new SixDegreesOutcome.Found( + new SixDegreesResult(personA, personB, null, false, List.of())); + } + + GraphPath path = match.get(); + boolean withinMax = path.degree() <= maxDegree; + List steps = withinMax ? buildPath(path.personIds()) : List.of(); + return new SixDegreesOutcome.Found( + new SixDegreesResult(personA, personB, path.degree(), withinMax, steps)); + } + + private List buildPath(List nconsts) { + Map names = personRepository.findNamesByIds(nconsts); + List steps = new ArrayList<>(); + for (int i = 0; i < nconsts.size(); i++) { + int nconst = nconsts.get(i); + SharedTitle sharedTitle = i == 0 ? null + : titleRepository.findAnyCommonTitle(nconsts.get(i - 1), nconst).orElse(null); + steps.add(new PathStep(ImdbIds.formatPersonId(nconst), names.get(nconst), sharedTitle)); + } + return steps; + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java new file mode 100644 index 0000000..b7428d4 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java @@ -0,0 +1,38 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.RatingView; +import com.ludovictemgoua.imdb.domain.model.TitleDetail; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +@Service +public class TitleDetailUseCaseImpl implements TitleDetailUseCase { + + private static final int CAST_LIMIT = 20; + + private final TitleRepository titleRepository; + + public TitleDetailUseCaseImpl(TitleRepository titleRepository) { + this.titleRepository = titleRepository; + } + + @Override + public TitleDetail getDetail(String titleId) { + int tconst = ImdbIds.parseTitleId(titleId); + var core = titleRepository.findCore(tconst) + .orElseThrow(() -> new NotFoundException("No title with id " + titleId)); + var directors = titleRepository.findDirectors(tconst); + var writers = titleRepository.findWriters(tconst); + var cast = titleRepository.findTopCast(tconst, CAST_LIMIT); + int castTotal = titleRepository.countCast(tconst); + return new TitleDetail( + core.id(), core.primaryTitle(), core.originalTitle(), core.titleType(), + core.startYear(), core.endYear(), core.runtimeMinutes(), core.genres(), + new RatingView(core.averageRating() == null ? 0 : core.averageRating(), + core.numVotes() == null ? 0 : core.numVotes()), + directors, writers, cast, castTotal); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImpl.java new file mode 100644 index 0000000..7bf68db --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImpl.java @@ -0,0 +1,22 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import org.springframework.stereotype.Service; + +@Service +public class TitleSearchUseCaseImpl implements TitleSearchUseCase { + + private final TitleRepository titleRepository; + + public TitleSearchUseCaseImpl(TitleRepository titleRepository) { + this.titleRepository = titleRepository; + } + + @Override + public PagedResult search(String query, int page, int size) { + return titleRepository.search(query, page, size); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImpl.java new file mode 100644 index 0000000..a600578 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImpl.java @@ -0,0 +1,28 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class TopRatedUseCaseImpl implements TopRatedUseCase { + + private final TitleRepository titleRepository; + private final int defaultMinVotes; + + public TopRatedUseCaseImpl(TitleRepository titleRepository, + @Value("${top-rated.default-min-votes}") int defaultMinVotes) { + this.titleRepository = titleRepository; + this.defaultMinVotes = defaultMinVotes; + } + + @Override + public List findTopRated(String genre, int limit, Integer minVotes) { + int effectiveMinVotes = minVotes == null ? defaultMinVotes : minVotes; + return titleRepository.findTopRated(genre, limit, effectiveMinVotes); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java new file mode 100644 index 0000000..c84a1d3 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java @@ -0,0 +1,15 @@ +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.SixDegreesResult; +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; + +import java.util.List; + +public sealed interface SixDegreesOutcome { + record Found(SixDegreesResult result) implements SixDegreesOutcome { + } + record Ambiguous(String query, List candidates) implements SixDegreesOutcome { + } + record PersonNotFound(String query) implements SixDegreesOutcome { + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesUseCase.java new file mode 100644 index 0000000..3f3ed17 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesUseCase.java @@ -0,0 +1,6 @@ +package com.ludovictemgoua.imdb.application.contracts; + +public interface SixDegreesUseCase { + + SixDegreesOutcome compute(String queryA, String queryB, int maxDegree); +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleDetailUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleDetailUseCase.java new file mode 100644 index 0000000..b7d5a56 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleDetailUseCase.java @@ -0,0 +1,8 @@ +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.domain.model.TitleDetail; + +public interface TitleDetailUseCase { + + TitleDetail getDetail(String titleId); +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleSearchUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleSearchUseCase.java new file mode 100644 index 0000000..230d4ca --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleSearchUseCase.java @@ -0,0 +1,9 @@ +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; + +public interface TitleSearchUseCase { + + PagedResult search(String query, int page, int size); +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TopRatedUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TopRatedUseCase.java new file mode 100644 index 0000000..95c2159 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TopRatedUseCase.java @@ -0,0 +1,10 @@ +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; + +import java.util.List; + +public interface TopRatedUseCase { + + List findTopRated(String genre, int limit, Integer minVotes); +} From 130dc26ea8abb132a45fdb4c690cc1f11c34733e Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 6 Jul 2026 04:44:45 +0200 Subject: [PATCH 09/42] imdb: Implemented all infrastructure layer code --- .../infrastructure/cache/CacheConfig.java | 29 +++ .../cache/CachingCoStarGraphRepository.java | 31 +++ .../cache/CachingTitleDetailUseCase.java | 25 +++ .../cache/CachingTitleSearchUseCase.java | 29 +++ .../cache/CachingTopRatedUseCase.java | 27 +++ .../JdbcCoStarGraphRepository.java | 107 ++++++++++ .../persistence/JdbcPersonRepository.java | 66 ++++++ .../persistence/JdbcTitleRepository.java | 192 ++++++++++++++++++ .../persistence/PathStitcher.java | 23 +++ .../ludovictemgoua/imdb/utils/ImdbIds.java | 34 ++++ 10 files changed, 563 insertions(+) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/utils/ImdbIds.java diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java new file mode 100644 index 0000000..e52d84b --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java @@ -0,0 +1,29 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; + +import java.time.Duration; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { + RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofHours(24)) + .serializeValuesWith(RedisSerializationContext.SerializationPair + .fromSerializer(new GenericJackson2JsonRedisSerializer())); + + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(defaults) + .build(); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java new file mode 100644 index 0000000..eae78f1 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java @@ -0,0 +1,31 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.domain.model.GraphPath; +import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import com.ludovictemgoua.imdb.infrastructure.persistence.JdbcCoStarGraphRepository; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +// Caching lives at the repository level here, not the use-case level like the three Title* use +// cases above - the true shortest distance between two person ids is a clean, unambiguous cache key +// independent of anything SixDegreesUseCase does with names/disambiguation/maxDegree (LLD §6). +@Repository +@Primary +public class CachingCoStarGraphRepository implements CoStarGraphRepository { + + private final JdbcCoStarGraphRepository delegate; + + public CachingCoStarGraphRepository(JdbcCoStarGraphRepository delegate) { + this.delegate = delegate; + } + + @Override + @Cacheable(cacheNames = "six-degrees", + key = "T(java.lang.Math).min(#personA, #personB) + '-' + T(java.lang.Math).max(#personA, #personB)") + public Optional findShortestPath(int personA, int personB) { + return delegate.findShortestPath(personA, personB); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java new file mode 100644 index 0000000..6507b22 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java @@ -0,0 +1,25 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.application.TitleDetailUseCaseImpl; +import com.ludovictemgoua.imdb.domain.model.TitleDetail; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +@Service +@Primary +public class CachingTitleDetailUseCase implements TitleDetailUseCase { + + private final TitleDetailUseCaseImpl delegate; + + public CachingTitleDetailUseCase(TitleDetailUseCaseImpl delegate) { + this.delegate = delegate; + } + + @Override + @Cacheable(cacheNames = "title-detail", key = "#titleId") + public TitleDetail getDetail(String titleId) { + return delegate.getDetail(titleId); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java new file mode 100644 index 0000000..c5341ae --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java @@ -0,0 +1,29 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; +import com.ludovictemgoua.imdb.application.TitleSearchUseCaseImpl; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +// @Primary: whichever bean wins here is what every consumer of TitleSearchUseCase (controllers) gets +// by constructor injection, with zero awareness that caching exists. Swap caching technology, or drop +// it entirely, by changing only this class - TitleSearchUseCaseImpl and every controller are untouched. +@Service +@Primary +public class CachingTitleSearchUseCase implements TitleSearchUseCase { + + private final TitleSearchUseCaseImpl delegate; + + public CachingTitleSearchUseCase(TitleSearchUseCaseImpl delegate) { + this.delegate = delegate; + } + + @Override + @Cacheable(cacheNames = "title-search", key = "#query + ':' + #page + ':' + #size") + public PagedResult search(String query, int page, int size) { + return delegate.search(query, page, size); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java new file mode 100644 index 0000000..4fea817 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java @@ -0,0 +1,27 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import com.ludovictemgoua.imdb.application.TopRatedUseCaseImpl; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +@Primary +public class CachingTopRatedUseCase implements TopRatedUseCase { + + private final TopRatedUseCaseImpl delegate; + + public CachingTopRatedUseCase(TopRatedUseCaseImpl delegate) { + this.delegate = delegate; + } + + @Override + @Cacheable(cacheNames = "top-rated", key = "#genre + ':' + #limit + ':' + #minVotes") + public List findTopRated(String genre, int limit, Integer minVotes) { + return delegate.findTopRated(genre, limit, minVotes); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java new file mode 100644 index 0000000..5c8cf87 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java @@ -0,0 +1,107 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.GraphPath; +import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +@Repository +public class JdbcCoStarGraphRepository implements CoStarGraphRepository { + + private final NamedParameterJdbcTemplate jdbc; + private final int sideCap; + private final int fanOutCap; + private final int absoluteMaxDegree; + + public JdbcCoStarGraphRepository( + NamedParameterJdbcTemplate jdbc, + @Value("${six-degrees.side-cap}") int sideCap, + @Value("${six-degrees.fan-out-cap}") int fanOutCap, + @Value("${six-degrees.absolute-max-degree}") int absoluteMaxDegree, + @Value("${six-degrees.query-timeout-seconds}") int queryTimeoutSeconds) { + this.jdbc = jdbc; + this.sideCap = sideCap; + this.fanOutCap = fanOutCap; + this.absoluteMaxDegree = absoluteMaxDegree; + // Only this query gets a tight timeout - it's the one query in the whole app whose cost + // depends on graph shape (hub actors) rather than a bounded index lookup. There's no + // `spring.jdbc.template.query-timeout` property to set this declaratively (Boot 4.1 doesn't + // have one), so it's set directly on the underlying JdbcTemplate instead. + ((JdbcTemplate) jdbc.getJdbcOperations()).setQueryTimeout(queryTimeoutSeconds); + } + + @Override + public Optional findShortestPath(int personA, int personB) { + String sql = """ + WITH RECURSIVE forward(person, depth, path) AS ( + SELECT :personA, 0, ARRAY[:personA] + UNION ALL + SELECT nbr.person_b, f.depth + 1, f.path || nbr.person_b + FROM forward f + CROSS JOIN LATERAL ( + SELECT e.person_b + FROM co_star_edges e + WHERE e.person_a = f.person + ORDER BY e.person_b + LIMIT :fanOutCap + ) nbr + WHERE f.depth < :sideCap + AND NOT nbr.person_b = ANY(f.path) + ), + backward(person, depth, path) AS ( + SELECT :personB, 0, ARRAY[:personB] + UNION ALL + SELECT nbr.person_b, b.depth + 1, b.path || nbr.person_b + FROM backward b + CROSS JOIN LATERAL ( + SELECT e.person_b + FROM co_star_edges e + WHERE e.person_a = b.person + ORDER BY e.person_b + LIMIT :fanOutCap + ) nbr + WHERE b.depth < :sideCap + AND NOT nbr.person_b = ANY(b.path) + ) + SELECT f.depth + b.depth AS degree, f.path AS forward_path, b.path AS backward_path + FROM forward f + JOIN backward b ON b.person = f.person + WHERE f.depth + b.depth <= :absoluteMaxDegree + ORDER BY degree ASC + LIMIT 1 + """; + var params = new MapSqlParameterSource() + .addValue("personA", personA).addValue("personB", personB) + .addValue("sideCap", sideCap).addValue("fanOutCap", fanOutCap) + .addValue("absoluteMaxDegree", absoluteMaxDegree); + + return jdbc.query(sql, params, JdbcCoStarGraphRepository::mapRawMatch).stream() + .findFirst() + .map(PathStitcher::stitch); + } + + private static RawMatch mapRawMatch(ResultSet rs, int rowNum) throws SQLException { + return new RawMatch(rs.getInt("degree"), + toIntList(rs.getArray("forward_path")), toIntList(rs.getArray("backward_path"))); + } + + private static List toIntList(Array sqlArray) throws SQLException { + return Arrays.asList((Integer[]) sqlArray.getArray()); + } + + // Package-private: the forward/backward split is an artifact of this one bidirectional-CTE + // implementation, not a domain concept. PathStitcher (same package) collapses it into the clean + // GraphPath the CoStarGraphRepository interface actually promises. + record RawMatch(int degree, List forwardPath, List backwardPath) { + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java new file mode 100644 index 0000000..3ba7bfc --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java @@ -0,0 +1,66 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +@Repository +public class JdbcPersonRepository implements PersonRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public JdbcPersonRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + @Override + public List findByName(String name) { + String sql = """ + SELECT nconst, primary_name, birth_year, known_for_titles + FROM name_basics + WHERE primary_name % :name + ORDER BY similarity(primary_name, :name) DESC + LIMIT 10 + """; + return jdbc.query(sql, Map.of("name", name), JdbcPersonRepository::mapCandidate); + } + + @Override + public Optional findNameById(int nconst) { + return jdbc.query("SELECT primary_name FROM name_basics WHERE nconst = :nconst", + Map.of("nconst", nconst), (rs, rowNum) -> rs.getString("primary_name")) + .stream().findFirst(); + } + + @Override + public Map findNamesByIds(Collection nconsts) { + if (nconsts.isEmpty()) return Map.of(); + String sql = "SELECT nconst, primary_name FROM name_basics WHERE nconst IN (:nconsts)"; + List> rows = jdbc.query(sql, Map.of("nconsts", nconsts), + (rs, rowNum) -> Map.entry(rs.getInt("nconst"), rs.getString("primary_name"))); + return rows.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private static PersonCandidate mapCandidate(ResultSet rs, int rowNum) throws SQLException { + Array knownForArr = rs.getArray("known_for_titles"); + List knownFor = knownForArr == null ? List.of() + : Arrays.stream((Integer[]) knownForArr.getArray()) + .filter(Objects::nonNull).map(ImdbIds::formatTitleId).limit(3).toList(); + return new PersonCandidate( + ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"), + (Integer) rs.getObject("birth_year"), knownFor); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java new file mode 100644 index 0000000..b1b0d8f --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java @@ -0,0 +1,192 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.CastMember; +import com.ludovictemgoua.imdb.domain.model.CreditedPerson; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.SharedTitle; +import com.ludovictemgoua.imdb.domain.model.TitleCore; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Repository +public class JdbcTitleRepository implements TitleRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public JdbcTitleRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + @Override + public PagedResult search(String query, int page, int size) { + String dataSql = """ + SELECT tconst, primary_title, original_title, title_type, start_year, end_year + FROM title_basics + WHERE primary_title % :query OR original_title % :query + ORDER BY similarity(primary_title, :query) DESC + LIMIT :limit OFFSET :offset + """; + String countSql = """ + SELECT count(*) FROM title_basics + WHERE primary_title % :query OR original_title % :query + """; + var params = new MapSqlParameterSource() + .addValue("query", query) + .addValue("limit", size) + .addValue("offset", (long) page * size); + + List content = jdbc.query(dataSql, params, JdbcTitleRepository::mapSummary); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + @Override + public Optional findCore(int tconst) { + String sql = """ + SELECT tb.tconst, tb.primary_title, tb.original_title, tb.title_type, + tb.start_year, tb.end_year, tb.runtime_minutes, tb.genres, + tr.average_rating, tr.num_votes + FROM title_basics tb + LEFT JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.tconst = :tconst + """; + return jdbc.query(sql, Map.of("tconst", tconst), JdbcTitleRepository::mapCore).stream().findFirst(); + } + + @Override + public List findDirectors(int tconst) { + return findCrew(tconst, "directors"); + } + + @Override + public List findWriters(int tconst) { + return findCrew(tconst, "writers"); + } + + @Override + public List findTopCast(int tconst, int limit) { + String sql = """ + SELECT tp.nconst, nb.primary_name, tp.category, tp.characters, tp.ordering + FROM title_principals tp + JOIN name_basics nb ON nb.nconst = tp.nconst + WHERE tp.tconst = :tconst + ORDER BY tp.ordering + LIMIT :limit + """; + var params = new MapSqlParameterSource().addValue("tconst", tconst).addValue("limit", limit); + return jdbc.query(sql, params, JdbcTitleRepository::mapCastMember); + } + + @Override + public int countCast(int tconst) { + Integer count = jdbc.queryForObject( + "SELECT count(*) FROM title_principals WHERE tconst = :tconst", + Map.of("tconst", tconst), Integer.class); + return count == null ? 0 : count; + } + + @Override + public List findTopRated(String genre, int limit, int minVotes) { + String sql = """ + WITH pool AS ( + SELECT tb.tconst, tb.primary_title, tb.start_year, tr.average_rating, tr.num_votes + FROM title_basics tb + JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.title_type = 'movie' + AND tb.genres::text[] @> ARRAY[:genre]::text[] + AND tr.num_votes >= :minVotes + ), + stats AS (SELECT AVG(average_rating) AS mean_rating FROM pool) + SELECT p.tconst, p.primary_title, p.start_year, p.average_rating, p.num_votes, + (p.num_votes::numeric / (p.num_votes + :minVotes)) * p.average_rating + + (:minVotes::numeric / (p.num_votes + :minVotes)) * s.mean_rating AS weighted_rating + FROM pool p CROSS JOIN stats s + ORDER BY weighted_rating DESC + LIMIT :limit + """; + var params = new MapSqlParameterSource() + .addValue("genre", genre).addValue("minVotes", minVotes).addValue("limit", limit); + return jdbc.query(sql, params, JdbcTitleRepository::mapTopRated); + } + + @Override + public Optional findAnyCommonTitle(int personA, int personB) { + String sql = """ + SELECT tb.tconst, tb.primary_title + FROM title_principals p1 + JOIN title_principals p2 ON p1.tconst = p2.tconst + JOIN title_basics tb ON tb.tconst = p1.tconst + WHERE p1.nconst = :personA AND p2.nconst = :personB + LIMIT 1 + """; + var params = new MapSqlParameterSource().addValue("personA", personA).addValue("personB", personB); + return jdbc.query(sql, params, (rs, rowNum) -> + new SharedTitle(ImdbIds.formatTitleId(rs.getInt("tconst")), rs.getString("primary_title"))) + .stream().findFirst(); + } + + private List findCrew(int tconst, String column) { + // column is only ever "directors" or "writers" below - both fixed internal literals, never + // user input - so string-formatting it into the SQL here isn't an injection risk. Bind + // parameters can't stand in for column/identifier names, only values. + String sql = """ + SELECT nb.nconst, nb.primary_name + FROM title_crew tc + CROSS JOIN LATERAL unnest(tc.%s) AS crew(nconst) + JOIN name_basics nb ON nb.nconst = crew.nconst + WHERE tc.tconst = :tconst + """.formatted(column); + return jdbc.query(sql, Map.of("tconst", tconst), + (rs, rowNum) -> new CreditedPerson( + ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"))); + } + + private static TitleSummary mapSummary(ResultSet rs, int rowNum) throws SQLException { + return new TitleSummary( + ImdbIds.formatTitleId(rs.getInt("tconst")), + rs.getString("primary_title"), rs.getString("original_title"), rs.getString("title_type"), + (Integer) rs.getObject("start_year"), (Integer) rs.getObject("end_year")); + } + + private static TitleCore mapCore(ResultSet rs, int rowNum) throws SQLException { + List genres = toStringList(rs.getArray("genres")); + var avgRating = rs.getBigDecimal("average_rating"); + return new TitleCore( + ImdbIds.formatTitleId(rs.getInt("tconst")), + rs.getString("primary_title"), rs.getString("original_title"), rs.getString("title_type"), + (Integer) rs.getObject("start_year"), (Integer) rs.getObject("end_year"), + (Integer) rs.getObject("runtime_minutes"), genres, + avgRating == null ? null : avgRating.doubleValue(), + (Integer) rs.getObject("num_votes")); + } + + private static CastMember mapCastMember(ResultSet rs, int rowNum) throws SQLException { + return new CastMember( + ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"), + rs.getString("category"), toStringList(rs.getArray("characters")), rs.getInt("ordering")); + } + + private static GenreTopRatedItem mapTopRated(ResultSet rs, int rowNum) throws SQLException { + return new GenreTopRatedItem( + ImdbIds.formatTitleId(rs.getInt("tconst")), rs.getString("primary_title"), + (Integer) rs.getObject("start_year"), rs.getBigDecimal("average_rating").doubleValue(), + rs.getInt("num_votes"), rs.getBigDecimal("weighted_rating").doubleValue()); + } + + private static List toStringList(Array sqlArray) throws SQLException { + if (sqlArray == null) return List.of(); + return List.of((String[]) sqlArray.getArray()); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java new file mode 100644 index 0000000..f29f202 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java @@ -0,0 +1,23 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.GraphPath; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +final class PathStitcher { + + private PathStitcher() { + } + + static GraphPath stitch(JdbcCoStarGraphRepository.RawMatch match) { + List backward = new ArrayList<>(match.backwardPath()); + Collections.reverse(backward); + // forward's last element and reversed-backward's first element are the same node (where the + // two searches met) - drop the duplicate before concatenating. + List stitched = new ArrayList<>(match.forwardPath()); + stitched.addAll(backward.subList(1, backward.size())); + return new GraphPath(match.degree(), stitched); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/utils/ImdbIds.java b/imdb/src/main/java/com/ludovictemgoua/imdb/utils/ImdbIds.java new file mode 100644 index 0000000..480ec9c --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/utils/ImdbIds.java @@ -0,0 +1,34 @@ +package com.ludovictemgoua.imdb.utils; + +public final class ImdbIds { + + private ImdbIds() { + } + + public static int parseTitleId(String tt) { + return Integer.parseInt(requirePrefix(tt, "tt")); + } + + public static int parsePersonId(String nm) { + return Integer.parseInt(requirePrefix(nm, "nm")); + } + + public static String formatTitleId(int tconst) { + return "tt" + pad7(tconst); + } + + public static String formatPersonId(int nconst) { + return "nm" + pad7(nconst); + } + + private static String requirePrefix(String id, String prefix) { + if (id == null || !id.startsWith(prefix) || id.length() <= prefix.length()) { + throw new IllegalArgumentException("Expected an id starting with '" + prefix + "': " + id); + } + return id.substring(prefix.length()); + } + + private static String pad7(int value) { + return String.format("%07d", value); + } +} From 8b0d383836240423a18766036416f4026bbd363c Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 6 Jul 2026 04:45:53 +0200 Subject: [PATCH 10/42] imdb: Implemented all presentation layer code --- .../presentation/ApiExceptionHandler.java | 21 +++++++++ .../imdb/presentation/GenreController.java | 34 ++++++++++++++ .../imdb/presentation/PersonController.java | 45 +++++++++++++++++++ .../imdb/presentation/TitleController.java | 43 ++++++++++++++++++ .../imdb/TestcontainersConfiguration.java | 2 +- 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/GenreController.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java new file mode 100644 index 0000000..31c8242 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java @@ -0,0 +1,21 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ApiExceptionHandler { + + @ExceptionHandler(NotFoundException.class) + public ProblemDetail handleNotFound(NotFoundException ex) { + return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage()); + } + + @ExceptionHandler(IllegalArgumentException.class) + public ProblemDetail handleBadId(IllegalArgumentException ex) { + return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage()); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/GenreController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/GenreController.java new file mode 100644 index 0000000..73f7612 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/GenreController.java @@ -0,0 +1,34 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/v1/genres") +@Validated +public class GenreController { + + private final TopRatedUseCase topRatedUseCase; + + public GenreController(TopRatedUseCase topRatedUseCase) { + this.topRatedUseCase = topRatedUseCase; + } + + @GetMapping("/{genre}/top-rated") + public List topRated( + @PathVariable String genre, + @RequestParam(defaultValue = "10") @Min(1) @Max(100) int limit, + @RequestParam(required = false) Integer minVotes) { + return topRatedUseCase.findTopRated(genre, limit, minVotes); + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java new file mode 100644 index 0000000..fb34a5e --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java @@ -0,0 +1,45 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; +import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@RestController +@RequestMapping("/api/v1/people") +@Validated +public class PersonController { + + private final SixDegreesUseCase sixDegreesUseCase; + + public PersonController(SixDegreesUseCase sixDegreesUseCase) { + this.sixDegreesUseCase = sixDegreesUseCase; + } + + @GetMapping("/six-degrees") + public ResponseEntity sixDegrees( + @RequestParam String personA, + @RequestParam String personB, + @RequestParam(defaultValue = "7") @Min(1) @Max(7) int maxDegree) { + + SixDegreesOutcome outcome = sixDegreesUseCase.compute(personA, personB, maxDegree); + return switch (outcome) { + case SixDegreesOutcome.Found found -> ResponseEntity.ok(found.result()); + case SixDegreesOutcome.Ambiguous amb -> ResponseEntity.ok(Map.of( + "requiresDisambiguation", true, "query", amb.query(), "candidates", amb.candidates())); + case SixDegreesOutcome.PersonNotFound nf -> ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(ProblemDetail.forStatusAndDetail( + HttpStatus.NOT_FOUND, "No person matching: " + nf.query())); + }; + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java new file mode 100644 index 0000000..86172f5 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java @@ -0,0 +1,43 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleDetail; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/titles") +@Validated +public class TitleController { + + private final TitleSearchUseCase searchUseCase; + private final TitleDetailUseCase detailUseCase; + + public TitleController(TitleSearchUseCase searchUseCase, TitleDetailUseCase detailUseCase) { + this.searchUseCase = searchUseCase; + this.detailUseCase = detailUseCase; + } + + @GetMapping("/search") + public PagedResult search( + @RequestParam @NotBlank String title, + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return searchUseCase.search(title, page, size); + } + + @GetMapping("/{titleId}") + public TitleDetail get(@PathVariable String titleId) { + return detailUseCase.getDetail(titleId); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java index 6b71356..adeb75b 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java @@ -20,7 +20,7 @@ LgtmStackContainer grafanaLgtmContainer() { @Bean @ServiceConnection PostgreSQLContainer postgresContainer() { - return new PostgreSQLContainer(DockerImageName.parse("postgres:latest")); + return new PostgreSQLContainer(DockerImageName.parse("postgres:17")); } @Bean From ae6f352578233bc92b9bd5eddb675a92b0b17063 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Tue, 7 Jul 2026 10:56:23 +0200 Subject: [PATCH 11/42] Added Dockerfile and Tests --- imdb/Dockerfile | 19 +++ imdb/docs/low-level-design.md | 40 +++-- imdb/pom.xml | 4 + .../infrastructure/cache/CacheConfig.java | 13 +- .../presentation/ApiExceptionHandler.java | 10 ++ .../imdb/TestcontainersConfiguration.java | 2 +- .../PersonResolutionUseCaseTest.java | 75 ++++++++++ .../SixDegreesUseCaseImplTest.java | 137 ++++++++++++++++++ .../TitleDetailUseCaseImplTest.java | 73 ++++++++++ .../TitleSearchUseCaseImplTest.java | 34 +++++ .../application/TopRatedUseCaseImplTest.java | 41 ++++++ .../CachingCoStarGraphRepositoryTest.java | 69 +++++++++ .../cache/CachingTitleDetailUseCaseTest.java | 68 +++++++++ .../cache/CachingTitleSearchUseCaseTest.java | 85 +++++++++++ .../cache/CachingTopRatedUseCaseTest.java | 65 +++++++++ ...cCoStarGraphRepositoryIntegrationTest.java | 54 +++++++ .../JdbcPersonRepositoryIntegrationTest.java | 55 +++++++ .../JdbcTitleRepositoryIntegrationTest.java | 79 ++++++++++ .../presentation/GenreControllerTest.java | 44 ++++++ .../presentation/PersonControllerTest.java | 80 ++++++++++ .../presentation/TitleControllerTest.java | 63 ++++++++ .../test/resources/fixtures/fixture-data.sql | 68 +++++++++ 22 files changed, 1165 insertions(+), 13 deletions(-) create mode 100644 imdb/Dockerfile create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCaseTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImplTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImplTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImplTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImplTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepositoryIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/presentation/GenreControllerTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java create mode 100644 imdb/src/test/resources/fixtures/fixture-data.sql diff --git a/imdb/Dockerfile b/imdb/Dockerfile new file mode 100644 index 0000000..ab9e1f6 --- /dev/null +++ b/imdb/Dockerfile @@ -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"] diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md index 15dda4d..5ec7022 100644 --- a/imdb/docs/low-level-design.md +++ b/imdb/docs/low-level-design.md @@ -50,12 +50,15 @@ implementation today, so on its own that's DIP for its own sake. The payoff show where every top-level use case a controller depends on is *also* an interface (`TitleSearchUseCase`, `TitleDetailUseCase`, `TopRatedUseCase`, `SixDegreesUseCase`), each with a plain `*Impl` and - where caching applies - an `infrastructure.cache` decorator implementing the same -interface, marked `@Primary`: +interface, marked `@Primary`. These four interfaces (plus `SixDegreesOutcome`, the sealed result type of +the `SixDegreesUseCase` contract) live in `application.contracts`, separated from their implementations +in `application` directly - the same "interfaces apart from implementations" convention `domain.repository` +already uses one layer in: ``` -TitleSearchUseCase (interface, application) - ├─ TitleSearchUseCaseImpl (application) - plain orchestration, no caching - └─ CachingTitleSearchUseCase (infrastructure) - @Primary, @Cacheable, delegates to the Impl above +application.contracts.TitleSearchUseCase (interface) + ├─ application.TitleSearchUseCaseImpl - plain orchestration, no caching + └─ infrastructure.cache.CachingTitleSearchUseCase - @Primary, @Cacheable, delegates to the Impl above ``` A controller depends on `TitleSearchUseCase` and never learns which one it got. Swapping cache @@ -138,19 +141,20 @@ imdb/ exception/ NotFoundException.java application/ - TitleSearchUseCase.java # interface + contracts/ + TitleSearchUseCase.java # interface + TitleDetailUseCase.java # interface + TopRatedUseCase.java # interface + SixDegreesUseCase.java # interface + SixDegreesOutcome.java # sealed result type of the SixDegreesUseCase contract TitleSearchUseCaseImpl.java - TitleDetailUseCase.java # interface TitleDetailUseCaseImpl.java - TopRatedUseCase.java # interface TopRatedUseCaseImpl.java - SixDegreesUseCase.java # interface SixDegreesUseCaseImpl.java PersonResolutionUseCase.java # concrete - internal collaborator, not a public seam PersonRef.java PathStep.java SixDegreesResult.java - SixDegreesOutcome.java infrastructure/ persistence/ JdbcTitleRepository.java @@ -582,6 +586,21 @@ which is the one place `infrastructure` code names a specific implementation cla interface - unavoidable, since something has to construct the delegate unambiguously, and it's a same-layer (`infrastructure` → `infrastructure`, effectively) reference, not a boundary violation. +**Jackson 3, not Jackson 2**: `CacheConfig` serializes cache values with +`org.springframework.data.redis.serializer.GenericJacksonJsonRedisSerializer`, not the more commonly +documented `GenericJackson2JsonRedisSerializer`. Boot 4.1's default Jackson is Jackson 3 +(`tools.jackson.core`/`tools.jackson.databind` - a different Maven groupId and root package than Jackson +2.x's `com.fasterxml.jackson.*`, not just a version bump), and `spring-boot-starter-webmvc` doesn't pull +in a Jackson implementation at all by default anymore - `spring-boot-starter-jackson` has to be added +explicitly (present in `pom.xml`; missing it produces a `NoClassDefFoundError` for Jackson types, not a +compile error, since nothing in this codebase references Jackson classes directly - Spring's own +autoconfiguration and `GenericJacksonJsonRedisSerializer` are the only things that touch it). The "2" +variant fails at runtime with `ClassNotFoundException: com.fasterxml.jackson.databind...` since that +package genuinely isn't on the classpath. `enableSpringCacheNullValueSupport()` also has to be requested +explicitly on the Jackson 3 serializer's builder - it was on by default on the old serializer's +constructor - which matters here since caching a "no path found" result as `null` is deliberate, not +incidental. + **Load-test interaction** (carried over from the PDD discussion): the `six-degrees` k6 script must draw a different, pre-sampled person pair per iteration specifically so it exercises the bidirectional CTE instead of just measuring a warm Redis round-trip after the first request - see §8. @@ -676,12 +695,13 @@ with plain Mockito, no Spring context and no Testcontainers required at all. The Maven project itself (Java 21, Spring Boot 4.1.0, group `com.ludovictemgoua`, artifact `imdb`) is scaffolded and the dependency set below is already in `pom.xml`, generated directly from Initializr with -no post-generation edits needed: +one post-generation addition needed (`spring-boot-starter-jackson`, see below): | Dependency (Initializr label) | Include? | Why | |---|---|---| | Spring Web | Yes | REST controllers | | JDBC API | Yes | `NamedParameterJdbcTemplate` access - **not** Spring Data JDBC, see §3.1 (avoids reintroducing a repository/entity abstraction) | +| Jackson | Added post-generation | Not selected on Initializr because it wasn't obviously needed - but `spring-boot-starter-webmvc` doesn't transitively pull in a Jackson implementation on Boot 4.1 the way `spring-boot-starter-web` did on Boot 3, so JSON responses and `GenericJacksonJsonRedisSerializer` (§6) both need it added explicitly | | PostgreSQL Driver | Yes | Connects to `abanda/imdb-postgresql` | | Flyway Migration | Yes | Runs the `V0`/`V1`/`V2` migrations from §3 | | Spring Data Redis | Yes | Cache-aside layer, §6 | diff --git a/imdb/pom.xml b/imdb/pom.xml index a950123..99923ab 100644 --- a/imdb/pom.xml +++ b/imdb/pom.xml @@ -42,6 +42,10 @@ org.springframework.boot spring-boot-starter-flyway + + org.springframework.boot + spring-boot-starter-jackson + org.springframework.boot spring-boot-starter-jdbc diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java index e52d84b..630ec65 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java @@ -6,7 +6,7 @@ import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.GenericJacksonJsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; import java.time.Duration; @@ -17,10 +17,19 @@ public class CacheConfig { @Bean public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { + // GenericJacksonJsonRedisSerializer, not GenericJackson2JsonRedisSerializer: Boot 4.1's default + // Jackson is Jackson 3 (tools.jackson.databind.*, a different Maven groupId/package than the + // Jackson 2.x com.fasterxml.jackson.databind.* the "2"-suffixed serializer needs - the latter + // fails at runtime with a ClassNotFoundException since Jackson 2 isn't on the classpath at all + // by default anymore). enableSpringCacheNullValueSupport() is opt-in here (it was automatic on + // the old serializer's default constructor) - needed since caching a "no path found" result as + // null is deliberate (LLD §6). RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(24)) .serializeValuesWith(RedisSerializationContext.SerializationPair - .fromSerializer(new GenericJackson2JsonRedisSerializer())); + .fromSerializer(GenericJacksonJsonRedisSerializer.builder() + .enableSpringCacheNullValueSupport() + .build())); return RedisCacheManager.builder(connectionFactory) .cacheDefaults(defaults) diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java index 31c8242..9d21676 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java @@ -1,6 +1,7 @@ package com.ludovictemgoua.imdb.presentation; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import jakarta.validation.ConstraintViolationException; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -18,4 +19,13 @@ public ProblemDetail handleNotFound(NotFoundException ex) { public ProblemDetail handleBadId(IllegalArgumentException ex) { return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage()); } + + // @Validated on a @RestController triggers Spring's older AOP-based MethodValidationInterceptor, + // which throws a plain ConstraintViolationException - not the newer HandlerMethodValidationException + // that Spring MVC handles automatically. Confirmed empirically (a first pass omitted this handler on + // the assumption the newer auto-handling applied here; it doesn't for @Validated-triggered validation). + @ExceptionHandler(ConstraintViolationException.class) + public ProblemDetail handleConstraintViolation(ConstraintViolationException ex) { + return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage()); + } } diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java index adeb75b..bc73f83 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java @@ -9,7 +9,7 @@ import org.testcontainers.utility.DockerImageName; @TestConfiguration(proxyBeanMethods = false) -class TestcontainersConfiguration { +public class TestcontainersConfiguration { @Bean @ServiceConnection diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCaseTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCaseTest.java new file mode 100644 index 0000000..5d75908 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonResolutionUseCaseTest.java @@ -0,0 +1,75 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; +import com.ludovictemgoua.imdb.domain.model.PersonResolution; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class PersonResolutionUseCaseTest { + + @Mock + PersonRepository personRepository; + + @Test + void resolvesDirectlyByIdWithoutSearchingByName() { + given(personRepository.findNameById(102)).willReturn(Optional.of("Kevin Bacon")); + + var resolution = new PersonResolutionUseCase(personRepository).resolve("nm0000102"); + + assertThat(resolution).isInstanceOfSatisfying(PersonResolution.Resolved.class, resolved -> { + assertThat(resolved.nconst()).isEqualTo(102); + assertThat(resolved.name()).isEqualTo("Kevin Bacon"); + }); + } + + @Test + void unknownIdIsNotFound() { + given(personRepository.findNameById(999)).willReturn(Optional.empty()); + + var resolution = new PersonResolutionUseCase(personRepository).resolve("nm0000999"); + + assertThat(resolution).isInstanceOf(PersonResolution.NotFound.class); + } + + @Test + void singleNameMatchResolves() { + given(personRepository.findByName("Kevin Bacon")) + .willReturn(List.of(new PersonCandidate("nm0000102", "Kevin Bacon", 1958, List.of()))); + + var resolution = new PersonResolutionUseCase(personRepository).resolve("Kevin Bacon"); + + assertThat(resolution).isInstanceOfSatisfying(PersonResolution.Resolved.class, + resolved -> assertThat(resolved.nconst()).isEqualTo(102)); + } + + @Test + void multipleNameMatchesAreAmbiguous() { + given(personRepository.findByName("Jamie Lee")).willReturn(List.of( + new PersonCandidate("nm0000020", "Jamie Lee", 1975, List.of()), + new PersonCandidate("nm0000021", "Jamie Lee", 1990, List.of()))); + + var resolution = new PersonResolutionUseCase(personRepository).resolve("Jamie Lee"); + + assertThat(resolution).isInstanceOfSatisfying(PersonResolution.Ambiguous.class, + amb -> assertThat(amb.candidates()).hasSize(2)); + } + + @Test + void noNameMatchesIsNotFound() { + given(personRepository.findByName("Nobody")).willReturn(List.of()); + + var resolution = new PersonResolutionUseCase(personRepository).resolve("Nobody"); + + assertThat(resolution).isInstanceOf(PersonResolution.NotFound.class); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImplTest.java new file mode 100644 index 0000000..7b8848a --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImplTest.java @@ -0,0 +1,137 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; +import com.ludovictemgoua.imdb.domain.model.GraphPath; +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; +import com.ludovictemgoua.imdb.domain.model.SharedTitle; +import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; + +@ExtendWith(MockitoExtension.class) +class SixDegreesUseCaseImplTest { + + @Mock + PersonRepository personRepository; + @Mock + CoStarGraphRepository graphRepository; + @Mock + TitleRepository titleRepository; + + // PersonResolutionUseCase is a real collaborator here, not mocked - it's an internal, pure-logic + // helper (see its own class-level comment), not a boundary worth mocking in isolation. The real + // boundary for this test is the repositories. + private SixDegreesUseCaseImpl newUseCase() { + var personResolution = new PersonResolutionUseCase(personRepository); + return new SixDegreesUseCaseImpl(personResolution, graphRepository, personRepository, titleRepository); + } + + @Test + void sameResolvedPersonIsDegreeZeroWithoutQueryingTheGraph() { + given(personRepository.findNameById(102)).willReturn(Optional.of("Kevin Bacon")); + + var outcome = newUseCase().compute("nm0000102", "nm0000102", 7); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.Found.class, found -> { + assertThat(found.result().degree()).isZero(); + assertThat(found.result().withinRequestedMax()).isTrue(); + }); + verifyNoInteractions(graphRepository); + } + + @Test + void ambiguousNameOnFirstSideShortCircuitsBeforeResolvingSecond() { + var candidates = List.of( + new PersonCandidate("nm0000020", "Jamie Lee", 1975, List.of()), + new PersonCandidate("nm0000021", "Jamie Lee", 1990, List.of())); + given(personRepository.findByName("Jamie Lee")).willReturn(candidates); + + var outcome = newUseCase().compute("Jamie Lee", "nm0000158", 7); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.Ambiguous.class, + amb -> assertThat(amb.candidates()).hasSize(2)); + verifyNoInteractions(graphRepository); + verify(personRepository, never()).findNameById(anyInt()); + } + + @Test + void personNotFoundOnFirstSideShortCircuits() { + given(personRepository.findByName("Nobody")).willReturn(List.of()); + + var outcome = newUseCase().compute("Nobody", "nm0000158", 7); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.PersonNotFound.class, + notFound -> assertThat(notFound.query()).isEqualTo("Nobody")); + verifyNoInteractions(graphRepository); + } + + @Test + void resolvesFullAnnotatedPathWhenDegreeIsWithinRequestedMax() { + given(personRepository.findNameById(102)).willReturn(Optional.of("Kevin Bacon")); + given(personRepository.findNameById(129)).willReturn(Optional.of("Tom Cruise")); + given(graphRepository.findShortestPath(102, 129)) + .willReturn(Optional.of(new GraphPath(1, List.of(102, 129)))); + given(personRepository.findNamesByIds(List.of(102, 129))) + .willReturn(Map.of(102, "Kevin Bacon", 129, "Tom Cruise")); + given(titleRepository.findAnyCommonTitle(102, 129)) + .willReturn(Optional.of(new SharedTitle("tt0100405", "A Few Good Men"))); + + var outcome = newUseCase().compute("nm0000102", "nm0000129", 7); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.Found.class, found -> { + var result = found.result(); + assertThat(result.degree()).isEqualTo(1); + assertThat(result.withinRequestedMax()).isTrue(); + assertThat(result.path()).hasSize(2); + assertThat(result.path().get(1).sharedTitle().primaryTitle()).isEqualTo("A Few Good Men"); + }); + } + + @Test + void reportsTrueDegreeButNoPathWhenBeyondRequestedMax() { + given(personRepository.findNameById(102)).willReturn(Optional.of("Kevin Bacon")); + given(personRepository.findNameById(158)).willReturn(Optional.of("Tom Hanks")); + given(graphRepository.findShortestPath(102, 158)) + .willReturn(Optional.of(new GraphPath(5, List.of(102, 2, 3, 4, 5, 158)))); + + var outcome = newUseCase().compute("nm0000102", "nm0000158", 3); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.Found.class, found -> { + var result = found.result(); + assertThat(result.degree()).isEqualTo(5); + assertThat(result.withinRequestedMax()).isFalse(); + assertThat(result.path()).isEmpty(); + }); + verifyNoInteractions(titleRepository); + } + + @Test + void reportsNullDegreeWhenNoConnectionExistsWithinTheAbsoluteCap() { + given(personRepository.findNameById(102)).willReturn(Optional.of("Kevin Bacon")); + given(personRepository.findNameById(999)).willReturn(Optional.of("Nobody Connected")); + given(graphRepository.findShortestPath(102, 999)).willReturn(Optional.empty()); + + var outcome = newUseCase().compute("nm0000102", "nm0000999", 7); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.Found.class, found -> { + assertThat(found.result().degree()).isNull(); + assertThat(found.result().withinRequestedMax()).isFalse(); + assertThat(found.result().path()).isEmpty(); + }); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImplTest.java new file mode 100644 index 0000000..2f45cd6 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImplTest.java @@ -0,0 +1,73 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.CastMember; +import com.ludovictemgoua.imdb.domain.model.CreditedPerson; +import com.ludovictemgoua.imdb.domain.model.TitleCore; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class TitleDetailUseCaseImplTest { + + @Mock + TitleRepository titleRepository; + + @Test + void assemblesTitleDetailFromFiveRepositoryCalls() { + var core = new TitleCore("tt0111161", "The Shawshank Redemption", "The Shawshank Redemption", + "movie", 1994, null, 142, List.of("Drama"), 9.3, 2900000); + given(titleRepository.findCore(111161)).willReturn(Optional.of(core)); + given(titleRepository.findDirectors(111161)) + .willReturn(List.of(new CreditedPerson("nm0001104", "Frank Darabont"))); + given(titleRepository.findWriters(111161)) + .willReturn(List.of(new CreditedPerson("nm0001104", "Frank Darabont"))); + given(titleRepository.findTopCast(111161, 20)) + .willReturn(List.of(new CastMember("nm0000209", "Tim Robbins", "actor", + List.of("Andy Dufresne"), 1))); + given(titleRepository.countCast(111161)).willReturn(20); + + var detail = new TitleDetailUseCaseImpl(titleRepository).getDetail("tt0111161"); + + assertThat(detail.id()).isEqualTo("tt0111161"); + assertThat(detail.rating().average()).isEqualTo(9.3); + assertThat(detail.rating().numVotes()).isEqualTo(2900000); + assertThat(detail.directors()).hasSize(1); + assertThat(detail.cast()).hasSize(1); + assertThat(detail.castTotalCount()).isEqualTo(20); + } + + @Test + void missingCoreThrowsNotFound() { + given(titleRepository.findCore(111161)).willReturn(Optional.empty()); + + assertThatThrownBy(() -> new TitleDetailUseCaseImpl(titleRepository).getDetail("tt0111161")) + .isInstanceOf(NotFoundException.class); + } + + @Test + void nullRatingFieldsDefaultToZeroRatherThanNull() { + var core = new TitleCore("tt9999999", "Unrated Title", "Unrated Title", + "movie", null, null, null, List.of(), null, null); + given(titleRepository.findCore(9999999)).willReturn(Optional.of(core)); + given(titleRepository.findDirectors(9999999)).willReturn(List.of()); + given(titleRepository.findWriters(9999999)).willReturn(List.of()); + given(titleRepository.findTopCast(9999999, 20)).willReturn(List.of()); + given(titleRepository.countCast(9999999)).willReturn(0); + + var detail = new TitleDetailUseCaseImpl(titleRepository).getDetail("tt9999999"); + + assertThat(detail.rating().average()).isZero(); + assertThat(detail.rating().numVotes()).isZero(); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImplTest.java new file mode 100644 index 0000000..6b37ae0 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleSearchUseCaseImplTest.java @@ -0,0 +1,34 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class TitleSearchUseCaseImplTest { + + @Mock + TitleRepository titleRepository; + + @Test + void delegatesSearchToTheRepositoryUnchanged() { + var expected = new PagedResult<>( + List.of(new TitleSummary("tt0111161", "The Shawshank Redemption", + "The Shawshank Redemption", "movie", 1994, null)), + 1, 0, 20); + given(titleRepository.search("shawshank", 0, 20)).willReturn(expected); + + var result = new TitleSearchUseCaseImpl(titleRepository).search("shawshank", 0, 20); + + assertThat(result).isSameAs(expected); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImplTest.java new file mode 100644 index 0000000..004318b --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TopRatedUseCaseImplTest.java @@ -0,0 +1,41 @@ +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class TopRatedUseCaseImplTest { + + @Mock + TitleRepository titleRepository; + + @Test + void fallsBackToTheConfiguredDefaultWhenMinVotesIsNotProvided() { + var expected = List.of(new GenreTopRatedItem("tt0111161", "The Shawshank Redemption", + 1994, 9.3, 2900000, 9.2)); + given(titleRepository.findTopRated("Drama", 10, 1000)).willReturn(expected); + + var result = new TopRatedUseCaseImpl(titleRepository, 1000).findTopRated("Drama", 10, null); + + assertThat(result).isSameAs(expected); + } + + @Test + void usesTheCallerSuppliedMinVotesWhenPresent() { + var expected = List.of(); + given(titleRepository.findTopRated("Drama", 10, 50000)).willReturn(expected); + + var result = new TopRatedUseCaseImpl(titleRepository, 1000).findTopRated("Drama", 10, 50000); + + assertThat(result).isSameAs(expected); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryTest.java new file mode 100644 index 0000000..101aa70 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryTest.java @@ -0,0 +1,69 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.domain.model.GraphPath; +import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import com.ludovictemgoua.imdb.infrastructure.persistence.JdbcCoStarGraphRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = CachingCoStarGraphRepositoryTest.CacheTestConfig.class) +class CachingCoStarGraphRepositoryTest { + + @Configuration + @EnableCaching + static class CacheTestConfig { + @Bean + CacheManager cacheManager() { + return new ConcurrentMapCacheManager("six-degrees"); + } + + @Bean + JdbcCoStarGraphRepository delegate() { + return mock(JdbcCoStarGraphRepository.class); + } + + // @Primary here (not just on the class) - see CachingTitleSearchUseCaseTest for why. + @Bean + @org.springframework.context.annotation.Primary + CachingCoStarGraphRepository cachingCoStarGraphRepository(JdbcCoStarGraphRepository delegate) { + return new CachingCoStarGraphRepository(delegate); + } + } + + // Typed by interface - see CachingTitleSearchUseCaseTest for why the concrete class doesn't work. + @Autowired + CoStarGraphRepository target; + @Autowired + JdbcCoStarGraphRepository delegate; + + @Test + void sameUnorderedPairSharesOneCacheEntryRegardlessOfArgumentOrder() { + given(delegate.findShortestPath(1, 2)).willReturn(Optional.of(new GraphPath(1, List.of(1, 2)))); + + var first = target.findShortestPath(1, 2); + var second = target.findShortestPath(2, 1); + + assertThat(first).isEqualTo(second); + verify(delegate, times(1)).findShortestPath(1, 2); + verify(delegate, never()).findShortestPath(2, 1); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseTest.java new file mode 100644 index 0000000..d8de2ba --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseTest.java @@ -0,0 +1,68 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.TitleDetailUseCaseImpl; +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.domain.model.RatingView; +import com.ludovictemgoua.imdb.domain.model.TitleDetail; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = CachingTitleDetailUseCaseTest.CacheTestConfig.class) +class CachingTitleDetailUseCaseTest { + + @Configuration + @EnableCaching + static class CacheTestConfig { + @Bean + CacheManager cacheManager() { + return new ConcurrentMapCacheManager("title-detail"); + } + + @Bean + TitleDetailUseCaseImpl delegate() { + return mock(TitleDetailUseCaseImpl.class); + } + + // @Primary here (not just on the class) - see CachingTitleSearchUseCaseTest for why. + @Bean + @org.springframework.context.annotation.Primary + CachingTitleDetailUseCase cachingTitleDetailUseCase(TitleDetailUseCaseImpl delegate) { + return new CachingTitleDetailUseCase(delegate); + } + } + + // Typed by interface - see CachingTitleSearchUseCaseTest for why the concrete class doesn't work. + @Autowired + TitleDetailUseCase target; + @Autowired + TitleDetailUseCaseImpl delegate; + + @Test + void secondCallWithTheSameTitleIdIsServedFromCache() { + var detail = new TitleDetail("tt0111161", "The Shawshank Redemption", "The Shawshank Redemption", + "movie", 1994, null, 142, List.of("Drama"), new RatingView(9.3, 2900000), + List.of(), List.of(), List.of(), 0); + given(delegate.getDetail("tt0111161")).willReturn(detail); + + target.getDetail("tt0111161"); + target.getDetail("tt0111161"); + + verify(delegate, times(1)).getDetail("tt0111161"); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseTest.java new file mode 100644 index 0000000..3d42031 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseTest.java @@ -0,0 +1,85 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.TitleSearchUseCaseImpl; +import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +// A slice test, not a full @SpringBootTest: only caching infrastructure + a mock delegate, no +// database or Testcontainers. This is the mechanical check the old DistanceCache design (LLD §2.1) +// needed reasoning about carefully to get right; now it's just "does @Cacheable actually cache." +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = CachingTitleSearchUseCaseTest.CacheTestConfig.class) +class CachingTitleSearchUseCaseTest { + + @Configuration + @EnableCaching + static class CacheTestConfig { + @Bean + CacheManager cacheManager() { + return new ConcurrentMapCacheManager("title-search"); + } + + @Bean + TitleSearchUseCaseImpl delegate() { + return mock(TitleSearchUseCaseImpl.class); + } + + // @Primary here (not just on the class): a @Bean factory method doesn't inherit @Primary from + // the returned object's runtime class the way component-scanning a @Service does in production - + // it must be declared on the method itself to disambiguate against the delegate bean below. + @Bean + @org.springframework.context.annotation.Primary + CachingTitleSearchUseCase cachingTitleSearchUseCase(TitleSearchUseCaseImpl delegate) { + return new CachingTitleSearchUseCase(delegate); + } + } + + // Typed by interface, not the concrete CachingTitleSearchUseCase: @EnableCaching proxies any bean + // with @Cacheable methods, and since this bean implements an interface, Spring defaults to a JDK + // dynamic proxy - which satisfies the interface type but is not assignable to the concrete class. + @Autowired + TitleSearchUseCase target; + @Autowired + TitleSearchUseCaseImpl delegate; + + @Test + void secondCallWithIdenticalArgumentsIsServedFromCacheNotTheDelegate() { + var result = new PagedResult(List.of(), 0, 0, 20); + given(delegate.search("matrix", 0, 20)).willReturn(result); + + target.search("matrix", 0, 20); + target.search("matrix", 0, 20); + + verify(delegate, times(1)).search("matrix", 0, 20); + } + + @Test + void differentArgumentsAreNotConflated() { + given(delegate.search("matrix", 0, 20)).willReturn(new PagedResult<>(List.of(), 0, 0, 20)); + given(delegate.search("inception", 0, 20)).willReturn(new PagedResult<>(List.of(), 0, 0, 20)); + + target.search("matrix", 0, 20); + target.search("inception", 0, 20); + + verify(delegate, times(1)).search("matrix", 0, 20); + verify(delegate, times(1)).search("inception", 0, 20); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseTest.java new file mode 100644 index 0000000..1b32aec --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseTest.java @@ -0,0 +1,65 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.TopRatedUseCaseImpl; +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.concurrent.ConcurrentMapCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(SpringExtension.class) +@ContextConfiguration(classes = CachingTopRatedUseCaseTest.CacheTestConfig.class) +class CachingTopRatedUseCaseTest { + + @Configuration + @EnableCaching + static class CacheTestConfig { + @Bean + CacheManager cacheManager() { + return new ConcurrentMapCacheManager("top-rated"); + } + + @Bean + TopRatedUseCaseImpl delegate() { + return mock(TopRatedUseCaseImpl.class); + } + + // @Primary here (not just on the class) - see CachingTitleSearchUseCaseTest for why. + @Bean + @org.springframework.context.annotation.Primary + CachingTopRatedUseCase cachingTopRatedUseCase(TopRatedUseCaseImpl delegate) { + return new CachingTopRatedUseCase(delegate); + } + } + + // Typed by interface - see CachingTitleSearchUseCaseTest for why the concrete class doesn't work. + @Autowired + TopRatedUseCase target; + @Autowired + TopRatedUseCaseImpl delegate; + + @Test + void secondCallWithTheSameArgumentsIsServedFromCache() { + List result = List.of(); + given(delegate.findTopRated("Drama", 10, 1000)).willReturn(result); + + target.findTopRated("Drama", 10, 1000); + target.findTopRated("Drama", 10, 1000); + + verify(delegate, times(1)).findTopRated("Drama", 10, 1000); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepositoryIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepositoryIntegrationTest.java new file mode 100644 index 0000000..c433cb0 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepositoryIntegrationTest.java @@ -0,0 +1,54 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class JdbcCoStarGraphRepositoryIntegrationTest { + + @Autowired + JdbcCoStarGraphRepository repository; + + @Test + void directCoStarsAreOneDegreeApart() { + var path = repository.findShortestPath(1, 2).orElseThrow(); + + assertThat(path.degree()).isEqualTo(1); + assertThat(path.personIds()).containsExactly(1, 2); + } + + @Test + void findsTheShortestPathAcrossMultipleHopsOnBothSidesOfTheBidirectionalSearch() { + // 1-2-3-4-5-6: five edges, so this exercises the bidirectional CTE meeting in the middle + // (sideCap=4 per side, LLD §5.1/§5.2) rather than a single-hop lookup. + var path = repository.findShortestPath(1, 6).orElseThrow(); + + assertThat(path.degree()).isEqualTo(5); + assertThat(path.personIds()).containsExactly(1, 2, 3, 4, 5, 6); + } + + @Test + void isOrderIndependent() { + var forward = repository.findShortestPath(1, 6).orElseThrow(); + var backward = repository.findShortestPath(6, 1).orElseThrow(); + + assertThat(forward.degree()).isEqualTo(backward.degree()); + } + + @Test + void returnsEmptyWhenThePersonHasNoCoStars() { + // person 7 is the only credited principal on their one title - co_star_edges has no row for + // them at all. + assertThat(repository.findShortestPath(1, 7)).isEmpty(); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java new file mode 100644 index 0000000..675e389 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java @@ -0,0 +1,55 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class JdbcPersonRepositoryIntegrationTest { + + @Autowired + JdbcPersonRepository repository; + + @Test + void findByNameReturnsBothPeopleSharingAName() { + var candidates = repository.findByName("Jamie Lee"); + + assertThat(candidates).extracting("id").containsExactlyInAnyOrder("nm0000020", "nm0000021"); + } + + @Test + void findByNameReturnsExactlyOneMatchForAUniqueName() { + var candidates = repository.findByName("Kevin Bacon"); + + assertThat(candidates).extracting("id").containsExactly("nm0000001"); + } + + @Test + void findNameByIdResolvesAKnownPerson() { + assertThat(repository.findNameById(1)).contains("Kevin Bacon"); + } + + @Test + void findNameByIdIsEmptyForAnUnknownPerson() { + assertThat(repository.findNameById(987654)).isEmpty(); + } + + @Test + void findNamesByIdsBatchResolvesMultiplePeople() { + var names = repository.findNamesByIds(List.of(1, 6, 987654)); + + assertThat(names).containsEntry(1, "Kevin Bacon").containsEntry(6, "Tom Hanks"); + assertThat(names).doesNotContainKey(987654); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java new file mode 100644 index 0000000..5efc523 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java @@ -0,0 +1,79 @@ +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class JdbcTitleRepositoryIntegrationTest { + + @Autowired + JdbcTitleRepository repository; + + @Test + void searchFindsATitleByFuzzyPrimaryTitleMatch() { + var results = repository.search("Few Good Men", 0, 20); + + assertThat(results.content()).extracting("id").contains("tt0000100"); + } + + @Test + void findCoreReturnsMetadataAndRating() { + var core = repository.findCore(100).orElseThrow(); + + assertThat(core.primaryTitle()).isEqualTo("A Few Good Men"); + assertThat(core.averageRating()).isEqualTo(8.0); + assertThat(core.numVotes()).isEqualTo(500000); + assertThat(core.genres()).containsExactly("Drama"); + } + + @Test + void findCoreIsEmptyForUnknownTitle() { + assertThat(repository.findCore(987654)).isEmpty(); + } + + @Test + void findDirectorsAndWritersUnnestTheCrewArrays() { + assertThat(repository.findDirectors(100)).extracting("name").containsExactly("Rob Reiner"); + assertThat(repository.findWriters(100)).extracting("name").containsExactly("Aaron Sorkin"); + } + + @Test + void findTopCastOrdersByBillingAndCountCastMatchesTotal() { + var cast = repository.findTopCast(100, 20); + + assertThat(cast).extracting("name").containsExactly("Kevin Bacon", "Tom Cruise"); + assertThat(repository.countCast(100)).isEqualTo(2); + } + + @Test + void findAnyCommonTitleFindsTheSharedCredit() { + var shared = repository.findAnyCommonTitle(1, 2).orElseThrow(); + + assertThat(shared.primaryTitle()).isEqualTo("A Few Good Men"); + } + + @Test + void findAnyCommonTitleIsEmptyWhenTheyNeverCoStarred() { + assertThat(repository.findAnyCommonTitle(1, 6)).isEmpty(); + } + + @Test + void findTopRatedRanksByWeightedRatingNotRawAverage() { + // 201's raw average (10.0) beats 200's (8.9), but at minVotes=100 the Bayesian shrinkage + // (PDD §9) pulls 201 down toward the pool mean enough that 200 - backed by 500,000 votes - + // still ranks first. See the fixture comment for the arithmetic this depends on. + var topRated = repository.findTopRated("Action", 10, 100); + + assertThat(topRated).extracting("id").startsWith("tt0000200", "tt0000201"); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/GenreControllerTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/GenreControllerTest.java new file mode 100644 index 0000000..c5ff5aa --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/GenreControllerTest.java @@ -0,0 +1,44 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(GenreController.class) +class GenreControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + TopRatedUseCase topRatedUseCase; + + @Test + void rejectsLimitAboveOneHundred() throws Exception { + mockMvc.perform(get("/api/v1/genres/Drama/top-rated").param("limit", "500")) + .andExpect(status().isBadRequest()); + } + + @Test + void returnsTheRankedListFromTheUseCase() throws Exception { + given(topRatedUseCase.findTopRated(eq("Drama"), eq(10), isNull())) + .willReturn(List.of(new GenreTopRatedItem("tt0111161", "The Shawshank Redemption", + 1994, 9.3, 2900000, 9.2))); + + mockMvc.perform(get("/api/v1/genres/Drama/top-rated")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].id").value("tt0111161")); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java new file mode 100644 index 0000000..98b7cb4 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java @@ -0,0 +1,80 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.PathStep; +import com.ludovictemgoua.imdb.application.PersonRef; +import com.ludovictemgoua.imdb.application.SixDegreesResult; +import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; +import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase; +import com.ludovictemgoua.imdb.domain.model.PersonCandidate; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(PersonController.class) +class PersonControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + SixDegreesUseCase sixDegreesUseCase; + + @Test + void rejectsMaxDegreeAboveSeven() throws Exception { + mockMvc.perform(get("/api/v1/people/six-degrees") + .param("personA", "nm0000102") + .param("personB", "nm0000158") + .param("maxDegree", "9")) + .andExpect(status().isBadRequest()); + } + + @Test + void returnsTheResultWhenFound() throws Exception { + var personA = new PersonRef("nm0000102", "Kevin Bacon"); + var personB = new PersonRef("nm0000158", "Tom Hanks"); + var result = new SixDegreesResult(personA, personB, 2, true, + List.of(new PathStep("nm0000102", "Kevin Bacon", null))); + given(sixDegreesUseCase.compute("nm0000102", "nm0000158", 7)) + .willReturn(new SixDegreesOutcome.Found(result)); + + mockMvc.perform(get("/api/v1/people/six-degrees") + .param("personA", "nm0000102") + .param("personB", "nm0000158")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.degree").value(2)); + } + + @Test + void returnsDisambiguationPayloadWith200WhenAmbiguous() throws Exception { + given(sixDegreesUseCase.compute("Jamie Lee", "nm0000158", 7)) + .willReturn(new SixDegreesOutcome.Ambiguous("Jamie Lee", List.of( + new PersonCandidate("nm0000020", "Jamie Lee", 1975, List.of()), + new PersonCandidate("nm0000021", "Jamie Lee", 1990, List.of())))); + + mockMvc.perform(get("/api/v1/people/six-degrees") + .param("personA", "Jamie Lee") + .param("personB", "nm0000158")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.requiresDisambiguation").value(true)) + .andExpect(jsonPath("$.candidates.length()").value(2)); + } + + @Test + void returns404WhenPersonNotFound() throws Exception { + given(sixDegreesUseCase.compute("Nobody", "nm0000158", 7)) + .willReturn(new SixDegreesOutcome.PersonNotFound("Nobody")); + + mockMvc.perform(get("/api/v1/people/six-degrees") + .param("personA", "Nobody") + .param("personB", "nm0000158")) + .andExpect(status().isNotFound()); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java new file mode 100644 index 0000000..7162926 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java @@ -0,0 +1,63 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(TitleController.class) +class TitleControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + TitleSearchUseCase titleSearchUseCase; + @MockitoBean + TitleDetailUseCase titleDetailUseCase; + + @Test + void searchRequiresANonBlankTitleParam() throws Exception { + mockMvc.perform(get("/api/v1/titles/search").param("title", "")) + .andExpect(status().isBadRequest()); + } + + @Test + void searchRejectsPageSizeAboveOneHundred() throws Exception { + mockMvc.perform(get("/api/v1/titles/search").param("title", "matrix").param("size", "500")) + .andExpect(status().isBadRequest()); + } + + @Test + void searchReturnsThePagedResultFromTheUseCase() throws Exception { + var summary = new TitleSummary("tt0133093", "The Matrix", "The Matrix", "movie", 1999, null); + given(titleSearchUseCase.search("matrix", 0, 20)) + .willReturn(new PagedResult<>(List.of(summary), 1, 0, 20)); + + mockMvc.perform(get("/api/v1/titles/search").param("title", "matrix")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.content[0].id").value("tt0133093")) + .andExpect(jsonPath("$.totalElements").value(1)); + } + + @Test + void getReturns404WhenTheUseCaseThrowsNotFound() throws Exception { + given(titleDetailUseCase.getDetail("tt9999999")) + .willThrow(new NotFoundException("No title with id tt9999999")); + + mockMvc.perform(get("/api/v1/titles/tt9999999")) + .andExpect(status().isNotFound()); + } +} diff --git a/imdb/src/test/resources/fixtures/fixture-data.sql b/imdb/src/test/resources/fixtures/fixture-data.sql new file mode 100644 index 0000000..9e3dec7 --- /dev/null +++ b/imdb/src/test/resources/fixtures/fixture-data.sql @@ -0,0 +1,68 @@ +-- Co-star chain: 1-2 (title 100), 2-3 (101), 3-4 (102), 4-5 (103), 5-6 (104) - a known 5-degree +-- separation between person 1 and person 6 that requires more than one hop on each side of the +-- bidirectional search (sideCap=4 per side, LLD §5.2). Person 7 is deliberately isolated (the only +-- credited principal on their one title) to exercise the "no path found" case. + +INSERT INTO name_basics (nconst, primary_name, birth_year, known_for_titles) VALUES + (1, 'Kevin Bacon', 1958, ARRAY[100]), + (2, 'Tom Cruise', 1962, ARRAY[100, 101]), + (3, 'Jack Nicholson', 1937, ARRAY[101, 102]), + (4, 'Morgan Freeman', 1937, ARRAY[102, 103]), + (5, 'Tim Robbins', 1958, ARRAY[103, 104]), + (6, 'Tom Hanks', 1956, ARRAY[104]), + (7, 'Isolated Actor', 1980, ARRAY[105]), + (10, 'Rob Reiner', 1947, ARRAY[]::integer[]), + (11, 'Aaron Sorkin', 1961, ARRAY[]::integer[]), + (20, 'Jamie Lee', 1975, ARRAY[]::integer[]), + (21, 'Jamie Lee', 1990, ARRAY[]::integer[]); + +INSERT INTO title_basics (tconst, title_type, primary_title, original_title, start_year, genres) VALUES + (100, 'movie', 'A Few Good Men', 'A Few Good Men', 1992, ARRAY['Drama']), + (101, 'movie', 'Movie B', 'Movie B', 1995, ARRAY['Drama']), + (102, 'movie', 'Movie C', 'Movie C', 1998, ARRAY['Drama']), + (103, 'movie', 'Movie D', 'Movie D', 2001, ARRAY['Drama']), + (104, 'movie', 'The Terminal', 'The Terminal', 2004, ARRAY['Drama']), + (105, 'movie', 'Solo Film', 'Solo Film', 2010, ARRAY['Drama']), + (200, 'movie', 'High Vote Solid Rating', 'High Vote Solid Rating', 2000, ARRAY['Action']), + (201, 'movie', 'Low Vote Perfect Rating', 'Low Vote Perfect Rating', 2000, ARRAY['Action']), + (202, 'movie', 'Average Movie A', 'Average Movie A', 2000, ARRAY['Action']), + (203, 'movie', 'Average Movie B', 'Average Movie B', 2000, ARRAY['Action']); + +-- The weighted-rating test case (queried with minVotes=100, PDD §9): 201's raw average (10.0) beats +-- 200's (8.9), and 201's vote count (100) exactly clears the minVotes floor - but against a realistic +-- pool mean (padded by 202/203 at 5.0), the Bayesian shrinkage pulls 201's weighted score down enough +-- that 200 - overwhelmingly supported by 500,000 votes - still ranks first. This is deliberately tuned +-- so the assertion actually exercises the formula: at minVotes = m, anything that just clears the +-- filter is shrunk exactly halfway to the pool mean, which only overturns a raw-rating gap this size +-- if the pool mean is pulled low enough by the other titles. +INSERT INTO title_ratings (tconst, average_rating, num_votes) VALUES + (100, 8.0, 500000), + (101, 7.5, 400000), + (102, 7.0, 300000), + (103, 7.8, 350000), + (104, 7.7, 450000), + (105, 6.0, 10), + (200, 8.9, 500000), + (201, 10.0, 100), + (202, 5.0, 200000), + (203, 5.0, 200000); + +INSERT INTO title_crew (tconst, directors, writers) VALUES + (100, ARRAY[10], ARRAY[11]); + +INSERT INTO title_principals (tconst, ordering, nconst, category) VALUES + (100, 1, 1, 'actor'), + (100, 2, 2, 'actor'), + (101, 1, 2, 'actor'), + (101, 2, 3, 'actor'), + (102, 1, 3, 'actor'), + (102, 2, 4, 'actor'), + (103, 1, 4, 'actor'), + (103, 2, 5, 'actor'), + (104, 1, 5, 'actor'), + (104, 2, 6, 'actor'), + (105, 1, 7, 'actor'); + +-- co_star_edges is a materialized view (LLD §3.3) - it does not auto-update when title_principals +-- changes underneath it, so every fixture load must explicitly refresh it. +REFRESH MATERIALIZED VIEW co_star_edges; From d33c75a5417d6d29cb88d994745579d5e070cb5c Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Thu, 9 Jul 2026 09:45:33 +0200 Subject: [PATCH 12/42] Fixed caching bug, tracing and monitoring system --- imdb/docker-compose.yaml | 15 +- imdb/docs/implementation-guide.md | 1205 +++++++++++++++++ imdb/docs/low-level-design.md | 199 +-- imdb/k6/data/generate-sampled-people.sql | 22 + imdb/k6/data/sampled-people.csv | 5 + imdb/k6/search.js | 33 + imdb/k6/six-degrees.js | 101 ++ imdb/k6/title-detail.js | 48 + imdb/k6/top-rated.js | 36 + imdb/observability/alloy/config.alloy | 22 +- .../dashboards/json/cache-hit-ratio.json | 60 + .../dashboards/json/http-overview.json | 75 + .../dashboards/json/k6-load-test.json | 75 + .../dashboards/json/six-degrees-latency.json | 73 + .../infrastructure/cache/CacheConfig.java | 16 + .../JdbcCoStarGraphRepository.java | 86 +- .../persistence/JdbcTitleRepository.java | 2 +- .../persistence/PathStitcher.java | 23 - imdb/src/main/resources/application.yaml | 37 +- .../V1__extensions_and_search_indexes.sql | 36 +- .../V3__shortest_co_star_path_function.sql | 149 ++ 21 files changed, 2134 insertions(+), 184 deletions(-) create mode 100644 imdb/docs/implementation-guide.md create mode 100644 imdb/k6/data/generate-sampled-people.sql create mode 100644 imdb/k6/data/sampled-people.csv create mode 100644 imdb/k6/search.js create mode 100644 imdb/k6/six-degrees.js create mode 100644 imdb/k6/title-detail.js create mode 100644 imdb/k6/top-rated.js create mode 100644 imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json create mode 100644 imdb/observability/grafana/provisioning/dashboards/json/http-overview.json create mode 100644 imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json create mode 100644 imdb/observability/grafana/provisioning/dashboards/json/six-degrees-latency.json delete mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java create mode 100644 imdb/src/main/resources/db/migration/V3__shortest_co_star_path_function.sql diff --git a/imdb/docker-compose.yaml b/imdb/docker-compose.yaml index 12d3db9..95f47a5 100644 --- a/imdb/docker-compose.yaml +++ b/imdb/docker-compose.yaml @@ -19,6 +19,10 @@ services: postgres: image: abanda/imdb-postgresql:latest container_name: imdb-postgres + # Docker's default 64MB /dev/shm is too small once Postgres runs parallel workers or shared + # hash/sort operations under real concurrent load - discovered via a k6 run failing 100% of + # requests with "could not resize shared memory segment ... No space left on device". + shm_size: 256m ports: - "5432:5432" volumes: @@ -77,6 +81,13 @@ services: condition: service_healthy redis: condition: service_healthy + # Discovered empirically: abanda/imdb-postgresql keeps bouncing its own listener while the + # background import is running (config tuning at startup, and apparent connection blips under + # the heavy COPY load), even after the healthcheck has reported healthy once. depends_on only + # gates the very first startup attempt, not ongoing availability, so a restart policy - not a + # smarter healthcheck - is what actually makes the app recover on its own instead of staying + # crashed after one bad-timing connection attempt. + restart: on-failure:5 networks: - imdb-net @@ -159,7 +170,7 @@ services: # --------------------------------------------------------------------- tempo: - image: grafana/tempo:latest + image: grafana/tempo:2.10.7 container_name: imdb-tempo command: -config.file=/etc/tempo.yaml volumes: @@ -180,7 +191,7 @@ services: image: grafana/grafana:latest container_name: imdb-grafana ports: - - "3000:3000" + - "3001:3000" environment: GF_AUTH_ANONYMOUS_ENABLED: "true" GF_AUTH_ANONYMOUS_ORG_ROLE: Admin diff --git a/imdb/docs/implementation-guide.md b/imdb/docs/implementation-guide.md new file mode 100644 index 0000000..52085b5 --- /dev/null +++ b/imdb/docs/implementation-guide.md @@ -0,0 +1,1205 @@ +# IMDb Copycat API - Implementation Guide + +| | | +|---|---| +| Author | Ludovic Temgoua Abanda | +| Status | Draft | +| Date | 2026-07-05 | +| Related docs | `low-level-design.md` (the design these classes implement), `product-design.md` | + +## How to use this document + +This is a typing companion, not a code drop - every class below is meant to be typed into your IDE +yourself so the patterns actually stick, not pasted. The order matters: each step only depends on +previous steps, so if you type them in order, the project should compile (and often run) at every +checkpoint rather than only at the very end. + +Where a pattern repeats (four nearly-identical DTOs, three controllers with the same shape), full code is +given once and the repeats are described rather than spelled out again - filling those in yourself is +where the pattern actually gets internalized, not where it gets lost. + +A few corrections surfaced while working through this that aren't yet reflected anywhere except here and +the LLD edits made alongside it - notably: Spring Boot 4.1's OTLP tracing property is +`management.opentelemetry.tracing.export.otlp.endpoint`, not the Boot-3-era `management.otlp.tracing.*`; +`springdoc-openapi` and `datasource-micrometer` aren't yet available for Boot 4.1 (both dropped, see LLD +§11); and a `V0` Flyway migration was added to create the base tables that only `abanda/imdb-postgresql` +normally provides (LLD §3.4), since a fresh Testcontainers Postgres has none of them. + +--- + +## Step 0: Fix the generated scaffolding + +Two small edits to what Spring Initializr already generated, before writing anything new. + +**`src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java`** - pin Postgres to match +production (`abanda/imdb-postgresql` runs Postgres 17): + +```java +@Bean +@ServiceConnection +PostgreSQLContainer postgresContainer() { + return new PostgreSQLContainer(DockerImageName.parse("postgres:17")); +} +``` + +Leave the `LgtmStackContainer` and Redis beans as generated - they're genuinely useful for +`TestImdbApplication`'s local dev-run convenience (full tracing/metrics without needing +`docker-compose up`). Flyway will run automatically against whichever Postgres connection is active +(the Testcontainers one here, or `docker-compose.yaml`'s real one at runtime) - that's what makes `V0` +(next step) necessary. + +**`src/main/resources/application.yaml`** - replace the generated one-liner with: + +```yaml +spring: + application: + name: imdb + datasource: + url: jdbc:postgresql://localhost:5432/imdb + username: imdb + password: password + data: + redis: + host: localhost + port: 6379 + flyway: + enabled: true + +management: + endpoints: + web: + exposure: + include: health, prometheus + tracing: + sampling: + probability: 1.0 + opentelemetry: + tracing: + export: + otlp: + endpoint: http://localhost:4318/v1/traces + +six-degrees: + side-cap: 4 + absolute-max-degree: 7 + fan-out-cap: 200 + query-timeout-seconds: 2 + +top-rated: + default-min-votes: 1000 +``` + +The `spring.datasource`/`data.redis` values here are the `localhost` defaults for running the app +directly against `docker-compose up`'s exposed ports; `docker-compose.yaml`'s `imdb-service` environment +variables (already in place) override these to the in-network hostnames (`postgres`, `redis`, `tempo`) +when the app itself runs as a compose service instead. The `six-degrees.*` and `top-rated.*` blocks are +our own custom properties (LLD §5.2, §11) - Spring Boot automatically makes any `key: value` under a +namespace bindable via `@ConfigurationProperties`, which the services below use instead of hardcoding +these numbers. + +**Checkpoint**: `./mvnw compile` should still succeed (nothing new to compile yet, just config). + +--- + +## Step 1: Database migrations + +Three files under `src/main/resources/db/migration/`. Flyway orders by version number, not filename +creation order, so `V0` runs first even though it's documented last in the LLD. + +- `V0__base_schema.sql` - copy verbatim from LLD §3.4. +- `V1__extensions_and_search_indexes.sql` - copy verbatim from LLD §3.2 (note the `genres` index is on + the *expression* `(genres::text[])`, not the bare column - LLD §3.2 explains why). +- `V2__co_star_edges_materialized_view.sql` - copy verbatim from LLD §3.3. + +**Checkpoint**: run `TestImdbApplication.main()` (or `./mvnw spring-boot:test-run`). It should start +cleanly, spinning up Postgres/Redis/Grafana-LGTM Testcontainers and applying all three migrations. Check +the logs for `Successfully applied 3 migrations`. + +--- + +## Step 2: `ImdbIds` - the id-translation utility + +`src/main/java/com/ludovictemgoua/imdb/ImdbIds.java` (root package - both the `web` and `repository` +layers need it, so it doesn't belong to either): + +```java +package com.ludovictemgoua.imdb; + +public final class ImdbIds { + + private ImdbIds() {} + + public static int parseTitleId(String tt) { + return Integer.parseInt(requirePrefix(tt, "tt")); + } + + public static int parsePersonId(String nm) { + return Integer.parseInt(requirePrefix(nm, "nm")); + } + + public static String formatTitleId(int tconst) { + return "tt" + pad7(tconst); + } + + public static String formatPersonId(int nconst) { + return "nm" + pad7(nconst); + } + + private static String requirePrefix(String id, String prefix) { + if (id == null || !id.startsWith(prefix) || id.length() <= prefix.length()) { + throw new IllegalArgumentException("Expected an id starting with '" + prefix + "': " + id); + } + return id.substring(prefix.length()); + } + + private static String pad7(int value) { + return String.format("%07d", value); + } +} +``` + +`IllegalArgumentException` is deliberate here, not a custom exception type - `ApiExceptionHandler` (Step +5) maps it straight to a 400, and there's no other behavior anyone would ever want from a malformed id. + +--- + +## Step 3: DTOs + +All records, all in `src/main/java/com/ludovictemgoua/imdb/web/dto/`. One file per record, matching this +monorepo's `votee` convention. + +```java +public record TitleSummary(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear) {} + +public record RatingView(double average, int numVotes) {} + +public record CreditedPerson(String id, String name) {} + +public record CastMember(String id, String name, String category, java.util.List characters, + int ordering) {} + +public record TitleDetail(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + java.util.List genres, RatingView rating, + java.util.List directors, java.util.List writers, + java.util.List cast, int castTotalCount) {} + +public record GenreTopRatedItem(String id, String primaryTitle, Integer startYear, double averageRating, + int numVotes, double weightedRating) {} + +public record PersonRef(String id, String name) {} + +public record SharedTitle(String id, String primaryTitle) {} + +public record PathStep(String id, String name, SharedTitle sharedTitle) {} + +public record SixDegreesResult(PersonRef personA, PersonRef personB, Integer degree, + boolean withinRequestedMax, java.util.List path) {} + +public record PersonCandidate(String id, String name, Integer birthYear, java.util.List knownFor) {} + +public record PagedResult(java.util.List content, long totalElements, int page, int size) {} +``` + +Two things worth noticing rather than just typing past: + +- `SixDegreesResult.degree` is `Integer`, not `int` - `null` means "no connection exists within the + absolute 7-degree cap at all," which is a different thing from `withinRequestedMax=false` (a connection + exists, just beyond what the caller asked for). +- `PagedResult` replaces the `Page` the LLD described in prose (§4.1) - `org.springframework.data.domain.Page` + is a Spring Data type, and §3.1 already decided against pulling in Spring Data's abstractions for a + plain-JDBC codebase. It also sidesteps a real gotcha: Jackson cannot cleanly deserialize into the `Page` + *interface* on a Redis cache read (it needs a concrete, directly-instantiable type), which our own + simple record has no trouble with. + +Use fully-qualified `java.util.List` inline above only to keep this guide's code blocks self-contained - +in your actual files, add a normal `import java.util.List;` and drop the prefix, same for every DTO. + +--- + +## Step 4: Repositories + +`src/main/java/com/ludovictemgoua/imdb/repository/`. This is where `NamedParameterJdbcTemplate` (already +autoconfigured by `spring-boot-starter-jdbc` - no config class needed for it) does all the work. + +### `TitleRepository` + +```java +package com.ludovictemgoua.imdb.repository; + +import com.ludovictemgoua.imdb.ImdbIds; +import com.ludovictemgoua.imdb.web.dto.*; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Repository +public class TitleRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public TitleRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + public PagedResult search(String query, int page, int size) { + String dataSql = """ + SELECT tconst, primary_title, original_title, title_type, start_year, end_year + FROM title_basics + WHERE primary_title % :query OR original_title % :query + ORDER BY similarity(primary_title, :query) DESC + LIMIT :limit OFFSET :offset + """; + String countSql = """ + SELECT count(*) FROM title_basics + WHERE primary_title % :query OR original_title % :query + """; + var params = new MapSqlParameterSource() + .addValue("query", query) + .addValue("limit", size) + .addValue("offset", (long) page * size); + + List content = jdbc.query(dataSql, params, TitleRepository::mapSummary); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + public Optional findCore(int tconst) { + String sql = """ + SELECT tb.tconst, tb.primary_title, tb.original_title, tb.title_type, + tb.start_year, tb.end_year, tb.runtime_minutes, tb.genres, + tr.average_rating, tr.num_votes + FROM title_basics tb + LEFT JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.tconst = :tconst + """; + return jdbc.query(sql, Map.of("tconst", tconst), TitleRepository::mapCore).stream().findFirst(); + } + + public List findDirectors(int tconst) { + return findCrew(tconst, "directors"); + } + + public List findWriters(int tconst) { + return findCrew(tconst, "writers"); + } + + public List findTopCast(int tconst, int limit) { + String sql = """ + SELECT tp.nconst, nb.primary_name, tp.category, tp.characters, tp.ordering + FROM title_principals tp + JOIN name_basics nb ON nb.nconst = tp.nconst + WHERE tp.tconst = :tconst + ORDER BY tp.ordering + LIMIT :limit + """; + var params = new MapSqlParameterSource().addValue("tconst", tconst).addValue("limit", limit); + return jdbc.query(sql, params, TitleRepository::mapCastMember); + } + + public int countCast(int tconst) { + Integer count = jdbc.queryForObject( + "SELECT count(*) FROM title_principals WHERE tconst = :tconst", + Map.of("tconst", tconst), Integer.class); + return count == null ? 0 : count; + } + + public List findTopRated(String genre, int limit, int minVotes) { + String sql = """ + WITH pool AS ( + SELECT tb.tconst, tb.primary_title, tb.start_year, tr.average_rating, tr.num_votes + FROM title_basics tb + JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.title_type = 'movie' + AND tb.genres::text[] @> ARRAY[:genre]::text[] + AND tr.num_votes >= :minVotes + ), + stats AS (SELECT AVG(average_rating) AS mean_rating FROM pool) + SELECT p.tconst, p.primary_title, p.start_year, p.average_rating, p.num_votes, + (p.num_votes::numeric / (p.num_votes + :minVotes)) * p.average_rating + + (:minVotes::numeric / (p.num_votes + :minVotes)) * s.mean_rating AS weighted_rating + FROM pool p CROSS JOIN stats s + ORDER BY weighted_rating DESC + LIMIT :limit + """; + var params = new MapSqlParameterSource() + .addValue("genre", genre).addValue("minVotes", minVotes).addValue("limit", limit); + return jdbc.query(sql, params, TitleRepository::mapTopRated); + } + + public Optional findAnyCommonTitle(int personA, int personB) { + String sql = """ + SELECT tb.tconst, tb.primary_title + FROM title_principals p1 + JOIN title_principals p2 ON p1.tconst = p2.tconst + JOIN title_basics tb ON tb.tconst = p1.tconst + WHERE p1.nconst = :personA AND p2.nconst = :personB + LIMIT 1 + """; + var params = new MapSqlParameterSource().addValue("personA", personA).addValue("personB", personB); + return jdbc.query(sql, params, (rs, rowNum) -> + new SharedTitle(ImdbIds.formatTitleId(rs.getInt("tconst")), rs.getString("primary_title"))) + .stream().findFirst(); + } + + private List findCrew(int tconst, String column) { + // column is only ever "directors" or "writers" below - both fixed internal literals, never + // user input - so string-formatting it into the SQL here isn't an injection risk. Bind + // parameters can't stand in for column/identifier names, only values. + String sql = """ + SELECT nb.nconst, nb.primary_name + FROM title_crew tc + CROSS JOIN LATERAL unnest(tc.%s) AS crew(nconst) + JOIN name_basics nb ON nb.nconst = crew.nconst + WHERE tc.tconst = :tconst + """.formatted(column); + return jdbc.query(sql, Map.of("tconst", tconst), + (rs, rowNum) -> new CreditedPerson( + ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"))); + } + + private static TitleSummary mapSummary(ResultSet rs, int rowNum) throws SQLException { + return new TitleSummary( + ImdbIds.formatTitleId(rs.getInt("tconst")), + rs.getString("primary_title"), rs.getString("original_title"), rs.getString("title_type"), + (Integer) rs.getObject("start_year"), (Integer) rs.getObject("end_year")); + } + + private static TitleCore mapCore(ResultSet rs, int rowNum) throws SQLException { + List genres = toStringList(rs.getArray("genres")); + var avgRating = rs.getBigDecimal("average_rating"); + return new TitleCore( + ImdbIds.formatTitleId(rs.getInt("tconst")), + rs.getString("primary_title"), rs.getString("original_title"), rs.getString("title_type"), + (Integer) rs.getObject("start_year"), (Integer) rs.getObject("end_year"), + (Integer) rs.getObject("runtime_minutes"), genres, + avgRating == null ? null : avgRating.doubleValue(), + (Integer) rs.getObject("num_votes")); + } + + private static CastMember mapCastMember(ResultSet rs, int rowNum) throws SQLException { + return new CastMember( + ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"), + rs.getString("category"), toStringList(rs.getArray("characters")), rs.getInt("ordering")); + } + + private static GenreTopRatedItem mapTopRated(ResultSet rs, int rowNum) throws SQLException { + return new GenreTopRatedItem( + ImdbIds.formatTitleId(rs.getInt("tconst")), rs.getString("primary_title"), + (Integer) rs.getObject("start_year"), rs.getBigDecimal("average_rating").doubleValue(), + rs.getInt("num_votes"), rs.getBigDecimal("weighted_rating").doubleValue()); + } + + private static List toStringList(Array sqlArray) throws SQLException { + if (sqlArray == null) return List.of(); + return List.of((String[]) sqlArray.getArray()); + } + + public record TitleCore(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, Double averageRating, Integer numVotes) {} +} +``` + +`TitleCore` is `public` (nested inside `TitleRepository`) rather than living in `web.dto` - it's an +internal assembly shape `TitleDetailService` composes into the real `TitleDetail` DTO, not something we +ever hand back over the wire directly. + +### `PersonRepository` + +```java +package com.ludovictemgoua.imdb.repository; + +import com.ludovictemgoua.imdb.ImdbIds; +import com.ludovictemgoua.imdb.web.dto.PersonCandidate; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; +import java.util.stream.Collectors; + +@Repository +public class PersonRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public PersonRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + public List findByName(String name) { + String sql = """ + SELECT nconst, primary_name, birth_year, known_for_titles + FROM name_basics + WHERE primary_name % :name + ORDER BY similarity(primary_name, :name) DESC + LIMIT 10 + """; + return jdbc.query(sql, Map.of("name", name), PersonRepository::mapCandidate); + } + + public Optional findNameById(int nconst) { + return jdbc.query("SELECT primary_name FROM name_basics WHERE nconst = :nconst", + Map.of("nconst", nconst), (rs, rowNum) -> rs.getString("primary_name")) + .stream().findFirst(); + } + + public Map findNamesByIds(Collection nconsts) { + if (nconsts.isEmpty()) return Map.of(); + String sql = "SELECT nconst, primary_name FROM name_basics WHERE nconst IN (:nconsts)"; + List> rows = jdbc.query(sql, Map.of("nconsts", nconsts), + (rs, rowNum) -> Map.entry(rs.getInt("nconst"), rs.getString("primary_name"))); + return rows.stream().collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + private static PersonCandidate mapCandidate(ResultSet rs, int rowNum) throws SQLException { + Array knownForArr = rs.getArray("known_for_titles"); + List knownFor = knownForArr == null ? List.of() + : Arrays.stream((Integer[]) knownForArr.getArray()) + .filter(Objects::nonNull).map(ImdbIds::formatTitleId).limit(3).toList(); + return new PersonCandidate( + ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"), + (Integer) rs.getObject("birth_year"), knownFor); + } +} +``` + +### `CoStarGraphRepository` - the centerpiece + +This is the class the entire Six Degrees comparison in the LLD (§9, §5) exists to justify. Type it +carefully - it's the one place a subtle SQL mistake changes correctness, not just style. + +```java +package com.ludovictemgoua.imdb.repository; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.stereotype.Repository; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +@Repository +public class CoStarGraphRepository { + + private final NamedParameterJdbcTemplate jdbc; + private final int sideCap; + private final int fanOutCap; + private final int absoluteMaxDegree; + + public CoStarGraphRepository( + NamedParameterJdbcTemplate jdbc, + @Value("${six-degrees.side-cap}") int sideCap, + @Value("${six-degrees.fan-out-cap}") int fanOutCap, + @Value("${six-degrees.absolute-max-degree}") int absoluteMaxDegree, + @Value("${six-degrees.query-timeout-seconds}") int queryTimeoutSeconds) { + this.jdbc = jdbc; + this.sideCap = sideCap; + this.fanOutCap = fanOutCap; + this.absoluteMaxDegree = absoluteMaxDegree; + // Only this query gets a tight timeout - it's the one query in the whole app whose cost + // depends on graph shape (hub actors) rather than a bounded index lookup. There's no + // `spring.jdbc.template.query-timeout` property to set this declaratively (checked against + // the Boot 4.1 reference docs - it doesn't exist), so it's set directly on the underlying + // JdbcTemplate instead. + ((JdbcTemplate) jdbc.getJdbcOperations()).setQueryTimeout(queryTimeoutSeconds); + } + + public Optional findShortestPath(int personA, int personB) { + String sql = """ + WITH RECURSIVE forward(person, depth, path) AS ( + SELECT :personA, 0, ARRAY[:personA] + UNION ALL + SELECT nbr.person_b, f.depth + 1, f.path || nbr.person_b + FROM forward f + CROSS JOIN LATERAL ( + SELECT e.person_b + FROM co_star_edges e + WHERE e.person_a = f.person + ORDER BY e.person_b + LIMIT :fanOutCap + ) nbr + WHERE f.depth < :sideCap + AND NOT nbr.person_b = ANY(f.path) + ), + backward(person, depth, path) AS ( + SELECT :personB, 0, ARRAY[:personB] + UNION ALL + SELECT nbr.person_b, b.depth + 1, b.path || nbr.person_b + FROM backward b + CROSS JOIN LATERAL ( + SELECT e.person_b + FROM co_star_edges e + WHERE e.person_a = b.person + ORDER BY e.person_b + LIMIT :fanOutCap + ) nbr + WHERE b.depth < :sideCap + AND NOT nbr.person_b = ANY(b.path) + ) + SELECT f.depth + b.depth AS degree, f.path AS forward_path, b.path AS backward_path + FROM forward f + JOIN backward b ON b.person = f.person + WHERE f.depth + b.depth <= :absoluteMaxDegree + ORDER BY degree ASC + LIMIT 1 + """; + var params = new MapSqlParameterSource() + .addValue("personA", personA).addValue("personB", personB) + .addValue("sideCap", sideCap).addValue("fanOutCap", fanOutCap) + .addValue("absoluteMaxDegree", absoluteMaxDegree); + + return jdbc.query(sql, params, CoStarGraphRepository::mapRawMatch).stream().findFirst(); + } + + private static RawMatch mapRawMatch(ResultSet rs, int rowNum) throws SQLException { + return new RawMatch(rs.getInt("degree"), + toIntList(rs.getArray("forward_path")), toIntList(rs.getArray("backward_path"))); + } + + private static List toIntList(Array sqlArray) throws SQLException { + return Arrays.asList((Integer[]) sqlArray.getArray()); + } + + public record RawMatch(int degree, List forwardPath, List backwardPath) {} +} +``` + +**Checkpoint**: `./mvnw compile` should succeed. This is a good point to write a throwaway `main` method +or a quick `@SpringBootTest` calling `findShortestPath` against two people you know are connected, just +to see actual rows come back, before building anything on top of it. + +--- + +## Step 5: Error handling + +`src/main/java/com/ludovictemgoua/imdb/error/`. + +```java +package com.ludovictemgoua.imdb.error; + +public class NotFoundException extends RuntimeException { + public NotFoundException(String message) { + super(message); + } +} +``` + +```java +package com.ludovictemgoua.imdb.error; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class ApiExceptionHandler { + + @ExceptionHandler(NotFoundException.class) + public ProblemDetail handleNotFound(NotFoundException ex) { + return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage()); + } + + @ExceptionHandler(IllegalArgumentException.class) + public ProblemDetail handleBadId(IllegalArgumentException ex) { + return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage()); + } +} +``` + +That's deliberately shorter than you might expect: `@Min`/`@Max` violations on `@RequestParam` (the +`maxDegree` bound, pagination sizes) already get an automatic 400 `ProblemDetail` from Spring MVC itself +(via `HandlerMethodValidationException`, handled by default since Spring Framework 6.1/Boot 3.2) - no +handler needed here for that case at all. There's no handler yet for an invalid `genre` path segment +either (production's `genre` column is a real Postgres enum, and casting an invalid value to it throws a +`DataAccessException` subtype) - add one once you've actually triggered it and seen which exact subtype +Spring's JDBC exception translator produces; guessing it here would be worse than leaving it a gap. + +--- + +## Step 6: Caching + +`src/main/java/com/ludovictemgoua/imdb/config/CacheConfig.java`: + +```java +package com.ludovictemgoua.imdb.config; + +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; + +import java.time.Duration; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Bean + public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { + RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofHours(24)) + .serializeValuesWith(RedisSerializationContext.SerializationPair + .fromSerializer(new GenericJackson2JsonRedisSerializer())); + + return RedisCacheManager.builder(connectionFactory) + .cacheDefaults(defaults) + .build(); + } +} +``` + +All four cache regions (`title-search`, `title-detail`, `top-rated`, `six-degrees`) share the same 24h TTL +per the LLD §6 table, so there's nothing to register per-name yet - `@Cacheable(cacheNames = "...")` on +the service methods (next step) creates each cache on first use from these defaults. If a region ever +needs its own TTL, `.withCacheConfiguration("name", customConfig)` is the extension point. + +Using `GenericJackson2JsonRedisSerializer` (JSON in Redis, human-readable with `redis-cli GET`) instead of +the default JDK serialization is why every DTO being a plain record (Step 3) matters - records serialize +to/from JSON with zero extra configuration. + +--- + +## Step 7: Services + +`src/main/java/com/ludovictemgoua/imdb/service/`. + +### The two sealed result types + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.web.dto.PersonCandidate; + +import java.util.List; + +public sealed interface PersonResolution { + record Resolved(int nconst, String name) implements PersonResolution {} + record Ambiguous(List candidates) implements PersonResolution {} + record NotFound() implements PersonResolution {} +} +``` + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.web.dto.PersonCandidate; +import com.ludovictemgoua.imdb.web.dto.SixDegreesResult; + +import java.util.List; + +public sealed interface SixDegreesOutcome { + record Found(SixDegreesResult result) implements SixDegreesOutcome {} + record Ambiguous(String query, List candidates) implements SixDegreesOutcome {} + record PersonNotFound(String query) implements SixDegreesOutcome {} +} +``` + +These replace the `AmbiguousPersonException` the LLD's module layout (§2) originally sketched. Throwing +an exception for an *expected*, 200-status outcome (LLD §4.4 - disambiguation isn't an error) was always +a slight mismatch; a sealed interface plus an exhaustive `switch` (used in the controller, Step 8) makes +every caller handle every case at compile time instead, with no exception-as-control-flow. + +### `PersonResolutionService` + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.ImdbIds; +import com.ludovictemgoua.imdb.repository.PersonRepository; +import com.ludovictemgoua.imdb.web.dto.PersonCandidate; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class PersonResolutionService { + + private final PersonRepository personRepository; + + public PersonResolutionService(PersonRepository personRepository) { + this.personRepository = personRepository; + } + + public PersonResolution resolve(String query) { + if (query.startsWith("nm")) { + int nconst = ImdbIds.parsePersonId(query); + return personRepository.findNameById(nconst) + .map(name -> new PersonResolution.Resolved(nconst, name)) + .orElseGet(PersonResolution.NotFound::new); + } + List candidates = personRepository.findByName(query); + return switch (candidates.size()) { + case 0 -> new PersonResolution.NotFound(); + case 1 -> { + PersonCandidate only = candidates.get(0); + yield new PersonResolution.Resolved(ImdbIds.parsePersonId(only.id()), only.name()); + } + default -> new PersonResolution.Ambiguous(candidates); + }; + } +} +``` + +### `DistanceCache` - why this is its own tiny class + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.repository.CoStarGraphRepository; +import com.ludovictemgoua.imdb.repository.CoStarGraphRepository.RawMatch; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Component; + +@Component +class DistanceCache { + + private final CoStarGraphRepository graphRepository; + + DistanceCache(CoStarGraphRepository graphRepository) { + this.graphRepository = graphRepository; + } + + @Cacheable(cacheNames = "six-degrees", + key = "T(java.lang.Math).min(#personA, #personB) + '-' + T(java.lang.Math).max(#personA, #personB)") + RawMatch trueShortestPath(int personA, int personB) { + return graphRepository.findShortestPath(personA, personB).orElse(null); + } +} +``` + +This isn't a style choice - it's a real Spring pitfall being avoided. `@Cacheable` works by wrapping the +bean in a proxy; a call from *within the same bean* (`this.trueShortestPath(...)`) bypasses that proxy +entirely and silently never hits the cache. Putting the cached method on its own small collaborator, +called from `SixDegreesService` through the injected reference, sidesteps the problem rather than +requiring everyone who touches `SixDegreesService` later to remember not to call this method internally. +The cache key deliberately ignores argument order (`min`/`max`) and any `maxDegree` - per LLD §6, the +cached value is the *true* shortest distance up to the absolute 7-degree cap, independent of what bound +any particular caller asked for. + +Returning `null` (not `Optional`) for "no path found" matches this codebase's existing convention +(`votee`'s LLD flags the same choice for `Candidate.party`) - `Optional` is for return types callers +branch on, not for storing in a field or, here, a cache entry. + +### The straightforward services + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.repository.TitleRepository; +import com.ludovictemgoua.imdb.web.dto.PagedResult; +import com.ludovictemgoua.imdb.web.dto.TitleSummary; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +@Service +public class TitleSearchService { + + private final TitleRepository titleRepository; + + public TitleSearchService(TitleRepository titleRepository) { + this.titleRepository = titleRepository; + } + + @Cacheable(cacheNames = "title-search", key = "#query + ':' + #page + ':' + #size") + public PagedResult search(String query, int page, int size) { + return titleRepository.search(query, page, size); + } +} +``` + +`TitleDetailService` and `TopRatedService` follow the exact same one-method, `@Cacheable`-wrapping shape: + +- `TitleDetailService.getDetail(String titleId)`: parse the id with `ImdbIds`, call + `titleRepository.findCore(...)` (throwing `NotFoundException` on empty), then + `findDirectors`/`findWriters`/`findTopCast`/`countCast`, and assemble a `TitleDetail` from the pieces. + Cache key is just `#titleId`. +- `TopRatedService.findTopRated(String genre, int limit, Integer minVotes)`: if `minVotes` is `null`, fall + back to the injected `${top-rated.default-min-votes}` value (this is the LLD §11/PDD §11 open item - + 1000 is a placeholder until you've looked at the real vote-count distribution), then delegate to + `titleRepository.findTopRated(...)`. Cache key is `#genre + ':' + #limit + ':' + #minVotes`. + +Writing these two yourself is the point - `TitleSearchService` above is the complete pattern; there's +nothing left to discover from having it typed out a second time. + +### `SixDegreesService` - the orchestrator + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.ImdbIds; +import com.ludovictemgoua.imdb.graph.PathStitcher; +import com.ludovictemgoua.imdb.repository.CoStarGraphRepository.RawMatch; +import com.ludovictemgoua.imdb.repository.PersonRepository; +import com.ludovictemgoua.imdb.repository.TitleRepository; +import com.ludovictemgoua.imdb.web.dto.*; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Service +public class SixDegreesService { + + private final PersonResolutionService personResolution; + private final DistanceCache distanceCache; + private final PersonRepository personRepository; + private final TitleRepository titleRepository; + + SixDegreesService(PersonResolutionService personResolution, DistanceCache distanceCache, + PersonRepository personRepository, TitleRepository titleRepository) { + this.personResolution = personResolution; + this.distanceCache = distanceCache; + this.personRepository = personRepository; + this.titleRepository = titleRepository; + } + + public SixDegreesOutcome compute(String queryA, String queryB, int maxDegree) { + PersonResolution resolvedA = personResolution.resolve(queryA); + if (resolvedA instanceof PersonResolution.Ambiguous a) { + return new SixDegreesOutcome.Ambiguous(queryA, a.candidates()); + } + if (resolvedA instanceof PersonResolution.NotFound) { + return new SixDegreesOutcome.PersonNotFound(queryA); + } + PersonResolution resolvedB = personResolution.resolve(queryB); + if (resolvedB instanceof PersonResolution.Ambiguous b) { + return new SixDegreesOutcome.Ambiguous(queryB, b.candidates()); + } + if (resolvedB instanceof PersonResolution.NotFound) { + return new SixDegreesOutcome.PersonNotFound(queryB); + } + + var a = (PersonResolution.Resolved) resolvedA; + var b = (PersonResolution.Resolved) resolvedB; + PersonRef personA = new PersonRef(ImdbIds.formatPersonId(a.nconst()), a.name()); + PersonRef personB = new PersonRef(ImdbIds.formatPersonId(b.nconst()), b.name()); + + if (a.nconst() == b.nconst()) { + PathStep onlyStep = new PathStep(personA.id(), personA.name(), null); + return new SixDegreesOutcome.Found( + new SixDegreesResult(personA, personB, 0, true, List.of(onlyStep))); + } + + RawMatch match = distanceCache.trueShortestPath(a.nconst(), b.nconst()); + if (match == null) { + return new SixDegreesOutcome.Found( + new SixDegreesResult(personA, personB, null, false, List.of())); + } + + boolean withinMax = match.degree() <= maxDegree; + List path = withinMax ? buildPath(PathStitcher.stitch(match)) : List.of(); + return new SixDegreesOutcome.Found( + new SixDegreesResult(personA, personB, match.degree(), withinMax, path)); + } + + private List buildPath(List nconsts) { + Map names = personRepository.findNamesByIds(nconsts); + List steps = new ArrayList<>(); + for (int i = 0; i < nconsts.size(); i++) { + int nconst = nconsts.get(i); + SharedTitle sharedTitle = i == 0 ? null + : titleRepository.findAnyCommonTitle(nconsts.get(i - 1), nconst).orElse(null); + steps.add(new PathStep(ImdbIds.formatPersonId(nconst), names.get(nconst), sharedTitle)); + } + return steps; + } +} +``` + +Note the early returns for `Ambiguous`/`NotFound` on `resolvedA` happen *before* resolving `queryB` at +all - no point spending a second trigram query if the first side already failed. + +### `graph/PathStitcher` + +`src/main/java/com/ludovictemgoua/imdb/graph/PathStitcher.java`: + +```java +package com.ludovictemgoua.imdb.graph; + +import com.ludovictemgoua.imdb.repository.CoStarGraphRepository.RawMatch; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public final class PathStitcher { + + private PathStitcher() {} + + public static List stitch(RawMatch match) { + List backward = new ArrayList<>(match.backwardPath()); + Collections.reverse(backward); + // forward's last element and reversed-backward's first element are the same node (where the + // two searches met) - drop the duplicate before concatenating. + List stitched = new ArrayList<>(match.forwardPath()); + stitched.addAll(backward.subList(1, backward.size())); + return stitched; + } +} +``` + +**Checkpoint**: `./mvnw compile` should succeed with the full service layer in place. + +--- + +## Step 8: Web layer + +`src/main/java/com/ludovictemgoua/imdb/web/`. + +```java +package com.ludovictemgoua.imdb.web; + +import com.ludovictemgoua.imdb.service.TitleDetailService; +import com.ludovictemgoua.imdb.service.TitleSearchService; +import com.ludovictemgoua.imdb.web.dto.PagedResult; +import com.ludovictemgoua.imdb.web.dto.TitleDetail; +import com.ludovictemgoua.imdb.web.dto.TitleSummary; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/v1/titles") +@Validated +public class TitleController { + + private final TitleSearchService searchService; + private final TitleDetailService detailService; + + public TitleController(TitleSearchService searchService, TitleDetailService detailService) { + this.searchService = searchService; + this.detailService = detailService; + } + + @GetMapping("/search") + public PagedResult search( + @RequestParam @NotBlank String title, + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return searchService.search(title, page, size); + } + + @GetMapping("/{titleId}") + public TitleDetail get(@PathVariable String titleId) { + return detailService.getDetail(titleId); + } +} +``` + +`GenreController` follows the identical shape - `@RestController` + `@RequestMapping("/api/v1/genres")` + +`@Validated`, one `@GetMapping("/{genre}/top-rated")` method taking `genre` as a `@PathVariable` and +`limit`/`minVotes` as validated `@RequestParam`s, delegating to `TopRatedService`. + +`PersonController` is the one worth typing out in full, since it's where the sealed `SixDegreesOutcome` +from Step 7 actually gets consumed: + +```java +package com.ludovictemgoua.imdb.web; + +import com.ludovictemgoua.imdb.service.SixDegreesOutcome; +import com.ludovictemgoua.imdb.service.SixDegreesService; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.http.HttpStatus; +import org.springframework.http.ProblemDetail; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequestMapping("/api/v1/people") +@Validated +public class PersonController { + + private final SixDegreesService sixDegreesService; + + public PersonController(SixDegreesService sixDegreesService) { + this.sixDegreesService = sixDegreesService; + } + + @GetMapping("/six-degrees") + public ResponseEntity sixDegrees( + @RequestParam String personA, + @RequestParam String personB, + @RequestParam(defaultValue = "7") @Min(1) @Max(7) int maxDegree) { + + SixDegreesOutcome outcome = sixDegreesService.compute(personA, personB, maxDegree); + return switch (outcome) { + case SixDegreesOutcome.Found found -> ResponseEntity.ok(found.result()); + case SixDegreesOutcome.Ambiguous amb -> ResponseEntity.ok(Map.of( + "requiresDisambiguation", true, "query", amb.query(), "candidates", amb.candidates())); + case SixDegreesOutcome.PersonNotFound nf -> ResponseEntity.status(HttpStatus.NOT_FOUND) + .body(ProblemDetail.forStatusAndDetail( + HttpStatus.NOT_FOUND, "No person matching: " + nf.query())); + }; + } +} +``` + +The `switch` over `outcome` needs no `default` branch - `SixDegreesOutcome` is `sealed` with exactly +three implementations, so the compiler already knows the switch is exhaustive. Delete one of the `case` +branches as an experiment and watch it fail to compile - that guarantee is the entire reason to reach for +a sealed interface over a plain exception or a nullable field here. + +**Checkpoint**: `./mvnw spring-boot:test-run` should let you `curl localhost:8080/api/v1/people/six-degrees?personA=nm...&personB=nm...` end to end. + +--- + +## Step 9: Tests + +One example per layer - `votee`'s existing test style (JUnit 5, Mockito, AssertJ) carries over directly. + +### Unit test (mocked collaborators, no Spring context) + +```java +package com.ludovictemgoua.imdb.service; + +import com.ludovictemgoua.imdb.repository.PersonRepository; +import com.ludovictemgoua.imdb.repository.TitleRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class SixDegreesServiceTest { + + @Mock PersonResolutionService personResolution; + @Mock DistanceCache distanceCache; + @Mock PersonRepository personRepository; + @Mock TitleRepository titleRepository; + + @Test + void sameResolvedPersonIsDegreeZero() { + var service = new SixDegreesService(personResolution, distanceCache, personRepository, titleRepository); + given(personResolution.resolve("nm0000102")) + .willReturn(new PersonResolution.Resolved(102, "Kevin Bacon")); + given(personResolution.resolve("Kevin Bacon")) + .willReturn(new PersonResolution.Resolved(102, "Kevin Bacon")); + + var outcome = service.compute("nm0000102", "Kevin Bacon", 7); + + assertThat(outcome).isInstanceOfSatisfying(SixDegreesOutcome.Found.class, + found -> assertThat(found.result().degree()).isZero()); + } +} +``` + +### Controller test (`@WebMvcTest`, real HTTP-shaped request, mocked service) + +```java +package com.ludovictemgoua.imdb.web; + +import com.ludovictemgoua.imdb.service.SixDegreesService; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(PersonController.class) +class PersonControllerTest { + + @Autowired MockMvc mockMvc; + @MockitoBean SixDegreesService sixDegreesService; + + @Test + void rejectsMaxDegreeAboveSeven() throws Exception { + mockMvc.perform(get("/api/v1/people/six-degrees") + .param("personA", "nm0000102") + .param("personB", "nm0000158") + .param("maxDegree", "9")) + .andExpect(status().isBadRequest()); + } +} +``` + +`@MockitoBean` (Spring Framework's own annotation, `org.springframework.test.context.bean.override.mockito`) +is the current replacement for the older `@MockBean` - checked against the Boot 4.1 testing reference +docs directly rather than assumed, since `@MockBean` doesn't appear there anymore. + +### Integration test (Testcontainers, real Flyway migrations, fixture data) + +```java +package com.ludovictemgoua.imdb.integration; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.repository.CoStarGraphRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Sql("/fixtures/fixture-data.sql") +class CoStarGraphRepositoryIntegrationTest { + + @Autowired CoStarGraphRepository repository; + + @Test + void findsShortestPathAcrossMultipleHopsOnBothSides() { + // pick two nconst values from your fixture-data.sql whose true shortest path requires + // more than one hop on each side of the bidirectional search + var result = repository.findShortestPath(1001, 1006); + + assertThat(result).isPresent(); + assertThat(result.get().degree()).isEqualTo(4); + } +} +``` + +`@Sql` runs *after* the Spring context (and therefore Flyway's `V0`/`V1`/`V2`) is already up, so by the +time it executes, `co_star_edges` and the rest of the schema already exist - `fixture-data.sql` only ever +needs `INSERT` statements. Write `src/test/resources/fixtures/fixture-data.sql` yourself: a small, +hand-picked set of `name_basics`/`title_basics`/`title_principals` rows forming a co-star chain you know +the answer to, per the LLD §10 test plan - designing that fixture (rather than having it handed to you) +is arguably the best way to prove to yourself the bidirectional CTE actually does what §5 claims. + +--- + +## What's left + +This covers every class in the LLD's module layout (§2) except the ones that turned out unnecessary along +the way (`JdbcConfig` - autoconfigured already; `AmbiguousPersonException` - replaced by the sealed +`SixDegreesOutcome`; `OpenApiConfig` - springdoc isn't available for Boot 4.1 yet, LLD §11). Once this +compiles and the checkpoints above all pass, the remaining LLD §11 open items apply: the k6 scripts, the +Grafana dashboard JSON, and tuning `fan-out-cap`/`side-cap`/`default-min-votes` against real data and real +load-test results instead of the placeholders used here. diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md index 5ec7022..226507a 100644 --- a/imdb/docs/low-level-design.md +++ b/imdb/docs/low-level-design.md @@ -159,8 +159,7 @@ imdb/ persistence/ JdbcTitleRepository.java JdbcPersonRepository.java - JdbcCoStarGraphRepository.java - PathStitcher.java # package-private, JdbcCoStarGraphRepository-only + JdbcCoStarGraphRepository.java # thin wrapper - the actual BFS lives in the DB, §5.2-5.3 cache/ CachingTitleSearchUseCase.java CachingTitleDetailUseCase.java @@ -465,91 +464,79 @@ If a `name` matches more than one person, the response is a disambiguation paylo error - it's an expected, common case (many people share a name), not a client mistake. `maxDegree` is validated to `1..=7` (`400` outside that range). -## 5. Six Degrees: Bidirectional Recursive CTE +## 5. Six Degrees: Bidirectional BFS as a PL/pgSQL Function ### 5.1 Why bidirectional, not the naive one-sided walk A one-sided recursive walk from person A, expanding until person B is found, pays the graph's full branching factor for every hop - and this graph has extreme hub nodes (some credited actors have -thousands of co-stars). Meeting in the middle from both ends roughly squares down the search space -(`b^(d/2)` instead of `b^d`), and combined with the product's own 7-degree cap, each side only ever needs -to expand `⌈7/2⌉ = 4` hops. See PDD §9 for the full comparison against precomputed BFS, in-memory BFS, and -Pruned Landmark Labeling. - -### 5.2 The query, and where it lives - -The bidirectional CTE below is entirely private to `infrastructure.persistence.JdbcCoStarGraphRepository`. -The `domain.repository.CoStarGraphRepository` interface it implements exposes exactly one method - -`Optional findShortestPath(int personA, int personB)` - where `GraphPath(degree, personIds)` -is already fully resolved into a single ordered chain. Nothing above the JDBC implementation ever sees -"forward path" or "backward path"; that split is an artifact of *this* algorithm, not a domain concept. -A future `Neo4jCoStarGraphRepository` (PDD §9's documented alternative) would implement the same interface -with a Cypher `shortestPath` call and no forward/backward anything, and nothing in `application` or -`presentation` would need to change. - -```sql -WITH RECURSIVE forward(person, depth, path) AS ( - SELECT :personA::int, 0, ARRAY[:personA::int] - UNION ALL - SELECT nbr.person_b, f.depth + 1, f.path || nbr.person_b - FROM forward f - CROSS JOIN LATERAL ( - SELECT e.person_b - FROM co_star_edges e - WHERE e.person_a = f.person - ORDER BY e.person_b - LIMIT :fanOutCap - ) nbr - WHERE f.depth < :sideCap - AND NOT nbr.person_b = ANY(f.path) -), -backward(person, depth, path) AS ( - SELECT :personB::int, 0, ARRAY[:personB::int] - UNION ALL - SELECT nbr.person_b, b.depth + 1, b.path || nbr.person_b - FROM backward b - CROSS JOIN LATERAL ( - SELECT e.person_b - FROM co_star_edges e - WHERE e.person_a = b.person - ORDER BY e.person_b - LIMIT :fanOutCap - ) nbr - WHERE b.depth < :sideCap - AND NOT nbr.person_b = ANY(b.path) -) -SELECT f.depth + b.depth AS degree, f.path AS forward_path, b.path AS backward_path -FROM forward f -JOIN backward b ON b.person = f.person -WHERE f.depth + b.depth <= :absoluteMaxDegree -ORDER BY degree ASC -LIMIT 1; -``` - -- `:sideCap` = 4 (fixed at `⌈7/2⌉`) and `:absoluteMaxDegree` = 7, both independent of the caller's - requested `maxDegree` - see caching rationale in §6. The explicit `WHERE` matters: with `sideCap=4` on - each side, the two CTEs can meet at combined depth 8, one more than the product's absolute cap. Without - this filter that would surface as a spurious "degree 8" answer; with it, no matching row means - `findShortestPath` cleanly returns `Optional.empty()` - a plain empty result, not a value that needs - post-hoc clipping. -- `:fanOutCap` (e.g. 200) bounds how many neighbors a single hub node contributes per hop. This is an - explicit, documented approximation: if a node's true shortest-path edge falls outside its top-200 - neighbors by `person_b` ordering, that path is missed. This is the practical trade-off that makes the - hub-blowup problem tractable in plain SQL; it is a config knob (`six-degrees.fan-out-cap`), not a hidden - magic number, so it can be tuned or disabled (`LIMIT NULL`-equivalent) if load testing shows it's overly - aggressive. -- A query timeout is set directly on the underlying `JdbcTemplate` inside `JdbcCoStarGraphRepository`'s - constructor (no declarative `spring.jdbc.template.query-timeout` property exists in Boot 4.1 - checked - against the reference docs directly) as a last-resort circuit breaker on top of the two caps above. -- The raw query result (`forward_path`/`backward_path` as parallel int arrays) is mapped to a - package-private `JdbcCoStarGraphRepository.RawMatch` record, then collapsed by the package-private - `PathStitcher.stitch(...)` (same package, same file neighborhood) into the `GraphPath` the interface - actually returns - reversing `backward_path` and concatenating, dropping the duplicated meeting node. - Both types are invisible outside `infrastructure.persistence`. -- `personA == personB` is special-cased in `SixDegreesUseCaseImpl` to return degree `0` without calling - the repository at all. - -### 5.3 Person resolution +thousands of co-stars; talk-show hosts exceed 8,000). Meeting in the middle from both ends roughly +squares down the search space (`b^(d/2)` instead of `b^d`), and combined with the product's own 7-degree +cap, each side only ever needs to expand `⌈7/2⌉ = 4` hops. See PDD §9 for the full comparison against +precomputed BFS, in-memory BFS, and Pruned Landmark Labeling. + +### 5.2 Why this isn't a single recursive CTE anymore + +The first working version *was* a single bidirectional recursive CTE (each side's frontier expansion +and cycle check expressed declaratively, path arrays carried through the recursion). It passed review +and its own unit tests, then failed under real data and load in two distinct ways: + +1. **Correctness**: fan-out was capped with `ORDER BY person_b LIMIT :fanOutCap`, always keeping the + same fixed (lowest-id) subset of a hub's neighbors and silently dropping the rest. If the actual + connecting co-star wasn't in that arbitrary subset, the query reported "no path found" (or a longer + path) even though a real, shorter path existed. This is a wrong-answer bug, not a slow-answer bug. +2. **Performance**: cycle prevention only checked that a single path didn't revisit its own history + (`NOT nbr.person_b = ANY(path)`) - there was no *shared* visited set. The same node gets rediscovered + by many different paths in a small-world co-star graph, and each rediscovery independently + re-expanded from that node again. A real hub-to-hub query (two talk-show hosts, ~8,000 co-stars each) + took 3+ minutes and spilled to disk with `fanOutCap=200`/`sideCap=4` - and no fan-out cap small enough + to avoid that blowup was also large enough to not risk bug 1. + +Both bugs share one root cause: a plain recursive CTE has no way to check a candidate node against +*everything already discovered so far* - only against the single path being extended. Fixing that +requires genuine iterative state (a real visited set per side), which SQL's `WITH RECURSIVE` can't +express on its own. The fix keeps this a pure SQL/PL-pgSQL solution (per-endpoint choice - see PDD §9 +for algorithms that mix in Java or a graph database instead) by moving it into a PL/pgSQL function: +`find_shortest_co_star_path` (`V3__shortest_co_star_path_function.sql`), called from +`infrastructure.persistence.JdbcCoStarGraphRepository` as a single `SELECT * FROM +find_shortest_co_star_path(:personA, :personB, :sideCap, :absoluteMaxDegree)`. The +`domain.repository.CoStarGraphRepository` interface is unchanged - still exactly one method, +`Optional findShortestPath(int personA, int personB)` - so this swap was invisible to +`application` and `presentation`. + +### 5.3 How the function works + +- Two `TEMP TABLE`s (`visited_forward`, `visited_backward`, each `(person, parent)`) hold the real, + de-duplicated visited set and parent pointer per side - created `IF NOT EXISTS` and `TRUNCATE`d at + the start of each call rather than `ON COMMIT DROP`, since a caller that runs the function twice + within one open transaction (e.g. a `@Transactional` test) would otherwise hit "relation already + exists" on the second call. +- Each iteration expands whichever side currently has the smaller frontier (the standard + bidirectional-BFS optimization), inserting every neighbor *not already visited on that side* - no + arbitrary cap, so no real neighbor is ever silently dropped. On a tie, a `v_prefer_forward` flag + alternates which side wins, flipped after every tie-driven choice - without this, a plain "prefer + forward on ties" rule starves the backward side completely on any non-branching chain (frontier size + stays 1 = 1 every iteration), a real bug caught by the `findsTheShortestPathAcrossMultipleHopsOnBoth- + SidesOfTheBidirectionalSearch` integration test before this shipped. +- After each expansion, only the *newly* discovered nodes are checked against the other side's full + visited set - the loop exits the instant they intersect, so most real pairs (small-world graph, most + people connect within 1-2 hops) resolve almost immediately rather than exploring to `sideCap` on both + sides unconditionally. +- Once a meeting node is found, the path is reconstructed by walking the `parent` pointers from the + meeting node back to each root - a plain linear parent-chain walk (not the combinatorial multi-path + search above), so a small recursive CTE is the right, cheap tool for that specific step. +- `:sideCap` = 4 and `:absoluteMaxDegree` = 7 bound the loop exactly as before (§6 for why these are + fixed independent of the caller's requested `maxDegree`); `personA == personB` short-circuits inside + the function (degree 0, no expansion at all), mirroring the special case `SixDegreesUseCaseImpl` + already has above it. +- A query timeout is still set directly on the underlying `JdbcTemplate` inside + `JdbcCoStarGraphRepository`'s constructor (no declarative `spring.jdbc.template.query-timeout` + property exists in Boot 4.1) as a last-resort circuit breaker, though early termination on + intersection means it's rarely exercised in practice now. +- Verified against the exact pathological pair that broke the old query (two ~8,000-co-star hub nodes, + no direct edge): 29-44ms and a correct degree-2 result, versus 3+ minutes and a disk spill before. + +### 5.4 Person resolution `PersonResolutionUseCase` (application layer, an internal collaborator of `SixDegreesUseCaseImpl` - see §2.1) resolves a `name` query against `name_basics` via the trigram index from §3.2, through the @@ -718,20 +705,50 @@ one post-generation addition needed (`spring-boot-starter-jackson`, see below): | Zipkin | No | Redundant trace backend - traces already go via OpenTelemetry/OTLP to Tempo | | otlp-metrics | No | Redundant metrics path - metrics already go via Prometheus pull-scrape | -Remaining work: +Done, verified against a real running stack (not just written and assumed correct): + +- **`Dockerfile`**: multi-stage build (Maven build stage -> JRE runtime stage), confirmed with a real + `docker build` (549MB final image, no errors). +- **Test suite** (§10): all 50 tests (unit, decorator, integration, controller) written and passing. +- **Grafana dashboards** under `observability/grafana/provisioning/dashboards/json/` - four dashboards + (HTTP overview, six-degrees latency breakdown, cache hit ratio, k6 load-test results), confirmed by + actually bringing up Grafana and checking the provisioned dashboards via its API (`/api/search`, + `/api/dashboards/uid/...`) rather than trusting hand-written JSON to be schema-correct. The cache + hit-ratio dashboard's `cache_gets_total`/`cache_puts_total` metric names come from Spring Boot's + documented auto-binding of cache metrics for `RedisCacheManager` - flagged in the dashboard's own + description to double check against a real scrape once the app has served traffic, since this wasn't + directly observed (see the next item for why). +- **k6 scripts and `data/sampled-people.csv`** under `imdb/k6/` - `title-detail.js` and `six-degrees.js` + discover real ids/people from the live API at `setup()` time rather than shipping a + dataset-snapshot-specific list of hardcoded ids (a first attempt at hardcoding a few "well-known" real + IMDb ids for the CSV turned out to be exactly the kind of unverified claim worth avoiding - see + `data/generate-sampled-people.sql` for how to build a proper large sample once real data is loaded). + Syntax and control flow verified with real `k6 run` invocations (the setup functions' own error + messages fired exactly as designed against no server). +- **Two real bugs surfaced by actually running the stack, not by review**: + 1. `abanda/imdb-postgresql` keeps bouncing its own Postgres listener throughout the entire ~20-30 minute + background import (config tuning at startup, and further blips under the heavy `COPY` load) - well + after the container healthcheck has reported healthy once. `depends_on: condition: service_healthy` + only gates the *first* startup attempt, not ongoing availability. Fixed at the right layer - Flyway's + own `connect-retries`/`connect-retries-interval` (§ above, `application.yaml`) so the connection + attempt itself retries for up to 30 minutes, rather than the whole Spring context failing once and + needing an external restart. + 2. `imdb-service` had no restart policy at all in `docker-compose.yaml`; added `restart: on-failure:5` + as a second line of defense on top of the Flyway fix, so a genuinely bad startup still self-heals + instead of sitting crashed until someone notices. + +Still open - these need the real, fully-imported dataset, which takes 20-30 minutes and is a deliberate +choice to run, not something to trigger incidentally: -- Write the multi-stage `Dockerfile` (Maven build stage -> JRE runtime stage) referenced by - `docker-compose.yaml`'s `imdb-service.build`. -- Author the actual Grafana dashboard JSON models under `observability/grafana/provisioning/dashboards/json/`. -- Author the k6 scripts and the sampled-actor CSV under `imdb/k6/`. -- Write the test suite described in §10 - unit tests, decorator tests, integration tests, controller - tests - none of it exists yet. - Pick the concrete `minVotes` default for the weighted-rating formula from the real vote-count distribution once the dataset is loaded (PDD §11). -- Tune `fanOutCap` and `sideCap` in §5.2 against real k6 results; both are exposed as configuration, not - hardcoded, specifically so this tuning doesn't require a code change. +- Tune `sideCap` in §5.3 against real k6 results if it's ever found to be too conservative or too + loose - `fanOutCap` no longer exists (§5.2: the BFS rewrite has a real visited set, so it never needs + to arbitrarily drop neighbors to bound the search). - Decide the `co_star_edges` refresh cadence (PDD §11 open question) if this ever moves beyond a single-import deployment. +- Confirm the `cache_gets_total`/`cache_puts_total` metric names above against a real scrape once the app + has actually served cached traffic. - The onion layering in §2 is enforced today only by convention (import direction) and code review, not by a build-tool boundary. If this project grows past its current size, splitting `domain`/`application`/ `infrastructure`/`presentation` into separate Maven modules would make the dependency rule diff --git a/imdb/k6/data/generate-sampled-people.sql b/imdb/k6/data/generate-sampled-people.sql new file mode 100644 index 0000000..d1419ea --- /dev/null +++ b/imdb/k6/data/generate-sampled-people.sql @@ -0,0 +1,22 @@ +-- Run against the fully-seeded database to produce a realistic load-test sample: a mix of +-- ordinary actors and high-degree "hub" actors (LLD §8 - six-degrees.js needs both to exercise +-- realistic and worst-case fan-out through co_star_edges under load). +-- +-- psql -h localhost -U imdb -d imdb -f generate-sampled-people.sql --csv -o sampled-people.csv + +WITH credit_counts AS ( + SELECT nconst, count(*) AS credits + FROM title_principals + WHERE category IN ('actor', 'actress', 'self') + GROUP BY nconst +), +hub_actors AS ( + SELECT nconst FROM credit_counts WHERE credits > 200 ORDER BY random() LIMIT 100 +), +ordinary_actors AS ( + SELECT nconst FROM credit_counts WHERE credits BETWEEN 2 AND 50 ORDER BY random() LIMIT 400 +) +SELECT 'nm' || lpad(nb.nconst::text, 7, '0') AS id, nb.primary_name AS name +FROM name_basics nb +JOIN (SELECT nconst FROM hub_actors UNION SELECT nconst FROM ordinary_actors) sampled + ON sampled.nconst = nb.nconst; diff --git a/imdb/k6/data/sampled-people.csv b/imdb/k6/data/sampled-people.csv new file mode 100644 index 0000000..8b50a68 --- /dev/null +++ b/imdb/k6/data/sampled-people.csv @@ -0,0 +1,5 @@ +id,name +# Empty by default - six-degrees.js falls back to live discovery via the API's own disambiguation +# responses when this file has no real rows. Populate it from the actual loaded dataset for a +# larger, more realistic sample (a mix of ordinary and high-degree "hub" actors, LLD §8): +# psql -h localhost -U imdb -d imdb -f generate-sampled-people.sql --csv -o sampled-people.csv diff --git a/imdb/k6/search.js b/imdb/k6/search.js new file mode 100644 index 0000000..c0c6b2e --- /dev/null +++ b/imdb/k6/search.js @@ -0,0 +1,33 @@ +import http from 'k6/http'; +import { check, sleep } from 'k6'; + +const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080'; + +// Fuzzy trigram search terms - deliberately generic word fragments likely to partial-match a +// wide spread of real primary/original titles, not exact titles. +const QUERY_TERMS = [ + 'love', 'war', 'man', 'night', 'king', 'world', 'story', 'life', 'day', + 'dark', 'star', 'shadow', 'girl', 'house', 'time', 'city', 'game', 'dream', + 'last', 'new', 'red', 'black', 'blue', 'home', 'land', 'wind', +]; + +export const options = { + stages: [ + { duration: '30s', target: 50 }, + { duration: '1m', target: 100 }, + { duration: '30s', target: 0 }, + ], + thresholds: { + http_req_duration: ['p(95)<300'], + http_req_failed: ['rate<0.01'], + }, +}; + +export default function () { + const term = QUERY_TERMS[Math.floor(Math.random() * QUERY_TERMS.length)]; + const res = http.get(`${BASE_URL}/api/v1/titles/search?title=${encodeURIComponent(term)}&size=20`); + check(res, { + 'status is 200': (r) => r.status === 200, + }); + sleep(1); +} diff --git a/imdb/k6/six-degrees.js b/imdb/k6/six-degrees.js new file mode 100644 index 0000000..e1b0c6e --- /dev/null +++ b/imdb/k6/six-degrees.js @@ -0,0 +1,101 @@ +import http from 'k6/http'; +import { check, sleep } from 'k6'; + +const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080'; +const MAX_DEGREE = __ENV.MAX_DEGREE || 7; + +// Common two-word names likely to be shared by more than one real person in a dataset this size - +// used only as a bootstrap when no curated CSV is present (see setup() below). +const SEED_QUERIES = [ + 'John Smith', 'Michael Johnson', 'David Miller', 'Robert Brown', 'James Wilson', + 'Mary Johnson', 'John Williams', 'Michael Smith', 'David Jones', 'Maria Garcia', + 'James Smith', 'John Davis', 'Robert Miller', 'Michael Brown', 'John Miller', +]; + +function loadFromCsv() { + let csv; + try { + csv = open('./data/sampled-people.csv'); + } catch (e) { + return []; + } + return csv + .split('\n') + .slice(1) // header + .map((line) => line.trim()) + .filter((line) => line.length > 0 && !line.startsWith('#')) + .map((line) => { + const [id, name] = line.split(','); + return { id, name }; + }); +} + +// Runs once before the load test. Prefers a curated data/sampled-people.csv - see +// data/generate-sampled-people.sql for how to build a large, realistic one from the real loaded +// dataset, mixing ordinary and high-degree "hub" actors (LLD §8). Falls back to discovering real +// person ids live from the API's own disambiguation responses when no CSV has been populated yet, +// so this script still runs meaningfully against a freshly-seeded database with zero setup. +export function setup() { + const fromCsv = loadFromCsv(); + if (fromCsv.length >= 2) { + return { people: fromCsv }; + } + + const pool = new Map(); + for (const name of SEED_QUERIES) { + const res = http.get( + `${BASE_URL}/api/v1/people/six-degrees?personA=${encodeURIComponent(name)}&personB=${encodeURIComponent(name)}&maxDegree=1` + ); + if (res.status !== 200) continue; + const body = res.json(); + if (body.requiresDisambiguation && Array.isArray(body.candidates)) { + for (const c of body.candidates) pool.set(c.id, c.name); + } else if (body.personA) { + pool.set(body.personA.id, body.personA.name); + } + } + + const people = Array.from(pool, ([id, name]) => ({ id, name })); + if (people.length < 2) { + throw new Error( + 'Could not assemble at least 2 distinct people (empty data/sampled-people.csv and no ' + + 'ambiguous-name discovery hits) - is the database seeded? See data/generate-sampled-people.sql.' + ); + } + return { people }; +} + +export const options = { + stages: [ + { duration: '30s', target: 20 }, + { duration: '1m', target: 50 }, + { duration: '30s', target: 0 }, + ], + thresholds: { + // Deliberately far looser than the other three endpoints (LLD §8): this is the one endpoint + // whose cost depends on graph shape (hub actors), not a bounded index lookup - the gap between + // this threshold and the others' is itself the finding this load test exists to produce. + http_req_duration: ['p(95)<3000'], + http_req_failed: ['rate<0.02'], + }, +}; + +// Picks two distinct people per iteration so the bidirectional CTE - and the six-degrees cache, +// keyed per unordered pair (LLD §6) - is genuinely exercised under load instead of collapsing +// into repeated hits on one warm cache entry. +export default function (data) { + const people = data.people; + const a = people[Math.floor(Math.random() * people.length)]; + let b = people[Math.floor(Math.random() * people.length)]; + while (b.id === a.id && people.length > 1) { + b = people[Math.floor(Math.random() * people.length)]; + } + + const res = http.get( + `${BASE_URL}/api/v1/people/six-degrees?personA=${encodeURIComponent(a.id)}&personB=${encodeURIComponent(b.id)}&maxDegree=${MAX_DEGREE}` + ); + check(res, { + 'status is 200 or 404': (r) => r.status === 200 || r.status === 404, + }); + sleep(1); +} diff --git a/imdb/k6/title-detail.js b/imdb/k6/title-detail.js new file mode 100644 index 0000000..b7de91e --- /dev/null +++ b/imdb/k6/title-detail.js @@ -0,0 +1,48 @@ +import http from 'k6/http'; +import { check, sleep } from 'k6'; + +const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080'; + +const SEED_QUERIES = ['the', 'man', 'love', 'war', 'star', 'night', 'life', 'day', 'girl', 'king']; + +// Runs once before the load test: gathers a pool of real title ids from the running system's own +// search endpoint, rather than shipping a dataset-snapshot-specific list of hardcoded ids that +// would go stale the moment the seeded database is reloaded. +export function setup() { + const ids = new Set(); + for (const term of SEED_QUERIES) { + const res = http.get(`${BASE_URL}/api/v1/titles/search?title=${encodeURIComponent(term)}&size=100`); + if (res.status === 200) { + const body = res.json(); + for (const item of body.content) { + ids.add(item.id); + } + } + } + const pool = Array.from(ids); + if (pool.length === 0) { + throw new Error('setup() found no title ids to sample from /api/v1/titles/search - is the database seeded?'); + } + return { pool }; +} + +export const options = { + stages: [ + { duration: '30s', target: 50 }, + { duration: '1m', target: 100 }, + { duration: '30s', target: 0 }, + ], + thresholds: { + http_req_duration: ['p(95)<300'], + http_req_failed: ['rate<0.01'], + }, +}; + +export default function (data) { + const id = data.pool[Math.floor(Math.random() * data.pool.length)]; + const res = http.get(`${BASE_URL}/api/v1/titles/${id}`); + check(res, { + 'status is 200': (r) => r.status === 200, + }); + sleep(1); +} diff --git a/imdb/k6/top-rated.js b/imdb/k6/top-rated.js new file mode 100644 index 0000000..605013a --- /dev/null +++ b/imdb/k6/top-rated.js @@ -0,0 +1,36 @@ +import http from 'k6/http'; +import { check, sleep } from 'k6'; + +const BASE_URL = __ENV.BASE_URL || 'http://localhost:8080'; + +// The standard 28 IMDb genre values. Verify these match the real seeded GENRE enum exactly +// before a serious run - a mismatched spelling/hyphenation silently returns an empty result +// rather than an error (the query filters `genres::text[] @> ARRAY[:genre]::text[]`, LLD §4.3): +// SELECT unnest(enum_range(NULL::genre)) ORDER BY 1; +const GENRES = [ + 'Action', 'Adult', 'Adventure', 'Animation', 'Biography', 'Comedy', 'Crime', + 'Documentary', 'Drama', 'Family', 'Fantasy', 'Film-Noir', 'Game-Show', + 'History', 'Horror', 'Music', 'Musical', 'Mystery', 'News', 'Reality-TV', + 'Romance', 'Sci-Fi', 'Short', 'Sport', 'Talk-Show', 'Thriller', 'War', 'Western', +]; + +export const options = { + stages: [ + { duration: '30s', target: 50 }, + { duration: '1m', target: 100 }, + { duration: '30s', target: 0 }, + ], + thresholds: { + http_req_duration: ['p(95)<500'], + http_req_failed: ['rate<0.01'], + }, +}; + +export default function () { + const genre = GENRES[Math.floor(Math.random() * GENRES.length)]; + const res = http.get(`${BASE_URL}/api/v1/genres/${encodeURIComponent(genre)}/top-rated?limit=25`); + check(res, { + 'status is 200': (r) => r.status === 200, + }); + sleep(1); +} diff --git a/imdb/observability/alloy/config.alloy b/imdb/observability/alloy/config.alloy index 9dd2086..03df2a6 100644 --- a/imdb/observability/alloy/config.alloy +++ b/imdb/observability/alloy/config.alloy @@ -2,10 +2,26 @@ discovery.docker "containers" { host = "unix:///var/run/docker.sock" } +// Loki 3.x indexes streams by service_name (falling back to "unknown_service" when a stream +// doesn't set one) rather than by arbitrary per-container labels - discovered when every +// container's logs were landing in one undifferentiated unknown_service stream, making them +// unqueryable per service. This extracts the container name (Docker prefixes it with "/") into +// service_name so each container is its own filterable stream in Grafana. +discovery.relabel "containers" { + targets = [] + + rule { + source_labels = ["__meta_docker_container_name"] + regex = "/(.*)" + target_label = "service_name" + } +} + loki.source.docker "default" { - host = "unix:///var/run/docker.sock" - targets = discovery.docker.containers.targets - forward_to = [loki.write.default.receiver] + host = "unix:///var/run/docker.sock" + targets = discovery.docker.containers.targets + relabel_rules = discovery.relabel.containers.rules + forward_to = [loki.write.default.receiver] } loki.write "default" { diff --git a/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json b/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json new file mode 100644 index 0000000..e38a41b --- /dev/null +++ b/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json @@ -0,0 +1,60 @@ +{ + "title": "IMDb - Cache Hit Ratio", + "uid": "imdb-cache-hit-ratio", + "tags": ["imdb"], + "timezone": "browser", + "schemaVersion": 39, + "refresh": "10s", + "time": { "from": "now-15m", "to": "now" }, + "description": "Uses Spring Boot's auto-bound cache.gets/cache.puts metrics for RedisCacheManager (no custom instrumentation - LLD §7). Verify the cache_gets_total{result=...} label values once the app has actually served traffic; this was not confirmed against a live scrape at authoring time.", + "panels": [ + { + "id": 1, + "title": "Hit ratio by cache region", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 0 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (cache) (rate(cache_gets_total{job=\"imdb-service\", result=\"hit\"}[$__rate_interval])) / sum by (cache) (rate(cache_gets_total{job=\"imdb-service\"}[$__rate_interval]))", + "legendFormat": "{{cache}}" + } + ], + "fieldConfig": { "defaults": { "unit": "percentunit", "min": 0, "max": 1 }, "overrides": [] } + }, + { + "id": 2, + "title": "Gets by region and result (hit/miss)", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (cache, result) (rate(cache_gets_total{job=\"imdb-service\"}[$__rate_interval]))", + "legendFormat": "{{cache}} - {{result}}" + } + ], + "fieldConfig": { "defaults": { "unit": "ops" }, "overrides": [] } + }, + { + "id": 3, + "title": "Puts by region", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (cache) (rate(cache_puts_total{job=\"imdb-service\"}[$__rate_interval]))", + "legendFormat": "{{cache}}" + } + ], + "fieldConfig": { "defaults": { "unit": "ops" }, "overrides": [] } + } + ] +} diff --git a/imdb/observability/grafana/provisioning/dashboards/json/http-overview.json b/imdb/observability/grafana/provisioning/dashboards/json/http-overview.json new file mode 100644 index 0000000..ff903c9 --- /dev/null +++ b/imdb/observability/grafana/provisioning/dashboards/json/http-overview.json @@ -0,0 +1,75 @@ +{ + "title": "IMDb - HTTP Overview", + "uid": "imdb-http-overview", + "tags": ["imdb"], + "timezone": "browser", + "schemaVersion": 39, + "refresh": "10s", + "time": { "from": "now-15m", "to": "now" }, + "panels": [ + { + "id": 1, + "title": "Request rate by endpoint", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (uri) (rate(http_server_requests_seconds_count{job=\"imdb-service\"}[$__rate_interval]))", + "legendFormat": "{{uri}}" + } + ], + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] } + }, + { + "id": 2, + "title": "p95 latency by endpoint", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.95, sum by (le, uri) (rate(http_server_requests_seconds_bucket{job=\"imdb-service\"}[$__rate_interval])))", + "legendFormat": "{{uri}}" + } + ], + "fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] } + }, + { + "id": 3, + "title": "5xx error rate by endpoint", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum by (uri) (rate(http_server_requests_seconds_count{job=\"imdb-service\", status=~\"5..\"}[$__rate_interval]))", + "legendFormat": "{{uri}}" + } + ], + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] } + }, + { + "id": 4, + "title": "JVM heap used", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum(jvm_memory_used_bytes{job=\"imdb-service\", area=\"heap\"})", + "legendFormat": "heap used" + } + ], + "fieldConfig": { "defaults": { "unit": "bytes" }, "overrides": [] } + } + ] +} diff --git a/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json b/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json new file mode 100644 index 0000000..8d832b1 --- /dev/null +++ b/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json @@ -0,0 +1,75 @@ +{ + "title": "IMDb - k6 Load Test Results", + "uid": "imdb-k6-load-test", + "tags": ["imdb", "k6"], + "timezone": "browser", + "schemaVersion": 39, + "refresh": "5s", + "time": { "from": "now-15m", "to": "now" }, + "description": "Fed by k6's --out experimental-prometheus-rw output (LLD §8). Run one script at a time (search.js, title-detail.js, top-rated.js, six-degrees.js) so a given time window's results are attributable to a single endpoint - do not read this dashboard while more than one k6 run is active.", + "panels": [ + { + "id": 1, + "title": "Virtual users", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "k6_vus", + "legendFormat": "VUs" + } + ] + }, + { + "id": 2, + "title": "Request rate", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum(rate(k6_http_reqs_total[$__rate_interval]))", + "legendFormat": "req/s" + } + ], + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] } + }, + { + "id": 3, + "title": "p95 request duration", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.95, sum by (le) (rate(k6_http_req_duration_seconds_bucket[$__rate_interval])))", + "legendFormat": "p95" + } + ], + "fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] } + }, + { + "id": 4, + "title": "Failed request rate", + "type": "timeseries", + "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum(rate(k6_http_req_failed_total[$__rate_interval]))", + "legendFormat": "failures/s" + } + ], + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] } + } + ] +} diff --git a/imdb/observability/grafana/provisioning/dashboards/json/six-degrees-latency.json b/imdb/observability/grafana/provisioning/dashboards/json/six-degrees-latency.json new file mode 100644 index 0000000..1836ee8 --- /dev/null +++ b/imdb/observability/grafana/provisioning/dashboards/json/six-degrees-latency.json @@ -0,0 +1,73 @@ +{ + "title": "IMDb - Six Degrees Latency Breakdown", + "uid": "imdb-six-degrees-latency", + "tags": ["imdb"], + "timezone": "browser", + "schemaVersion": 39, + "refresh": "10s", + "time": { "from": "now-15m", "to": "now" }, + "description": "Six-degrees is the one endpoint whose cost depends on graph shape (hub actors), not a bounded index lookup - LLD §5/§8. This dashboard exists to make that gap visible against the other three endpoints, not just eyeball a single number.", + "panels": [ + { + "id": 1, + "title": "p50 / p95 / p99 latency - six-degrees only", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 0 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.50, sum by (le) (rate(http_server_requests_seconds_bucket{job=\"imdb-service\", uri=\"/api/v1/people/six-degrees\"}[$__rate_interval])))", + "legendFormat": "p50" + }, + { + "refId": "B", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.95, sum by (le) (rate(http_server_requests_seconds_bucket{job=\"imdb-service\", uri=\"/api/v1/people/six-degrees\"}[$__rate_interval])))", + "legendFormat": "p95" + }, + { + "refId": "C", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.99, sum by (le) (rate(http_server_requests_seconds_bucket{job=\"imdb-service\", uri=\"/api/v1/people/six-degrees\"}[$__rate_interval])))", + "legendFormat": "p99" + } + ], + "fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] } + }, + { + "id": 2, + "title": "p95 latency: six-degrees vs the other three endpoints", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 8 }, + "description": "The gap between this line and the other three is the finding the k6 load test (LLD §8) exists to produce.", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "histogram_quantile(0.95, sum by (le, uri) (rate(http_server_requests_seconds_bucket{job=\"imdb-service\"}[$__rate_interval])))", + "legendFormat": "{{uri}}" + } + ], + "fieldConfig": { "defaults": { "unit": "s" }, "overrides": [] } + }, + { + "id": 3, + "title": "six-degrees request rate", + "type": "timeseries", + "gridPos": { "h": 8, "w": 24, "x": 0, "y": 16 }, + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "targets": [ + { + "refId": "A", + "datasource": { "type": "prometheus", "uid": "prometheus" }, + "expr": "sum(rate(http_server_requests_seconds_count{job=\"imdb-service\", uri=\"/api/v1/people/six-degrees\"}[$__rate_interval]))", + "legendFormat": "requests/sec" + } + ], + "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] } + } + ] +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java index 630ec65..19653b6 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java @@ -8,6 +8,8 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.GenericJacksonJsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; +import tools.jackson.databind.jsontype.BasicPolymorphicTypeValidator; +import tools.jackson.databind.jsontype.PolymorphicTypeValidator; import java.time.Duration; @@ -24,11 +26,25 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) // by default anymore). enableSpringCacheNullValueSupport() is opt-in here (it was automatic on // the old serializer's default constructor) - needed since caching a "no path found" result as // null is deliberate (LLD §6). + // + // enableDefaultTyping is also opt-in here (automatic on the old serializer) - without it, the + // serializer writes plain JSON with no type metadata at all, so every cache HIT (not miss) + // deserializes to a raw LinkedHashMap instead of the original record and throws + // ClassCastException - only surfaced once a real cache entry was actually read back on a second + // request, since writing a cache entry never exercises the read path. Scoped to our own + // packages (not enableUnsafeDefaultTyping's wide-open Object.class) since Redis is a trust + // boundary in principle even though this deployment doesn't expose it externally. + PolymorphicTypeValidator typeValidator = BasicPolymorphicTypeValidator.builder() + .allowIfSubType("com.ludovictemgoua.imdb.") + .allowIfSubType("java.util.") + .build(); + RedisCacheConfiguration defaults = RedisCacheConfiguration.defaultCacheConfig() .entryTtl(Duration.ofHours(24)) .serializeValuesWith(RedisSerializationContext.SerializationPair .fromSerializer(GenericJacksonJsonRedisSerializer.builder() .enableSpringCacheNullValueSupport() + .enableDefaultTyping(typeValidator) .build())); return RedisCacheManager.builder(connectionFactory) diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java index 5c8cf87..69040f2 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java @@ -8,6 +8,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; +import javax.sql.DataSource; import java.sql.Array; import java.sql.ResultSet; import java.sql.SQLException; @@ -20,88 +21,49 @@ public class JdbcCoStarGraphRepository implements CoStarGraphRepository { private final NamedParameterJdbcTemplate jdbc; private final int sideCap; - private final int fanOutCap; private final int absoluteMaxDegree; public JdbcCoStarGraphRepository( - NamedParameterJdbcTemplate jdbc, + DataSource dataSource, @Value("${six-degrees.side-cap}") int sideCap, - @Value("${six-degrees.fan-out-cap}") int fanOutCap, @Value("${six-degrees.absolute-max-degree}") int absoluteMaxDegree, @Value("${six-degrees.query-timeout-seconds}") int queryTimeoutSeconds) { - this.jdbc = jdbc; + // A dedicated JdbcTemplate over the same DataSource/connection pool, not the app's shared + // auto-configured NamedParameterJdbcTemplate bean - setQueryTimeout mutates the JdbcTemplate + // instance itself, and Spring only creates one shared instance of that bean by default, so + // setting the timeout there was leaking this query's tight timeout onto every other + // repository's queries (discovered when a plain title search got cancelled by this six-degrees- + // specific timeout). Only this query gets a tight timeout - it's the one query in the whole app + // whose cost depends on graph shape (hub actors) rather than a bounded index lookup. There's no + // `spring.jdbc.template.query-timeout` property to set this declaratively (Boot 4.1 doesn't have + // one), so it's set directly on this repository's own JdbcTemplate instead. + JdbcTemplate template = new JdbcTemplate(dataSource); + template.setQueryTimeout(queryTimeoutSeconds); + this.jdbc = new NamedParameterJdbcTemplate(template); this.sideCap = sideCap; - this.fanOutCap = fanOutCap; this.absoluteMaxDegree = absoluteMaxDegree; - // Only this query gets a tight timeout - it's the one query in the whole app whose cost - // depends on graph shape (hub actors) rather than a bounded index lookup. There's no - // `spring.jdbc.template.query-timeout` property to set this declaratively (Boot 4.1 doesn't - // have one), so it's set directly on the underlying JdbcTemplate instead. - ((JdbcTemplate) jdbc.getJdbcOperations()).setQueryTimeout(queryTimeoutSeconds); } @Override public Optional findShortestPath(int personA, int personB) { - String sql = """ - WITH RECURSIVE forward(person, depth, path) AS ( - SELECT :personA, 0, ARRAY[:personA] - UNION ALL - SELECT nbr.person_b, f.depth + 1, f.path || nbr.person_b - FROM forward f - CROSS JOIN LATERAL ( - SELECT e.person_b - FROM co_star_edges e - WHERE e.person_a = f.person - ORDER BY e.person_b - LIMIT :fanOutCap - ) nbr - WHERE f.depth < :sideCap - AND NOT nbr.person_b = ANY(f.path) - ), - backward(person, depth, path) AS ( - SELECT :personB, 0, ARRAY[:personB] - UNION ALL - SELECT nbr.person_b, b.depth + 1, b.path || nbr.person_b - FROM backward b - CROSS JOIN LATERAL ( - SELECT e.person_b - FROM co_star_edges e - WHERE e.person_a = b.person - ORDER BY e.person_b - LIMIT :fanOutCap - ) nbr - WHERE b.depth < :sideCap - AND NOT nbr.person_b = ANY(b.path) - ) - SELECT f.depth + b.depth AS degree, f.path AS forward_path, b.path AS backward_path - FROM forward f - JOIN backward b ON b.person = f.person - WHERE f.depth + b.depth <= :absoluteMaxDegree - ORDER BY degree ASC - LIMIT 1 - """; + // The actual bidirectional-BFS logic lives entirely in the find_shortest_co_star_path SQL + // function (V3 migration) - a real level-synchronized BFS with a genuine per-side visited + // set, replacing an earlier single-statement recursive CTE that had no visited set (only + // per-path cycle checks) and capped fan-out with an arbitrary ORDER BY that could silently + // drop the true shortest path. See the V3 migration for the full rationale. + String sql = "SELECT * FROM find_shortest_co_star_path(:personA, :personB, :sideCap, :absoluteMaxDegree)"; var params = new MapSqlParameterSource() .addValue("personA", personA).addValue("personB", personB) - .addValue("sideCap", sideCap).addValue("fanOutCap", fanOutCap) - .addValue("absoluteMaxDegree", absoluteMaxDegree); + .addValue("sideCap", sideCap).addValue("absoluteMaxDegree", absoluteMaxDegree); - return jdbc.query(sql, params, JdbcCoStarGraphRepository::mapRawMatch).stream() - .findFirst() - .map(PathStitcher::stitch); + return jdbc.query(sql, params, JdbcCoStarGraphRepository::mapGraphPath).stream().findFirst(); } - private static RawMatch mapRawMatch(ResultSet rs, int rowNum) throws SQLException { - return new RawMatch(rs.getInt("degree"), - toIntList(rs.getArray("forward_path")), toIntList(rs.getArray("backward_path"))); + private static GraphPath mapGraphPath(ResultSet rs, int rowNum) throws SQLException { + return new GraphPath(rs.getInt("result_degree"), toIntList(rs.getArray("result_path"))); } private static List toIntList(Array sqlArray) throws SQLException { return Arrays.asList((Integer[]) sqlArray.getArray()); } - - // Package-private: the forward/backward split is an artifact of this one bidirectional-CTE - // implementation, not a domain concept. PathStitcher (same package) collapses it into the clean - // GraphPath the CoStarGraphRepository interface actually promises. - record RawMatch(int degree, List forwardPath, List backwardPath) { - } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java index b1b0d8f..f7be74d 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java @@ -105,7 +105,7 @@ WITH pool AS ( FROM title_basics tb JOIN title_ratings tr ON tr.tconst = tb.tconst WHERE tb.title_type = 'movie' - AND tb.genres::text[] @> ARRAY[:genre]::text[] + AND genres_as_text(tb.genres) @> ARRAY[:genre]::text[] AND tr.num_votes >= :minVotes ), stats AS (SELECT AVG(average_rating) AS mean_rating FROM pool) diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java deleted file mode 100644 index f29f202..0000000 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/PathStitcher.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ludovictemgoua.imdb.infrastructure.persistence; - -import com.ludovictemgoua.imdb.domain.model.GraphPath; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -final class PathStitcher { - - private PathStitcher() { - } - - static GraphPath stitch(JdbcCoStarGraphRepository.RawMatch match) { - List backward = new ArrayList<>(match.backwardPath()); - Collections.reverse(backward); - // forward's last element and reversed-backward's first element are the same node (where the - // two searches met) - drop the duplicate before concatenating. - List stitched = new ArrayList<>(match.forwardPath()); - stitched.addAll(backward.subList(1, backward.size())); - return new GraphPath(match.degree(), stitched); - } -} diff --git a/imdb/src/main/resources/application.yaml b/imdb/src/main/resources/application.yaml index aec6d24..8d5470e 100644 --- a/imdb/src/main/resources/application.yaml +++ b/imdb/src/main/resources/application.yaml @@ -5,12 +5,32 @@ spring: url: jdbc:postgresql://localhost:5432/imdb username: imdb password: password + hikari: + # Default (10) was completely swamped by k6's 100-VU search load test - HikariPool logs showed + # total=10, active=10, idle=0, waiting=46, cascading into 30s connection-acquisition timeouts. + # 30 gives real headroom under concurrent load while staying well under Postgres's + # max_connections=100 (leaves room for postgres-exporter and manual/admin connections). + maximum-pool-size: 30 data: redis: host: localhost port: 6379 flyway: enabled: true + # abanda/imdb-postgresql keeps bouncing its own listener throughout the (up to 30 minute) + # background data import, well after the container's healthcheck first reports healthy - + # discovered empirically while bringing this stack up. Flyway's own retry loop rides out those + # gaps directly instead of the whole application failing to start on an unlucky first attempt. + connect-retries: 180 + connect-retries-interval: 10s + # abanda/imdb-postgresql's own init.sh populates the `public` schema (name_basics, title_basics, + # etc.) via raw psql/imdblib, entirely outside Flyway - so on a freshly imported database Flyway + # sees a non-empty schema with no history table and refuses to proceed. baseline-version: 0 tells + # it to treat V0 (the CREATE TABLE IF NOT EXISTS base schema, already satisfied by imdblib's + # tables) as the starting point, and only apply V1/V2 on top. Has no effect on the empty schema + # Testcontainers spins up for integration tests - Flyway just runs V0-V2 there as normal. + baseline-on-migrate: true + baseline-version: 0 management: endpoints: @@ -25,11 +45,26 @@ management: export: otlp: endpoint: http://localhost:4318/v1/traces + # Adding the "OpenTelemetry" Initializr module also auto-configures a push-based OTLP metrics + # exporter (defaulting to localhost:4318/v1/metrics, which inside a container doesn't resolve to + # anything useful) - discovered from a live ConnectException in the logs. Metrics were always meant + # to go via Prometheus pull-scrape only (LLD dependency table, `/actuator/prometheus`), not push, so + # this second unwanted exporter is disabled outright rather than pointed anywhere. Note the + # inconsistent Boot 4.1 property namespace: metrics kept "management.otlp.*" while tracing moved to + # "management.opentelemetry.tracing.*" above - confirmed against OtlpMetricsProperties directly, not + # guessed, since the two don't mirror each other. + otlp: + metrics: + export: + enabled: false six-degrees: side-cap: 4 absolute-max-degree: 7 - fan-out-cap: 200 + # fan-out-cap removed: the V3 find_shortest_co_star_path function does a real BFS with a genuine + # visited set, so it never needs to arbitrarily drop neighbors to bound the search - it expands + # every unvisited neighbor of the current frontier, which is what fixed a real bug (the old + # capped-and-ordered fan-out could silently miss the true shortest path). query-timeout-seconds: 2 top-rated: diff --git a/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql b/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql index f274bf8..a41adfb 100644 --- a/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql +++ b/imdb/src/main/resources/db/migration/V1__extensions_and_search_indexes.sql @@ -6,8 +6,20 @@ CREATE INDEX idx_title_basics_primary_title_trgm CREATE INDEX idx_title_basics_original_title_trgm ON title_basics USING gin (original_title gin_trgm_ops); +-- title_basics.genres is TEXT[] in our own V0 fallback schema (Testcontainers) but GENRE[] (a +-- custom enum array) on the real abanda/imdb-postgresql-seeded database - genres::text[] works as a +-- query-time cast against either, but Postgres won't accept a bare cast in an index expression since +-- it can't prove the underlying enum-array-to-text-array cast function is IMMUTABLE. Wrapping it in +-- our own SQL function marked IMMUTABLE (accepting anyarray, so it still works against either +-- schema) sidesteps that - discovered when the plain ::text[] version failed at migration time +-- against the real, freshly-imported dataset with "functions in index expression must be marked +-- IMMUTABLE". JdbcTitleRepository's genre filter query must use this same function, not a raw cast, +-- so the planner recognizes the expression as matching the index. +CREATE OR REPLACE FUNCTION genres_as_text(anyarray) RETURNS text[] + LANGUAGE sql IMMUTABLE PARALLEL SAFE AS $$ SELECT $1::text[] $$; + CREATE INDEX idx_title_basics_genres - ON title_basics USING gin ((genres::text[])); + ON title_basics USING gin (genres_as_text(genres)); CREATE INDEX idx_title_ratings_rank ON title_ratings (average_rating DESC, num_votes DESC); @@ -18,3 +30,25 @@ CREATE INDEX idx_title_principals_nconst_acting CREATE INDEX idx_name_basics_primary_name_trgm ON name_basics USING gin (primary_name gin_trgm_ops); + +-- Discovered under k6 load testing: short/common search terms (e.g. "man", "war", "day" - the bulk +-- of realistic single-word title searches) make pg_trgm's `%` operator match an enormous fraction of +-- the table, since a 3-4 letter string has very few distinct trigrams. Raising +-- pg_trgm.similarity_threshold does NOT help - EXPLAIN ANALYZE showed the GIN bitmap index scan +-- returns the exact same huge candidate set (832K+ rows for "man") regardless of threshold, because +-- the threshold is only applied as a post-fetch recheck, not at the index scan itself. The actual +-- fix is gin_fuzzy_search_limit, which caps how many rows a GIN index scan will return for a +-- low-selectivity query term: took the "man" query from 39.6s / 176,300 buffer reads down to ~120ms +-- / ~3,000 buffer reads, and turned a 100%-failure k6 run into a 100%-pass, p95=4.45ms run. +-- Trade-off (accepted deliberately): `totalElements` in the search response becomes an +-- under-count for very common terms, since it's counting a sampled candidate set rather than the +-- true total (Postgres's own docs describe gin_fuzzy_search_limit results as "likely to be +-- incomplete" - expected and fine for a fuzzy-search results page, not fine for anything relying on +-- an exact count). Set at the database level so every pooled HikariCP connection picks it up +-- automatically, without a per-query SET statement or Java code change. Uses current_database() +-- rather than hardcoding "imdb" - Testcontainers' PostgreSQLContainer defaults to a database named +-- "test", and this migration runs there too. +DO $$ +BEGIN + EXECUTE format('ALTER DATABASE %I SET gin_fuzzy_search_limit = 5000', current_database()); +END $$; diff --git a/imdb/src/main/resources/db/migration/V3__shortest_co_star_path_function.sql b/imdb/src/main/resources/db/migration/V3__shortest_co_star_path_function.sql new file mode 100644 index 0000000..b406e70 --- /dev/null +++ b/imdb/src/main/resources/db/migration/V3__shortest_co_star_path_function.sql @@ -0,0 +1,149 @@ +-- Replaces an earlier single-statement bidirectional recursive CTE that had two real bugs, both +-- found under real load/data (not review): +-- +-- 1. Correctness: the old query capped each node's fan-out with `ORDER BY person_b LIMIT +-- :fanOutCap`, always keeping the same fixed (lowest-id) subset of a hub's neighbors and +-- silently dropping the rest. If the actual connecting co-star wasn't in that arbitrary +-- subset, the query would report "no path found" (or a longer path) even though a real, +-- shorter path existed. +-- 2. Performance: cycle prevention only checked that a single path didn't revisit its own +-- history (`NOT nbr.person_b = ANY(path)`) - it had no shared visited set. The same node gets +-- rediscovered by many different paths in a small-world co-star graph, and each rediscovery +-- independently re-expanded from that node again, causing genuine combinatorial blowup. A +-- real hub-to-hub query (two talk-show hosts, ~8,000 co-stars each) took 3+ minutes and spilled +-- to disk with fanOutCap=200/sideCap=4. +-- +-- This function is a proper level-synchronized bidirectional BFS: real visited-set temp tables +-- per side (so every node is expanded at most once, ever - no redundant re-expansion, no +-- arbitrary cap needed to drop real neighbors), expanding whichever side currently has the +-- smaller frontier (the standard bidirectional-BFS optimization - keeps total work minimal), and +-- stopping the instant the two frontiers intersect (true shortest path, found as early as +-- possible - most real pairs resolve within 1-2 hops). Verified against the exact pathological +-- pair that broke the old query (two ~8,000-co-star hub nodes, no direct edge): 44ms, correct +-- degree-2 result, versus 3+ minutes before. +CREATE OR REPLACE FUNCTION find_shortest_co_star_path( + p_person_a INTEGER, + p_person_b INTEGER, + p_side_cap INTEGER, + p_absolute_max_degree INTEGER +) RETURNS TABLE(result_degree INTEGER, result_path INTEGER[]) AS $$ +DECLARE + v_new_forward INTEGER[]; + v_new_backward INTEGER[]; + v_meeting INTEGER; + v_fwd_depth INTEGER := 0; + v_bwd_depth INTEGER := 0; + v_frontier_forward INTEGER[] := ARRAY[p_person_a]; + v_frontier_backward INTEGER[] := ARRAY[p_person_b]; + -- Tie-break flag for when both frontiers are the same size (see WHILE loop below) - without + -- this, a plain "<=" comparison always favors forward on ties, which completely starves the + -- backward side for any non-branching chain (frontier size stays 1 = 1 forever), since forward + -- would keep winning every tie until it alone hits side_cap. Flipped after every tie-driven + -- choice so both sides make progress. Found by a failing integration test on a 5-edge linear + -- chain (1-2-3-4-5-6), not by review. + v_prefer_forward BOOLEAN := true; +BEGIN + IF p_person_a = p_person_b THEN + RETURN QUERY SELECT 0, ARRAY[p_person_a]; + RETURN; + END IF; + + -- Session-scoped temp tables, reused across calls on the same pooled connection rather than + -- ON COMMIT DROP - a call wrapped in a caller-managed transaction that runs this function more + -- than once before committing (e.g. a @Transactional test calling findShortestPath twice) would + -- hit "relation already exists" on the second call, since ON COMMIT DROP only cleans up at + -- actual commit, not between statements in an open transaction. TRUNCATE instead, which is + -- correct regardless of transaction/session boundaries. + CREATE TEMP TABLE IF NOT EXISTS visited_forward (person INTEGER PRIMARY KEY, parent INTEGER); + CREATE TEMP TABLE IF NOT EXISTS visited_backward (person INTEGER PRIMARY KEY, parent INTEGER); + TRUNCATE visited_forward, visited_backward; + INSERT INTO visited_forward VALUES (p_person_a, NULL); + INSERT INTO visited_backward VALUES (p_person_b, NULL); + + WHILE v_fwd_depth + v_bwd_depth < p_absolute_max_degree + AND v_fwd_depth < p_side_cap AND v_bwd_depth < p_side_cap + AND (array_length(v_frontier_forward, 1) IS NOT NULL OR array_length(v_frontier_backward, 1) IS NOT NULL) + LOOP + IF array_length(v_frontier_forward, 1) IS NOT NULL + AND (array_length(v_frontier_backward, 1) IS NULL + OR array_length(v_frontier_forward, 1) < array_length(v_frontier_backward, 1) + OR (array_length(v_frontier_forward, 1) = array_length(v_frontier_backward, 1) AND v_prefer_forward)) THEN + + WITH new_nodes AS ( + INSERT INTO visited_forward (person, parent) + SELECT x.person_b, x.parent FROM ( + SELECT DISTINCT ON (e.person_b) e.person_b, e.person_a AS parent + FROM co_star_edges e + WHERE e.person_a = ANY(v_frontier_forward) + AND NOT EXISTS (SELECT 1 FROM visited_forward vf WHERE vf.person = e.person_b) + ORDER BY e.person_b + ) x + RETURNING person + ) + SELECT array_agg(person) INTO v_new_forward FROM new_nodes; + + v_frontier_forward := v_new_forward; + v_fwd_depth := v_fwd_depth + 1; + v_prefer_forward := false; + + IF v_new_forward IS NOT NULL THEN + SELECT vb.person INTO v_meeting + FROM visited_backward vb + WHERE vb.person = ANY(v_new_forward) + LIMIT 1; + EXIT WHEN v_meeting IS NOT NULL; + END IF; + ELSE + WITH new_nodes AS ( + INSERT INTO visited_backward (person, parent) + SELECT x.person_b, x.parent FROM ( + SELECT DISTINCT ON (e.person_b) e.person_b, e.person_a AS parent + FROM co_star_edges e + WHERE e.person_a = ANY(v_frontier_backward) + AND NOT EXISTS (SELECT 1 FROM visited_backward vb WHERE vb.person = e.person_b) + ORDER BY e.person_b + ) x + RETURNING person + ) + SELECT array_agg(person) INTO v_new_backward FROM new_nodes; + + v_frontier_backward := v_new_backward; + v_bwd_depth := v_bwd_depth + 1; + v_prefer_forward := true; + + IF v_new_backward IS NOT NULL THEN + SELECT vf.person INTO v_meeting + FROM visited_forward vf + WHERE vf.person = ANY(v_new_backward) + LIMIT 1; + EXIT WHEN v_meeting IS NOT NULL; + END IF; + END IF; + END LOOP; + + IF v_meeting IS NULL THEN + RETURN; + END IF; + + -- Reconstruct the path by walking parent pointers from the meeting node back to each root - + -- a plain linear parent-chain walk, not the combinatorial multi-path search above, so a + -- recursive CTE is the right (and cheap) tool here. + RETURN QUERY + WITH RECURSIVE forward_chain AS ( + SELECT person, parent, 1 AS ord FROM visited_forward WHERE person = v_meeting + UNION ALL + SELECT vf.person, vf.parent, fc.ord + 1 + FROM visited_forward vf JOIN forward_chain fc ON vf.person = fc.parent + ), + backward_chain AS ( + SELECT person, parent, 1 AS ord FROM visited_backward WHERE person = v_meeting + UNION ALL + SELECT vb.person, vb.parent, bc.ord + 1 + FROM visited_backward vb JOIN backward_chain bc ON vb.person = bc.parent + ) + SELECT + (SELECT max(ord) FROM forward_chain) - 1 + (SELECT max(ord) FROM backward_chain) - 1, + (SELECT array_agg(person ORDER BY ord DESC) FROM forward_chain) + || (SELECT array_agg(person ORDER BY ord ASC) FROM backward_chain WHERE ord > 1); +END; +$$ LANGUAGE plpgsql; From 9c94a011b66063c1353b6ecf8e6e6cdad4ed8911 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Fri, 10 Jul 2026 01:11:50 +0200 Subject: [PATCH 13/42] Fix 6-degree sql implementation --- imdb/k6/data/sampled-people.csv | 504 +++++++++++++++++- imdb/k6/six-degrees.js | 23 +- imdb/src/main/resources/application.yaml | 8 + .../V4__title_principals_nconst_index.sql | 11 + 4 files changed, 534 insertions(+), 12 deletions(-) create mode 100644 imdb/src/main/resources/db/migration/V4__title_principals_nconst_index.sql diff --git a/imdb/k6/data/sampled-people.csv b/imdb/k6/data/sampled-people.csv index 8b50a68..113c118 100644 --- a/imdb/k6/data/sampled-people.csv +++ b/imdb/k6/data/sampled-people.csv @@ -1,5 +1,501 @@ id,name -# Empty by default - six-degrees.js falls back to live discovery via the API's own disambiguation -# responses when this file has no real rows. Populate it from the actual loaded dataset for a -# larger, more realistic sample (a mix of ordinary and high-degree "hub" actors, LLD §8): -# psql -h localhost -U imdb -d imdb -f generate-sampled-people.sql --csv -o sampled-people.csv +nm9330281,Lotte Grondahl +nm1577641,Hannes Gieseler +nm0668359,Joel Christopher Payne +nm2102963,Josef Mattes +nm0300041,Gerhard Garbers +nm3991520,Tristen Yap +nm3644680,Des Brittain +nm9452648,Abdullatif Alsheti +nm0928390,Colette Wilda +nm3228990,Aleksander Mazur +nm3180848,Kate Sanford +nm5200264,Julia Christina Ray +nm1443437,Eric Lamp +nm0379382,Patricia Hermenier +nm0298310,Mike Fuller +nm1038305,Sami Huttunen +nm0497853,Mason Lee +nm1105859,Daniela Rathana +nm0408017,Grant Imahara +nm1524400,Travis Stockman +nm1547163,Brennan Weir +nm5441406,Alex Brooker +nm2083199,Gary Pease +nm1161316,Cris King +nm4358982,Jamie Jurju +nm5735979,Nathanial Jacobs +nm1471923,Fikrat Salem +nm1677486,Robert Markle +nm0341659,Derek Griffiths +nm5550107,Chresten +nm3120419,Richard Condo +nm8586788,Jeet Raidutt +nm1301323,Valery Carranza +nm7330294,Kenta Kojiri +nm1447033,Giselle Samson +nm1048030,Trem da Alegria +nm9199784,McKenna Allen +nm5211665,Jimena Torres Cautivo +nm1234143,Anurag Thakur +nm2832137,Xander Denke +nm2499292,North E. West +nm1230316,Marc Babin +nm0735884,Iván Rodríguez +nm1714424,Red Panda +nm1646605,Anthony J Cruz +nm1773391,Vedana Kinchevska +nm7555178,Before Dark +nm1983394,Christy Little +nm1700610,Marco Alcaraz +nm4868822,Paul Greenberg +nm8627787,Anthony Selemidis +nm7855993,Keyvan +nm1184236,Andrea Gomez +nm7586587,Alana LeBlanc Barnett +nm1082770,Beau Danner +nm8939814,Wesley Weigel +nm0733289,María Luisa Robledo +nm1699430,Adelowo A. Richard +nm1635373,Piotr Muszynski +nm5833432,Tetsuhito Aoki +nm0640573,Peter O'Crotty +nm1068023,Harald Jähner +nm9637898,Rob Ebner +nm4904649,Arturo Versaci +nm1738504,Deepti Gujral +nm7759926,Elijah Lucian +nm2981567,Patrik Plesinger +nm1274011,Berrie +nm9937505,Brooke Sheppard +nm0452834,Akiko Kikuchi +nm2574512,Hristos Fragos +nm1375949,Allyssa Anderson +nm9174470,Harro Siegel +nm1539988,Jake Lawrence Coronado +nm3381431,Sammy Spear and His Orchestra +nm3056623,NeNe Leakes +nm5470854,Keya Hamilton +nm1080163,PriyomNaziba Bashar +nm1690743,April Yvette Thompson +nm1546492,Werner Kramer +nm1616345,Cher Lourens +nm2209279,Mikkel Kryger Rasmussen +nm0766733,Anne Saunders +nm1254239,Yuri Dimitrov +nm8084664,Ömer Acar +nm2865320,Gerald Vincent +nm1709523,Kirsty Wirth +nm0151321,Ben Morris +nm4464857,Elizabeth Henstridge +nm1836488,Alex Ganster +nm2763822,Shaghayegh Mohammadali +nm0885779,Catherine Van Bree +nm1354673,Kale Cox +nm4898556,Todd Aiken +nm5255619,Robert Vogel +nm8625013,Jim Ritter +nm1634105,Mel Alcalde +nm0631462,Joe Nightingale +nm6453159,Alyssa Chase +nm1053428,Nàcara Huélamo +nm3311160,Yûsuke Kobayashi +nm1810883,K. Alexander Michael +nm3576847,Tom Brogan +nm1115651,Yura Yelin +nm1372956,Jon Santos +nm1690282,Janine Miramas +nm0660400,Lars Pape +nm1120193,Adam Boor +nm1364226,Dora Malo +nm0096234,Edwin Bordo +nm0798041,Sergei Silkin +nm3796733,Ellie Frankel Sextet +nm0239894,Graham Duckett +nm1111672,Havana Chapman-Edwards +nm4859632,Steph McGovern +nm0607847,Beryl Mortimer +nm0141140,Isabelle Carré +nm5829250,Timothy Paul McCray +nm9539908,Gianfranco Miconi +nm1265876,Jon Courtney +nm7209979,Desmar Guevara +nm0126594,István Bársony +nm0426980,Dorrie Joiner +nm2713185,Manu Onraita +nm2951900,Peter Flihan +nm1082287,Shaquille Mathurin +nm4790855,Bengey Asse +nm7160617,Caelan Benn +nm3736634,Ana Shaw +nm1124364,Bay Eaton +nm3030804,Manel Esteller +nm1893726,Malka Braun +nm4448700,Peter Mueller +nm0293299,Ben Freeman +nm3716645,Matt Cobb +nm2177405,Clara Ponsot +nm8294938,Rami Boraie +nm2717025,Gabriel Winter +nm1247177,Benjamin Alford Jr. +nm2686199,Dennis Kilcoyne +nm9046337,Alessio Di Domenicantonio +nm7437055,Ibragimov Ali +nm1033082,Andreas Mundt +nm0717086,Poul Reichhardt +nm7426879,Sebastiano Pestoni +nm1352786,Samira Halal +nm8036630,Chris Chandler +nm1151731,Bianca Medeiros Krainson +nm1425326,Gerardo Larrosa +nm1493168,Kristin Kaspersen +nm5278103,Willie Soon +nm8515276,Camila Maia +nm1383162,Isaac Stanley-Becker +nm0938772,Maximilian Wolters +nm2121770,Douglas Nabors +nm0406904,Barry Baz Idoine +nm4144181,Darren Fleming +nm5535554,Ken'ichi Tsukada +nm2971900,Wei-Wei Chang +nm7497701,Lore Lons +nm0882939,Nicolas Vachon +nm3618107,Mosharraf Karim +nm7600010,Sethu Lakshmi +nm9915967,Omid Ebrahimi +nm0179179,Marjorie Corbett +nm0059176,Joe B. Barton +nm1064745,Jacques Servolin +nm7080282,Tara Morgan +nm2141966,Marc Basany +nm0174760,Brian Conley +nm8483590,Alicja Gescinska +nm0509470,Gundula Liebisch +nm1074912,Will Clempner +nm0062709,Clive Baxter +nm0370243,Trish Hawkins +nm4803690,Avril Lennox +nm2164919,Debra Burlingame +nm3907852,Emma Rogers +nm1100751,Mang Udel +nm3446681,Charles Coburn +nm9822268,Deepak Joshi +nm1657108,Aika Kumawat +nm4864942,Elizabeth The Koala +nm3198091,Ben Matheny +nm1363379,Blanca Martínez +nm2176630,Catherine Waller +nm3277955,Kalup Linzy +nm2929559,Ted Stokes +nm2296989,Osiris Larkin +nm0610468,Bill Moyers +nm2237399,Danica Dias +nm6148301,Cari Spinnler +nm7654212,Lucas Lefevre +nm0017644,Sophie Aldred +nm6493917,Rachel Kushner +nm1035020,Toni Albà +nm1053032,Evi Hoste +nm1143976,Cindrella D. Cruz +nm4462778,Eny Autran +nm3403880,Roozbeh Behtaji +nm1371588,Hazuki Nishikawa +nm1229640,Hoon Lee +nm0005286,Haley Joel Osment +nm9483662,António Alvarinho +nm6495624,Kevin Gonzalez +nm1533853,Louai El Amrousy +nm5153052,Magen Hudak +nm5122304,Johannes Vetter +nm3702655,Cyntia Botello +nm4484082,Emanuele Dainotti +nm0065721,Stephen Beckett +nm4065451,Shaneequa Thelissen +nm1368505,Keith Flint +nm1994167,Jordan Carlos +nm9422149,Kevin Ashford +nm7022882,Stewart Bloomfield +nm5948509,Jason Sackel +nm9254291,Kessir Riliniki +nm4372868,Tom Berdine +nm8455937,Adrián Baena +nm2304840,Dominic L. Santana +nm8545863,Tariq Hanna +nm8414597,Grace Tormis +nm4863181,Roberto Velasco +nm5625020,Natasha Rothwell +nm3592766,Anjali +nm4055042,Bohdan Pomahac +nm1222809,Lucy Ricketts +nm1059529,Domingos Coimbra +nm0858828,Frank M. Thomas +nm1815894,Jace Hinson +nm3821762,Marc Murphy +nm1299775,Bente Hansen +nm1082117,Mad Clip +nm1111839,Ian Shen +nm5849849,Heather Seaman +nm7409442,Riley Chandler +nm5056980,Dakota Buchanan +nm1190669,Cicily Stone +nm9948834,Tinoco Alves +nm1764201,Carole Malone +nm1151013,Robert Blake Bryant +nm1186315,Victor Taïeb +nm1176043,Uriya Elkayam +nm1462684,Mary T Lynch +nm3109659,Nancy Cordes +nm0241009,Yvette Duguay +nm1121644,Michael Bedard +nm1092036,Daniela Hubloher +nm0921835,Adolf Wessely +nm0122036,Dennis Burkley +nm4163847,Sibel Meriç +nm1242653,Tzion Azoulay +nm1103255,Walter Günther +nm8718067,Tais Gadea Lara +nm2197299,Seneca Ramirez +nm4151111,Whitney Lavaux +nm0279605,Jules Fisher +nm1843265,Ako Mitchell +nm0591123,Cristiano Minellono +nm1708220,Baron Angeles +nm4684947,Liandra Sadzo +nm3005882,Mel Counts +nm4678159,Greg Giuliano +nm5472911,Mike Rhodes +nm1029059,David Argoeti +nm0556036,Masahiro Matsuoka +nm2971684,David Zory +nm6576659,Nilze Carvalho +nm0203922,Rebekah Davies +nm1466378,Qwerty121 +nm5564707,Lizzie Leeds +nm1243644,Oveq +nm2450891,Miho Tsuji +nm6762114,Stine Omar +nm0501461,Filo Lemoine +nm1360696,Matthew Andrew Gonzalez +nm1300508,Sarah von Racknitz +nm4050779,Dominik Reynolds +nm0902702,Hubert von Meyerinck +nm0429274,Star Jones +nm0733577,Víctor Roca +nm0812405,Nodar Sokhadze +nm1492158,Doug Biro +nm5503695,Oldrich Kulhánek +nm0031779,Miguel Anzures +nm1766984,Adi Dassler +nm9543598,Yuexi Wang +nm1376857,Amin Yoma +nm9467028,Francisco Pascual +nm8293499,Victor Pourcel +nm1016348,The Candy Dates +nm4233401,Mary Rose Bonello +nm1473097,Hugo Almeida +nm2424236,Yasuyuki Maekawa +nm1008957,Silver van Sprundel +nm0262763,Fred Evans +nm3144553,Nicolas Grard +nm2572540,Michael Nalder +nm0870780,Christian Tramitz +nm8097288,Gianni Spezzano +nm9142049,Reina Lee +nm4740113,Saara Chaudry +nm1195110,Evelyn Hines +nm1552301,Milan Tocinovski +nm1612417,Geraldine Aherne +nm2639074,Gökçe Gürsoy +nm1262300,Kerstin Schweiger +nm4949546,Todd Bobenrieth +nm1667469,Kylie Morgan +nm0341400,William Griffin +nm1784952,Nicola Vidotto +nm0676940,Robert Petersen +nm2100311,Aymeline Valade +nm1680852,Hugues Saint Louis +nm0001557,Viggo Mortensen +nm6432430,Michael Alvarado +nm6554537,Puneet +nm0294689,Patxi Freytez +nm6622872,Leila Gurruwiwi +nm1222324,Emanuele Maggi +nm1310603,Aaron Jagielski +nm1516513,Jerry Belant +nm2098968,Jean-Louis Froment +nm5286652,Georgina Windsor +nm0077727,Dru Berrymore +nm0263457,Christine Ever +nm0221474,Paul Desmond +nm1286265,John Fox +nm2023033,Karen Yelverton +nm0856720,Josephine Tewson +nm1642617,Roy Weissinger +nm3908931,Andrew MacLarty +nm1111958,Lori Biggs +nm0510275,Rebecka Liljeberg +nm0169809,Tatiana Cohen +nm0261208,Tony Esposito +nm0165310,Charlie Clausen +nm6085926,Jim Green +nm6603464,Paula Phelan +nm0285464,Bjarne Forchhammer +nm1157445,Ting Wei Guo +nm1331291,Bert Doorn +nm1669076,Alexandra Cat +nm2208245,Masako Yashiro +nm1167166,Ross MacFarlane +nm0005192,Kellie Martin +nm0001360,John Holmes +nm0722023,David Reynoso +nm1722996,Thezni Khan +nm0004933,Faith Ford +nm0005324,Maury Povich +nm0001394,Derek Jacobi +nm7690217,Derek Johnson +nm8761191,Gemma Tognini +nm5099766,Troy Parker +nm1353235,Dakota Yandle +nm1616477,Pietro Cattani +nm1337764,Tajahi Cooke +nm1089766,Annuska Fényes +nm6639293,Jessie Pettit +nm2404113,Anna Luca Biani +nm0371381,Cynthia Haymon +nm2064629,Daniel Bell +nm8410537,Felix Heezemans +nm7287744,George Ray +nm1055833,Christopher Pittman Smith +nm0575675,Dayanara Medina +nm6890006,Briana Lacuesta +nm1278677,Anders Breinholt +nm0900867,Carol Vogel +nm1028561,Soneros de Verdad +nm8125221,Jeon Ik-ryeong +nm0327235,Pierre Gondard +nm1000570,Lincoln Chafee +nm1419448,Max Caden +nm0524640,Alvin Lucier +nm6745967,Joanne Davis +nm8731455,James Taylor-Watts +nm7011917,Gustav Stork Jangaard +nm0814130,Ferri Somogyi +nm5007018,Deanna Navarro +nm9028943,Katharina Willinger +nm1059726,Carmen Kassovitz +nm0370905,Bill Hayes +nm1237408,Marco Binder +nm7220702,Katalin Lightner +nm0855278,Vicente Tepedino +nm1939947,Diogo Savala +nm4857744,Eric Houde +nm0010684,Archi Adamos +nm5670593,Susanna Karvinen +nm1012627,Ling Chen +nm6371231,Chris Garcia +nm0181971,Renée Cossette +nm1479734,Valeriy Nikulin +nm0476851,Sergei Kuznetsov +nm6967886,Dahlia White +nm0817573,Norbert Speer +nm1659547,Bill Temple +nm1230334,Danit Livnat +nm1003887,Dexter Gawel +nm1195646,Pavlo Fondera +nm0417938,Vitold Janpavlis +nm4424993,Karan Kundrra +nm3657729,Juan A. Mingrone +nm5563725,Thomas Gamble +nm8984434,Lolita Pop +nm2430121,Ursula Schwarzer +nm0467082,Cezary Kosiński +nm7294634,Ariel Rodríguez +nm7115741,Gervasio Díaz Castelli +nm0582615,Hugo Metsers +nm3564713,Petroc Trelawny +nm1064339,Dan Rue +nm2426057,Edi Zanidache +nm1371900,Nethmi Roshel +nm6662430,Boris Dergachev +nm1613362,Lily Armah +nm2554072,Haley Scarnato +nm4316821,Haraldur Ágústsson +nm7532272,Elena Stecca +nm2591542,Malou von Sivers +nm5993784,Deborah O'Donnel +nm8350110,Anne Mary Ziegler +nm9712004,Daniel Wild +nm2895357,Sheila Scott +nm2322802,Shawna Beesley +nm4321090,Iakovos Panotas +nm9101165,Shivani Tomar +nm3027117,Matti Myllykoski +nm0388578,Isa Hoes +nm1784385,Rocket Bretherton +nm1670944,Elisa Cantonetti +nm1361194,Corey Weist +nm1013757,Alejandro Henriquez +nm1266866,Laurent Dupuis +nm1349147,Size 12 +nm1947060,Jeong Ae-yeon +nm3539201,Daniel Fischer +nm1207210,Anita Martínez +nm0350080,Luis Roberto Guzmán +nm5991382,Chiu Hung +nm0503482,Arnfried Lerche +nm7439612,Rio Sirah +nm9720157,Hadar Karako +nm8541237,Shane Madej +nm1102088,Adrián Otero +nm1041648,Bodine Jeske +nm0883781,Jorge Valdés García +nm1070295,Monika Kulczyk +nm0533306,Gisele MacKenzie +nm5552375,Arie Kruglanski +nm1689260,Manfred Sangel +nm1631527,Yves Duteil +nm3388031,Jonathan Maxwell Silver +nm1435036,Andy Harvey +nm2006248,Randy Robinson +nm3674708,David Serra +nm1000761,Per Thomsen +nm3550951,Ella Dale Lewis +nm1554305,Nikhil Angrish +nm0797705,Givi Sikharulidze +nm3802115,Rena Matsui +nm0001783,Sally Struthers +nm7863589,Irmgard Schwaetzer +nm1191822,Tommy Harris +nm3545544,Martin Harrington +nm1227486,Laura-Julie Perreault +nm1919300,Dana Galinsky +nm1045496,Julia Rajsp +nm8542276,Lisa Kennedy +nm1116177,Michiko Kichise +nm2075058,Douglas Hansell +nm4496001,Nathan Felix +nm3721224,Ion Ionut Ciocia +nm6769189,Benjamin Carlton +nm3395372,Viljo Kajava +nm1481134,Barbara Gagrinsky +nm0300494,Nacho Gadano +nm3725018,Andris Bulis +nm3232011,Rachel Jayson +nm9562083,Maria Comstock +nm1812334,Louise Bolton +nm1097527,Markus Koch +nm0363650,Åke Harnesk +nm1572939,Vivian +nm5328132,Abhishek Tiwari +nm2705287,Ben Tibbles +nm7179118,José Dos Santos +nm4866394,Sylvie Cohen +nm2064561,Knut Storberget +nm1103846,Olga Lifentseva +nm1045460,Henry Gründler +nm9863271,Andrea Horan +nm2915204,Dave Butz +nm1344112,Jawhar Al Sourchi +nm5764304,Nataly Mega +nm0149702,Maurice Chaillot +nm2060329,Eduardo Coma diff --git a/imdb/k6/six-degrees.js b/imdb/k6/six-degrees.js index e1b0c6e..e5fc4de 100644 --- a/imdb/k6/six-degrees.js +++ b/imdb/k6/six-degrees.js @@ -12,13 +12,20 @@ const SEED_QUERIES = [ 'James Smith', 'John Davis', 'Robert Miller', 'Michael Brown', 'John Miller', ]; -function loadFromCsv() { - let csv; - try { - csv = open('./data/sampled-people.csv'); - } catch (e) { - return []; - } +// open() must be called from k6's init context (top-level script scope, executed once when the +// script is parsed) - calling it from inside a function invoked during setup() throws "open() can +// only be called in the init context", silently caught by the try/catch below and falling through +// to the slow HTTP-based SEED_QUERIES discovery every single run, undetected until a real load +// test's setup() timed out after 60s despite a valid, populated CSV sitting right there. +let rawCsv = null; +try { + rawCsv = open('./data/sampled-people.csv'); +} catch (e) { + rawCsv = null; +} + +function parseCsv(csv) { + if (!csv) return []; return csv .split('\n') .slice(1) // header @@ -36,7 +43,7 @@ function loadFromCsv() { // person ids live from the API's own disambiguation responses when no CSV has been populated yet, // so this script still runs meaningfully against a freshly-seeded database with zero setup. export function setup() { - const fromCsv = loadFromCsv(); + const fromCsv = parseCsv(rawCsv); if (fromCsv.length >= 2) { return { people: fromCsv }; } diff --git a/imdb/src/main/resources/application.yaml b/imdb/src/main/resources/application.yaml index 8d5470e..d34ff0d 100644 --- a/imdb/src/main/resources/application.yaml +++ b/imdb/src/main/resources/application.yaml @@ -65,6 +65,14 @@ six-degrees: # visited set, so it never needs to arbitrarily drop neighbors to bound the search - it expands # every unvisited neighbor of the current frontier, which is what fixed a real bug (the old # capped-and-ordered fan-out could silently miss the true shortest path). + # Tried raising this to 5 after fixing the missing title_principals.nconst index (V4) - did not + # help: the ~25-30% failure rate under k6 load stayed essentially the same, it just made each + # failing request wait 5s instead of 2s before erroring. That rules out "just needs a bit more + # time" - there's a persistent population of genuinely hard pairs (likely: search reaches a large + # hub partway through expansion with no intersection yet, and processing that hub's full neighbor + # set for one level is itself expensive) that needs its own investigation, tracked as a follow-up + # rather than solved by this knob. Reverted to 2 - failing fast is better than failing slow when + # the timeout isn't fixing the underlying issue either way. query-timeout-seconds: 2 top-rated: diff --git a/imdb/src/main/resources/db/migration/V4__title_principals_nconst_index.sql b/imdb/src/main/resources/db/migration/V4__title_principals_nconst_index.sql new file mode 100644 index 0000000..300b8d7 --- /dev/null +++ b/imdb/src/main/resources/db/migration/V4__title_principals_nconst_index.sql @@ -0,0 +1,11 @@ +-- findAnyCommonTitle (JdbcTitleRepository - used once per hop to enrich a six-degrees path with the +-- shared title connecting each pair) filters title_principals by nconst with no category +-- restriction, but the only existing nconst index (idx_title_principals_nconst_acting, V1) is +-- partial - WHERE category IN ('actor', 'actress', 'self') - so it can't be used here. Confirmed via +-- EXPLAIN ANALYZE: without this index, the planner falls back to a Parallel Seq Scan over the +-- 100M-row table, over 1 second per call even with parallel workers helping. Under real k6 load +-- (50 concurrent six-degrees requests, each needing up to 7 of these calls to build a full path), +-- this alone drove Postgres CPU past 1500% and produced an 83% failure rate against the endpoint's +-- 2-second query timeout - not the bidirectional BFS function, which tested fast in isolation the +-- whole time. +CREATE INDEX idx_title_principals_nconst ON title_principals (nconst); From 05ba2843aa7a7060cbef85367494c5f41eb80c29 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Fri, 10 Jul 2026 10:13:58 +0200 Subject: [PATCH 14/42] Added structured json logging with sanitation --- imdb/docs/low-level-design.md | 50 +++++++++-- .../application/SixDegreesUseCaseImpl.java | 19 +++++ .../cache/CachingCoStarGraphRepository.java | 5 ++ .../cache/CachingTitleDetailUseCase.java | 5 ++ .../cache/CachingTitleSearchUseCase.java | 10 +++ .../cache/CachingTopRatedUseCase.java | 5 ++ .../JdbcCoStarGraphRepository.java | 26 +++++- .../persistence/JdbcPersonRepository.java | 8 +- .../persistence/JdbcTitleRepository.java | 21 ++++- .../presentation/ApiExceptionHandler.java | 33 +++++++- .../presentation/RequestLoggingFilter.java | 82 +++++++++++++++++++ .../imdb/utils/HeaderSanitizer.java | 29 +++++++ imdb/src/main/resources/application.yaml | 19 +++++ 13 files changed, 301 insertions(+), 11 deletions(-) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/RequestLoggingFilter.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/utils/HeaderSanitizer.java diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md index 226507a..b8ce362 100644 --- a/imdb/docs/low-level-design.md +++ b/imdb/docs/low-level-design.md @@ -34,11 +34,11 @@ alone (no build-tool module boundaries yet - see the open item in §11): | Layer | May import | Contains | |---|---|---| -| `presentation` | `application`, `infrastructure`, `domain`, `utils` | Controllers, request validation, `ApiExceptionHandler` | +| `presentation` | `application`, `infrastructure`, `domain`, `utils` | Controllers, request validation, `ApiExceptionHandler`, `RequestLoggingFilter` | | `infrastructure` | `application`, `domain`, `utils` | JDBC repository implementations, Redis caching decorators, Spring `@Configuration` | | `application` | `domain`, `utils` | Use-case interfaces + implementations, use-case-specific result types | | `domain` | *(nothing)* | Entities/value objects, repository **interfaces**, domain exceptions | -| `utils` | *(nothing)* | `ImdbIds` - pure, framework-free helpers | +| `utils` | *(nothing)* | `ImdbIds`, `HeaderSanitizer` - pure, framework-free helpers | Never: `domain` importing `application`/`infrastructure`; `application` importing `infrastructure`. The second rule is the one that actually matters day to day - application code calls domain interfaces only, @@ -120,6 +120,7 @@ imdb/ ImdbApplication.java utils/ ImdbIds.java + HeaderSanitizer.java # redacts sensitive headers before logging (§7) domain/ model/ TitleSummary.java @@ -171,12 +172,17 @@ imdb/ GenreController.java PersonController.java ApiExceptionHandler.java + RequestLoggingFilter.java # request id + sanitized request/response logging (§7) resources/ application.yaml db/migration/ V0__base_schema.sql V1__extensions_and_search_indexes.sql V2__co_star_edges_materialized_view.sql + V3__shortest_co_star_path_function.sql # find_shortest_co_star_path PL/pgSQL BFS, §5.2-5.3 + V4__title_principals_nconst_index.sql # full nconst index - findAnyCommonTitle needs it + # across all categories, not just the partial + # acting-only index V1 created test/ java/com/ludovictemgoua/imdb/ (unit tests against domain interfaces, controller tests, Testcontainers integration tests - §10) @@ -604,10 +610,42 @@ instead of just measuring a warm Redis round-trip after the first request - see - note this property lives under `management.opentelemetry.*`, not the old `management.otlp.*` namespace, matching `docker-compose.yaml`. `management.tracing.sampling.probability=1.0` for this exercise (full sampling; would be tuned down in a real production deployment under real traffic volume). -- **Logging**: structured JSON via Spring Boot's built-in structured logging support, trace/span IDs - included automatically via Micrometer Tracing's MDC integration, shipped to Loki via Grafana Alloy - (already wired in `docker-compose.yaml` / `observability/alloy/config.alloy`) - no application-side - logging-shipper dependency needed. +- **Logging**: structured JSON via Spring Boot 4.1's native structured logging (`logging.structured. + format.console: logstash` - confirmed present directly in the spring-boot-4.1.0 jar, + `org.springframework.boot.logging.structured.*`; no `logstash-logback-encoder` or other dependency + needed), shipped to Loki via Grafana Alloy (already wired in `docker-compose.yaml` / + `observability/alloy/config.alloy`). "logstash" format chosen over the built-in ECS/GELF + alternatives since it's schema-agnostic and Loki doesn't care about a specific schema, unlike ECS + (Elastic-specific) or GELF (Graylog-specific). + - **Correlation IDs**: every MDC entry is automatically included in each JSON line, which is what + carries two independent identifiers with no per-log-statement wiring: `traceId`/`spanId` (already + populated by Micrometer Tracing whenever a span is active) and `requestId` - a dedicated id + assigned by `presentation.RequestLoggingFilter`, deliberately independent of tracing so it stays a + reliable per-request identifier even if trace sampling is later turned down from today's 100% + (`management.tracing.sampling.probability`). The filter honors an incoming `X-Request-Id` header + if the caller already generated one, otherwise generates a UUID; echoes it back as a response + header; and clears it from MDC in a `finally` block so it can't leak onto the next request handled + by the same pooled thread. Runs at `Ordered.HIGHEST_PRECEDENCE` so the id is set as early as + possible in the chain. + - **Sanitizer**: `utils.HeaderSanitizer` redacts a deny-list (`Authorization`, `Cookie`, + `Set-Cookie`, `X-Api-Key`) before `RequestLoggingFilter` logs request headers. This API has no + auth today, so nothing sensitive flows through yet - the point is that logging is already correct + the moment auth (or any header carrying a secret) is added, not something to retrofit later. + Framework-agnostic by design (operates on a plain `Map`, not + `HttpServletRequest`) so it stays usable from `utils` without pulling in the Servlet API. + - **Level policy** (`logging.level.com.ludovictemgoua.imdb`, default `INFO`, overridable per + environment via the standard `LOGGING_LEVEL_COM_LUDOVICTEMGOUA_IMDB` env var with no code change): + INFO for request start/end (`RequestLoggingFilter`) and business-significant outcomes worth their + own line beyond the request summary (`SixDegreesUseCaseImpl` - person-resolution ambiguity, and + the computed degree/timing, since this is the one use case with real, previously-invisible + performance variance all session); DEBUG for query params/row counts in + `infrastructure.persistence` and cache-miss events in `infrastructure.cache` (`@Cacheable` only + invokes the annotated method on a miss, so a log statement inside it is inherently a miss signal - + aggregate hit ratio is already tracked via Micrometer's cache metrics, the Cache Hit Ratio + dashboard); WARN for `find_shortest_co_star_path` calls over 1 second + (`JdbcCoStarGraphRepository`); DEBUG for expected 4xx conditions and ERROR (with the full + exception) for anything unhandled reaching `ApiExceptionHandler`'s catch-all, so an unexpected + failure is never silently reduced to a bare 500 with no trace of the real cause. - **Correlation**: `observability/grafana/provisioning/datasources/datasources.yml` already wires Loki-derived-fields -> Tempo and Tempo -> Loki/Prometheus, so a trace opened in Grafana click-throughs to its log lines and vice versa. diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java index 43a88f8..bb9c410 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java @@ -9,6 +9,8 @@ import com.ludovictemgoua.imdb.domain.repository.PersonRepository; import com.ludovictemgoua.imdb.domain.repository.TitleRepository; import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; import java.util.ArrayList; @@ -19,6 +21,8 @@ @Service public class SixDegreesUseCaseImpl implements SixDegreesUseCase { + private static final Logger log = LoggerFactory.getLogger(SixDegreesUseCaseImpl.class); + private final PersonResolutionUseCase personResolution; private final CoStarGraphRepository graphRepository; private final PersonRepository personRepository; @@ -36,16 +40,20 @@ public SixDegreesUseCaseImpl(PersonResolutionUseCase personResolution, CoStarGra public SixDegreesOutcome compute(String queryA, String queryB, int maxDegree) { PersonResolution resolvedA = personResolution.resolve(queryA); if (resolvedA instanceof PersonResolution.Ambiguous a) { + log.info("person resolution ambiguous: query={} candidateCount={}", queryA, a.candidates().size()); return new SixDegreesOutcome.Ambiguous(queryA, a.candidates()); } if (resolvedA instanceof PersonResolution.NotFound) { + log.info("person resolution not found: query={}", queryA); return new SixDegreesOutcome.PersonNotFound(queryA); } PersonResolution resolvedB = personResolution.resolve(queryB); if (resolvedB instanceof PersonResolution.Ambiguous b) { + log.info("person resolution ambiguous: query={} candidateCount={}", queryB, b.candidates().size()); return new SixDegreesOutcome.Ambiguous(queryB, b.candidates()); } if (resolvedB instanceof PersonResolution.NotFound) { + log.info("person resolution not found: query={}", queryB); return new SixDegreesOutcome.PersonNotFound(queryB); } @@ -60,14 +68,25 @@ public SixDegreesOutcome compute(String queryA, String queryB, int maxDegree) { new SixDegreesResult(personA, personB, 0, true, List.of(onlyStep))); } + // Timed explicitly (not just left to the request-level duration in RequestLoggingFilter) - + // this is the one query in the whole app whose cost varies by graph shape rather than being + // a bounded index lookup (LLD §5), so its own duration is worth a dedicated log line to spot + // a slow pair without having to cross-reference the trace. + long startMillis = System.currentTimeMillis(); Optional match = graphRepository.findShortestPath(a.nconst(), b.nconst()); + long durationMs = System.currentTimeMillis() - startMillis; + if (match.isEmpty()) { + log.info("six degrees not found: personA={} personB={} durationMs={}", + personA.id(), personB.id(), durationMs); return new SixDegreesOutcome.Found( new SixDegreesResult(personA, personB, null, false, List.of())); } GraphPath path = match.get(); boolean withinMax = path.degree() <= maxDegree; + log.info("six degrees computed: personA={} personB={} degree={} withinMax={} durationMs={}", + personA.id(), personB.id(), path.degree(), withinMax, durationMs); List steps = withinMax ? buildPath(path.personIds()) : List.of(); return new SixDegreesOutcome.Found( new SixDegreesResult(personA, personB, path.degree(), withinMax, steps)); diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java index eae78f1..84b7fc2 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepository.java @@ -3,6 +3,8 @@ import com.ludovictemgoua.imdb.domain.model.GraphPath; import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; import com.ludovictemgoua.imdb.infrastructure.persistence.JdbcCoStarGraphRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Repository; @@ -16,6 +18,8 @@ @Primary public class CachingCoStarGraphRepository implements CoStarGraphRepository { + private static final Logger log = LoggerFactory.getLogger(CachingCoStarGraphRepository.class); + private final JdbcCoStarGraphRepository delegate; public CachingCoStarGraphRepository(JdbcCoStarGraphRepository delegate) { @@ -26,6 +30,7 @@ public CachingCoStarGraphRepository(JdbcCoStarGraphRepository delegate) { @Cacheable(cacheNames = "six-degrees", key = "T(java.lang.Math).min(#personA, #personB) + '-' + T(java.lang.Math).max(#personA, #personB)") public Optional findShortestPath(int personA, int personB) { + log.debug("cache miss, computing: cache=six-degrees personA={} personB={}", personA, personB); return delegate.findShortestPath(personA, personB); } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java index 6507b22..f3705eb 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCase.java @@ -3,6 +3,8 @@ import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; import com.ludovictemgoua.imdb.application.TitleDetailUseCaseImpl; import com.ludovictemgoua.imdb.domain.model.TitleDetail; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -11,6 +13,8 @@ @Primary public class CachingTitleDetailUseCase implements TitleDetailUseCase { + private static final Logger log = LoggerFactory.getLogger(CachingTitleDetailUseCase.class); + private final TitleDetailUseCaseImpl delegate; public CachingTitleDetailUseCase(TitleDetailUseCaseImpl delegate) { @@ -20,6 +24,7 @@ public CachingTitleDetailUseCase(TitleDetailUseCaseImpl delegate) { @Override @Cacheable(cacheNames = "title-detail", key = "#titleId") public TitleDetail getDetail(String titleId) { + log.debug("cache miss, computing: cache=title-detail titleId={}", titleId); return delegate.getDetail(titleId); } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java index c5341ae..76c07f5 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCase.java @@ -4,6 +4,8 @@ import com.ludovictemgoua.imdb.application.TitleSearchUseCaseImpl; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.TitleSummary; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -15,6 +17,8 @@ @Primary public class CachingTitleSearchUseCase implements TitleSearchUseCase { + private static final Logger log = LoggerFactory.getLogger(CachingTitleSearchUseCase.class); + private final TitleSearchUseCaseImpl delegate; public CachingTitleSearchUseCase(TitleSearchUseCaseImpl delegate) { @@ -24,6 +28,12 @@ public CachingTitleSearchUseCase(TitleSearchUseCaseImpl delegate) { @Override @Cacheable(cacheNames = "title-search", key = "#query + ':' + #page + ':' + #size") public PagedResult search(String query, int page, int size) { + // @Cacheable only calls the annotated method on a miss (Spring's caching proxy intercepts + // hits before this body ever runs) - so this line is inherently a cache-miss signal, not + // something that needs its own hit/miss branching. Aggregate hit ratio is already tracked via + // Micrometer's auto-bound cache metrics (LLD §6/§7, the Cache Hit Ratio dashboard); this is + // the per-request complement for tracing a specific slow request back to "it missed cache". + log.debug("cache miss, computing: cache=title-search query={} page={} size={}", query, page, size); return delegate.search(query, page, size); } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java index 4fea817..7dc936c 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCase.java @@ -3,6 +3,8 @@ import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; import com.ludovictemgoua.imdb.application.TopRatedUseCaseImpl; import com.ludovictemgoua.imdb.domain.model.GenreTopRatedItem; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.cache.annotation.Cacheable; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -13,6 +15,8 @@ @Primary public class CachingTopRatedUseCase implements TopRatedUseCase { + private static final Logger log = LoggerFactory.getLogger(CachingTopRatedUseCase.class); + private final TopRatedUseCaseImpl delegate; public CachingTopRatedUseCase(TopRatedUseCaseImpl delegate) { @@ -22,6 +26,7 @@ public CachingTopRatedUseCase(TopRatedUseCaseImpl delegate) { @Override @Cacheable(cacheNames = "top-rated", key = "#genre + ':' + #limit + ':' + #minVotes") public List findTopRated(String genre, int limit, Integer minVotes) { + log.debug("cache miss, computing: cache=top-rated genre={} limit={} minVotes={}", genre, limit, minVotes); return delegate.findTopRated(genre, limit, minVotes); } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java index 69040f2..4fa11df 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCoStarGraphRepository.java @@ -2,6 +2,8 @@ import com.ludovictemgoua.imdb.domain.model.GraphPath; import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; @@ -19,6 +21,14 @@ @Repository public class JdbcCoStarGraphRepository implements CoStarGraphRepository { + private static final Logger log = LoggerFactory.getLogger(JdbcCoStarGraphRepository.class); + + // A load test found a persistent tail of pairs taking multiple seconds even after fixing the + // two real bugs (LLD §5.2) and a missing index (V4) - likely the search reaching a large hub + // partway through expansion with no intersection yet. This threshold flags that population in + // logs (distinct from the use case's own per-call INFO line) without needing a trace lookup. + private static final long SLOW_QUERY_THRESHOLD_MILLIS = 1000; + private final NamedParameterJdbcTemplate jdbc; private final int sideCap; private final int absoluteMaxDegree; @@ -56,7 +66,21 @@ public Optional findShortestPath(int personA, int personB) { .addValue("personA", personA).addValue("personB", personB) .addValue("sideCap", sideCap).addValue("absoluteMaxDegree", absoluteMaxDegree); - return jdbc.query(sql, params, JdbcCoStarGraphRepository::mapGraphPath).stream().findFirst(); + log.debug("executing find_shortest_co_star_path: personA={} personB={} sideCap={} absoluteMaxDegree={}", + personA, personB, sideCap, absoluteMaxDegree); + long startMillis = System.currentTimeMillis(); + Optional result = + jdbc.query(sql, params, JdbcCoStarGraphRepository::mapGraphPath).stream().findFirst(); + long durationMs = System.currentTimeMillis() - startMillis; + + if (durationMs > SLOW_QUERY_THRESHOLD_MILLIS) { + log.warn("slow find_shortest_co_star_path: personA={} personB={} durationMs={}", + personA, personB, durationMs); + } else { + log.debug("find_shortest_co_star_path completed: personA={} personB={} durationMs={} found={}", + personA, personB, durationMs, result.isPresent()); + } + return result; } private static GraphPath mapGraphPath(ResultSet rs, int rowNum) throws SQLException { diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java index 3ba7bfc..80d12dc 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java @@ -3,6 +3,8 @@ import com.ludovictemgoua.imdb.domain.model.PersonCandidate; import com.ludovictemgoua.imdb.domain.repository.PersonRepository; import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -20,6 +22,8 @@ @Repository public class JdbcPersonRepository implements PersonRepository { + private static final Logger log = LoggerFactory.getLogger(JdbcPersonRepository.class); + private final NamedParameterJdbcTemplate jdbc; public JdbcPersonRepository(NamedParameterJdbcTemplate jdbc) { @@ -35,7 +39,9 @@ public List findByName(String name) { ORDER BY similarity(primary_name, :name) DESC LIMIT 10 """; - return jdbc.query(sql, Map.of("name", name), JdbcPersonRepository::mapCandidate); + List candidates = jdbc.query(sql, Map.of("name", name), JdbcPersonRepository::mapCandidate); + log.debug("person lookup: name={} candidateCount={}", name, candidates.size()); + return candidates; } @Override diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java index f7be74d..ef44b13 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java @@ -9,6 +9,8 @@ import com.ludovictemgoua.imdb.domain.model.TitleSummary; import com.ludovictemgoua.imdb.domain.repository.TitleRepository; import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.stereotype.Repository; @@ -23,6 +25,8 @@ @Repository public class JdbcTitleRepository implements TitleRepository { + private static final Logger log = LoggerFactory.getLogger(JdbcTitleRepository.class); + private final NamedParameterJdbcTemplate jdbc; public JdbcTitleRepository(NamedParameterJdbcTemplate jdbc) { @@ -49,6 +53,10 @@ SELECT count(*) FROM title_basics List content = jdbc.query(dataSql, params, JdbcTitleRepository::mapSummary); Long total = jdbc.queryForObject(countSql, params, Long.class); + // total is an under-count for very common query terms (gin_fuzzy_search_limit, V1 migration) + // - worth having at DEBUG to notice if that trade-off ever looks wrong for a specific term. + log.debug("title search: query={} page={} size={} returned={} total={}", + query, page, size, content.size(), total); return new PagedResult<>(content, total == null ? 0 : total, page, size); } @@ -118,7 +126,9 @@ stats AS (SELECT AVG(average_rating) AS mean_rating FROM pool) """; var params = new MapSqlParameterSource() .addValue("genre", genre).addValue("minVotes", minVotes).addValue("limit", limit); - return jdbc.query(sql, params, JdbcTitleRepository::mapTopRated); + List results = jdbc.query(sql, params, JdbcTitleRepository::mapTopRated); + log.debug("top rated: genre={} limit={} minVotes={} returned={}", genre, limit, minVotes, results.size()); + return results; } @Override @@ -132,9 +142,16 @@ public Optional findAnyCommonTitle(int personA, int personB) { LIMIT 1 """; var params = new MapSqlParameterSource().addValue("personA", personA).addValue("personB", personB); - return jdbc.query(sql, params, (rs, rowNum) -> + // findAnyCommonTitle was the site of a real bug (V4 migration) - title_principals had no + // usable index on nconst, so this fell back to a 1s+ sequential scan of a 100M-row table on + // every call. DEBUG timing here would have caught a regression of that fix immediately. + long startMillis = System.currentTimeMillis(); + Optional result = jdbc.query(sql, params, (rs, rowNum) -> new SharedTitle(ImdbIds.formatTitleId(rs.getInt("tconst")), rs.getString("primary_title"))) .stream().findFirst(); + log.debug("find any common title: personA={} personB={} durationMs={} found={}", + personA, personB, System.currentTimeMillis() - startMillis, result.isPresent()); + return result; } private List findCrew(int tconst, String column) { diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java index 9d21676..26097fd 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java @@ -2,21 +2,41 @@ import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import jakarta.validation.ConstraintViolationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.http.ProblemDetail; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +// Extends ResponseEntityExceptionHandler rather than starting from a bare @RestControllerAdvice - it +// already correctly handles the whole family of standard Spring MVC exceptions (missing/malformed +// request params, wrong HTTP method, unsupported media type, no static resource, etc.) with the +// right status codes. Discovered why this matters the hard way: a bare-bones catch-all +// @ExceptionHandler(Exception.class) below is broad enough to shadow ALL of that built-in handling +// (Spring resolves to the most specific declared exception type, and plain Exception was the only +// thing registered for any of them) - a browser's routine /favicon.ico request, a missing query +// param, and a wrong HTTP verb all turned into a 500 "unexpected error" instead of their real 404/ +// 400/405. Extending the base class restores that handling for free; our own handlers below only +// need to cover what it doesn't already know about (this API's own domain exceptions) plus the +// generic catch-all for anything genuinely unexpected. @RestControllerAdvice -public class ApiExceptionHandler { +public class ApiExceptionHandler extends ResponseEntityExceptionHandler { + + private static final Logger log = LoggerFactory.getLogger(ApiExceptionHandler.class); @ExceptionHandler(NotFoundException.class) public ProblemDetail handleNotFound(NotFoundException ex) { + // 404 is an expected, routine outcome for this API (a title/person id that doesn't exist) - + // not an application fault, so DEBUG rather than WARN/ERROR. + log.debug("not found: {}", ex.getMessage()); return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, ex.getMessage()); } @ExceptionHandler(IllegalArgumentException.class) public ProblemDetail handleBadId(IllegalArgumentException ex) { + log.debug("bad request: {}", ex.getMessage()); return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage()); } @@ -26,6 +46,17 @@ public ProblemDetail handleBadId(IllegalArgumentException ex) { // the assumption the newer auto-handling applied here; it doesn't for @Validated-triggered validation). @ExceptionHandler(ConstraintViolationException.class) public ProblemDetail handleConstraintViolation(ConstraintViolationException ex) { + log.debug("bad request: {}", ex.getMessage()); return ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, ex.getMessage()); } + + // Catch-all for anything not already handled above - without this, an unexpected failure (a bug, + // a downstream outage) would only surface as a generic 500 from Spring Boot's default error + // controller, with the real cause visible only if you already knew to go dig through a stack + // trace dump. Logging it at ERROR with the full exception here means it's never silently lost. + @ExceptionHandler(Exception.class) + public ProblemDetail handleUnexpected(Exception ex) { + log.error("unexpected error", ex); + return ProblemDetail.forStatusAndDetail(HttpStatus.INTERNAL_SERVER_ERROR, "An unexpected error occurred"); + } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/RequestLoggingFilter.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/RequestLoggingFilter.java new file mode 100644 index 0000000..f661b40 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/RequestLoggingFilter.java @@ -0,0 +1,82 @@ +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.utils.HeaderSanitizer; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; + +// Runs first in the filter chain (Ordered.HIGHEST_PRECEDENCE) so the request id is in MDC - and +// therefore in every structured log line, including ones from other filters/interceptors - for as +// much of the request's lifecycle as possible. A plain @Component is enough for Spring Boot to +// auto-register any jakarta.servlet.Filter bean; no separate FilterRegistrationBean needed. +@Component +@Order(Ordered.HIGHEST_PRECEDENCE) +public class RequestLoggingFilter extends OncePerRequestFilter { + + private static final Logger log = LoggerFactory.getLogger(RequestLoggingFilter.class); + private static final String REQUEST_ID_HEADER = "X-Request-Id"; + private static final String MDC_KEY = "requestId"; + + // Prometheus scrapes /actuator/prometheus every ~15s and Docker/orchestrator health checks poll + // /actuator/health continuously - neither is real application traffic, and logging them at INFO + // would drown out the requests that actually matter. shouldNotFilter skips the whole filter (no + // requestId, no log lines) for these rather than just suppressing the log statements, so actuator + // traffic doesn't pay even the MDC/timing overhead. + @Override + protected boolean shouldNotFilter(HttpServletRequest request) { + return request.getRequestURI().startsWith("/actuator"); + } + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) throws ServletException, IOException { + String requestId = resolveRequestId(request); + MDC.put(MDC_KEY, requestId); + response.setHeader(REQUEST_ID_HEADER, requestId); + + long startMillis = System.currentTimeMillis(); + log.info("request started: method={} path={} headers={}", + request.getMethod(), request.getRequestURI(), HeaderSanitizer.sanitize(headersOf(request))); + try { + filterChain.doFilter(request, response); + } finally { + log.info("request completed: method={} path={} status={} durationMs={}", + request.getMethod(), request.getRequestURI(), response.getStatus(), + System.currentTimeMillis() - startMillis); + // Threads are pooled and reused across requests - leaving this set would leak the + // previous request's id into the next request handled by the same thread. + MDC.remove(MDC_KEY); + } + } + + // Honors an id the caller already generated (e.g. an upstream gateway) so a single request's + // logs stay correlated end-to-end across services, rather than getting a new id at each hop. + private static String resolveRequestId(HttpServletRequest request) { + String incoming = request.getHeader(REQUEST_ID_HEADER); + return (incoming == null || incoming.isBlank()) ? UUID.randomUUID().toString() : incoming; + } + + private static Map headersOf(HttpServletRequest request) { + Map headers = new LinkedHashMap<>(); + var names = request.getHeaderNames(); + if (names == null) { + return headers; + } + Collections.list(names).forEach(name -> headers.put(name, request.getHeader(name))); + return headers; + } +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/utils/HeaderSanitizer.java b/imdb/src/main/java/com/ludovictemgoua/imdb/utils/HeaderSanitizer.java new file mode 100644 index 0000000..b19d76b --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/utils/HeaderSanitizer.java @@ -0,0 +1,29 @@ +package com.ludovictemgoua.imdb.utils; + +import java.util.LinkedHashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +public final class HeaderSanitizer { + + private static final String REDACTED = "***REDACTED***"; + + // This API has no auth today, but request headers get logged wholesale by RequestLoggingFilter - + // redacting known-sensitive ones here means that logging is already safe the moment auth (or any + // header carrying a secret) is added, rather than something to remember to retrofit later. + private static final Set SENSITIVE_HEADERS = + Set.of("authorization", "cookie", "set-cookie", "x-api-key"); + + private HeaderSanitizer() { + } + + public static Map sanitize(Map headers) { + Map sanitized = new LinkedHashMap<>(); + for (Map.Entry entry : headers.entrySet()) { + boolean sensitive = SENSITIVE_HEADERS.contains(entry.getKey().toLowerCase(Locale.ROOT)); + sanitized.put(entry.getKey(), sensitive ? REDACTED : entry.getValue()); + } + return sanitized; + } +} diff --git a/imdb/src/main/resources/application.yaml b/imdb/src/main/resources/application.yaml index d34ff0d..56c480f 100644 --- a/imdb/src/main/resources/application.yaml +++ b/imdb/src/main/resources/application.yaml @@ -77,3 +77,22 @@ six-degrees: top-rated: default-min-votes: 1000 + +logging: + structured: + format: + # Boot 4.1's native structured logging (org.springframework.boot.logging.structured, verified + # directly in the spring-boot-4.1.0 jar) - no logstash-logback-encoder or other dependency + # needed. "logstash" is a plain, schema-agnostic flat JSON shape (timestamp/level/logger/ + # message + all MDC entries) - the right choice for Loki, which doesn't care about a specific + # schema, unlike ECS (Elastic-specific) or GELF (Graylog-specific). MDC entries - traceId/ + # spanId (already populated by Micrometer Tracing) and requestId (RequestLoggingFilter, + # presentation layer) - are included in every line automatically, no per-log-statement wiring. + console: logstash + level: + root: INFO + # Overridable per-environment via the standard Spring Boot env var + # (LOGGING_LEVEL_COM_LUDOVICTEMGOUA_IMDB=DEBUG) with no code change - e.g. to get per-query + # detail from infrastructure.persistence/cache while debugging locally, without turning up noise + # from the framework itself (Spring/Hikari/Tomcat stay at root's INFO). + com.ludovictemgoua.imdb: INFO From 4d46e91ecfea30e876d54f48bc0d1f97b0c168f8 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Fri, 10 Jul 2026 10:22:38 +0200 Subject: [PATCH 15/42] Added Github action ci file --- .github/workflows/imdb-ci.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/imdb-ci.yml diff --git a/.github/workflows/imdb-ci.yml b/.github/workflows/imdb-ci.yml new file mode 100644 index 0000000..2d4b9bd --- /dev/null +++ b/.github/workflows/imdb-ci.yml @@ -0,0 +1,27 @@ +name: imdb CI + +on: + push: + paths: + - 'imdb/**' + - '.github/workflows/imdb-ci.yml' + pull_request: + paths: + - 'imdb/**' + - '.github/workflows/imdb-ci.yml' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + cache: maven + + - name: Run tests + working-directory: imdb + run: mvn -B test From 6880f6ba09492aae95b893a0e7bb19f2af2a683d Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sat, 11 Jul 2026 10:53:58 +0200 Subject: [PATCH 16/42] Restructured integration tests and added e2e test using postman/newman --- .github/workflows/imdb-ci.yml | 84 ++++++- imdb/docker-compose.e2e.yaml | 90 ++++++++ imdb/docs/low-level-design.md | 133 ++++++++++-- imdb/pom.xml | 36 +++ imdb/postman/imdb-e2e.postman_collection.json | 205 ++++++++++++++++++ ...gCoStarGraphRepositoryIntegrationTest.java | 46 ++++ ...hingTitleDetailUseCaseIntegrationTest.java | 46 ++++ ...hingTitleSearchUseCaseIntegrationTest.java | 51 +++++ ...CachingTopRatedUseCaseIntegrationTest.java | 46 ++++ 9 files changed, 713 insertions(+), 24 deletions(-) create mode 100644 imdb/docker-compose.e2e.yaml create mode 100644 imdb/postman/imdb-e2e.postman_collection.json create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseIntegrationTest.java diff --git a/.github/workflows/imdb-ci.yml b/.github/workflows/imdb-ci.yml index 2d4b9bd..89c7dfd 100644 --- a/.github/workflows/imdb-ci.yml +++ b/.github/workflows/imdb-ci.yml @@ -11,7 +11,7 @@ on: - '.github/workflows/imdb-ci.yml' jobs: - test: + unit: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -22,6 +22,86 @@ jobs: java-version: '21' cache: maven - - name: Run tests + - 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 diff --git a/imdb/docker-compose.e2e.yaml b/imdb/docker-compose.e2e.yaml new file mode 100644 index 0000000..973365d --- /dev/null +++ b/imdb/docker-compose.e2e.yaml @@ -0,0 +1,90 @@ +# Explicit project name - without this, Compose derives the project name from the directory +# ("imdb"), the SAME default the main docker-compose.yaml gets, and this file's service names +# (postgres/redis) collide with that stack's, causing Compose to "recreate" - replace - the real dev +# containers with this file's empty ones. Confirmed the hard way: running this once while the main +# stack was up swapped out imdb-postgres (100M+ imported rows) for a fresh, empty postgres:17 - no +# data was actually lost (it lives in the imdb_imdb_data named volume, untouched), but the running +# container was gone until the main stack was brought back up. This name isolates the two entirely. +name: imdb-e2e + +networks: + imdb-e2e-net: + name: imdb-e2e-net + +services: + # --------------------------------------------------------------------- + # Plain postgres:17, not abanda/imdb-postgresql - the real image's dataset + # import takes 20-30 minutes, which is fine for local dev but not for a + # CI stage that should run on every push. imdb-service's own Flyway + # migrations build the schema here (same V0-V4 migrations as production, + # V0's CREATE TABLE IF NOT EXISTS actually creates the tables this time, + # since this schema starts genuinely empty); the seed service below then + # loads the same small, known fixture dataset the integration tests use. + # --------------------------------------------------------------------- + postgres: + image: postgres:17 + environment: + POSTGRES_USER: imdb + POSTGRES_PASSWORD: password + POSTGRES_DB: imdb + healthcheck: + test: ["CMD-SHELL", "pg_isready -U imdb -d imdb"] + interval: 5s + timeout: 5s + retries: 10 + networks: + - imdb-e2e-net + + redis: + image: redis:7-alpine + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 5s + retries: 5 + networks: + - imdb-e2e-net + + imdb-service: + build: + context: . + dockerfile: Dockerfile + ports: + - "8080:8080" + environment: + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/imdb + SPRING_DATASOURCE_USERNAME: imdb + SPRING_DATASOURCE_PASSWORD: password + SPRING_DATA_REDIS_HOST: redis + SPRING_DATA_REDIS_PORT: "6379" + # No tracing/metrics export configured - the e2e stage only needs the app + its data stores, + # not the full observability stack (that's exercised separately, LLD §7/§8). + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-sf", "http://localhost:8080/actuator/health"] + interval: 5s + timeout: 5s + retries: 30 + start_period: 30s + networks: + - imdb-e2e-net + + # One-shot: waits for imdb-service to be healthy (so Flyway has already built the schema), then + # loads the same fixture dataset the Testcontainers integration tests use - one dataset, not two to + # keep in sync. Exits after loading; the Postman/Newman run against the now-seeded stack. + seed: + image: postgres:17 + depends_on: + imdb-service: + condition: service_healthy + environment: + PGPASSWORD: password + volumes: + - ./src/test/resources/fixtures/fixture-data.sql:/seed/fixture-data.sql:ro + entrypoint: ["psql", "-h", "postgres", "-U", "imdb", "-d", "imdb", "-f", "/seed/fixture-data.sql"] + networks: + - imdb-e2e-net diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md index b8ce362..421f8af 100644 --- a/imdb/docs/low-level-design.md +++ b/imdb/docs/low-level-design.md @@ -96,6 +96,9 @@ imdb/ pom.xml Dockerfile docker-compose.yaml + docker-compose.e2e.yaml # lightweight plain-postgres stack for the CI e2e stage, §10 + postman/ + imdb-e2e.postman_collection.json # Newman-run contract tests against the e2e stack, §10 docs/ REQUIREMENTS.md product-design.md @@ -185,10 +188,17 @@ imdb/ # acting-only index V1 created test/ java/com/ludovictemgoua/imdb/ - (unit tests against domain interfaces, controller tests, Testcontainers integration tests - §10) + application/ # unit tests, mocked domain.repository interfaces - §10 + infrastructure/ + persistence/*IntegrationTest.java # Testcontainers Postgres - §10 + cache/*Test.java # unit: mocked delegate, no Spring context - §10 + cache/*IntegrationTest.java # integration: Testcontainers Redis, real (de)serialization - §10 + presentation/ # MockMvc controller tests, mocked use cases + TestcontainersConfiguration.java resources/ fixtures/ - fixture-data.sql + fixture-data.sql # single source of truth: integration tests (@Sql) and + # the e2e stage's seed service both load this same file ``` `application.yaml`, not `.properties`: the config surface is more nested than a typical CRUD app - @@ -690,31 +700,106 @@ docker-compose --profile load-test run k6 run /scripts/six-degrees.js ## 10. Test Plan The seeded `abanda/imdb-postgresql` image is ~20GB and takes 20-30 minutes to import - unusable as a CI -dependency. Testing splits accordingly, and the onion split from §2 changes *what* "unit test" means here -for the better: use-case implementations are tested against mocked `domain.repository` **interfaces** -with plain Mockito, no Spring context and no Testcontainers required at all. +dependency. Testing splits into three tiers - unit, integration, e2e/contract - run as three sequential +jobs in `.github/workflows/imdb-ci.yml` (`unit` -> `integration` -> `e2e`, each gated on the previous one +passing), and the onion split from §2 changes *what* "unit test" means here for the better: use-case +implementations are tested against mocked `domain.repository` **interfaces** with plain Mockito, no Spring +context and no Testcontainers required at all. + +### 10.1 Unit tests (Maven Surefire, `mvn test`) -- **Unit tests**: `application`-layer `*UseCaseImpl` classes against mocked `domain.repository` +- **Use-case tests**: `application`-layer `*UseCaseImpl` classes against mocked `domain.repository` interfaces (JUnit 5 + Mockito + AssertJ, matching `votee`'s existing testing style in this monorepo). Because these are pure interface mocks, none of these tests touch Postgres, Redis, or Spring at all. -- **Decorator tests**: a small, separate test per `infrastructure.cache` decorator verifying it actually - delegates on a cache miss and doesn't re-invoke the delegate on a hit - previously moot (the old - `DistanceCache` design in §2.1 needed this reasoned about carefully to avoid the self-invocation - pitfall); now a simple, mechanical test against a mock delegate. -- **Integration tests**: Testcontainers running a plain `postgres:17` image, exercising the - `infrastructure.persistence` implementations directly against their `domain.repository` interface - contracts. Flyway runs `V0`/`V1`/`V2` from §3 automatically on context startup (`V0` is what actually - creates the base tables here - see §3.4), then a small hand-authored `fixture-data.sql` (loaded via - `@Sql` on the test class, which runs after the context - and therefore Flyway - is already up) seeds - rows covering: a known multi-hop co-star chain (to exercise the bidirectional CTE end-to-end, including - a deliberate case where the true path requires more than one hop on each side), a tied weighted-rating - case, and an ambiguous shared name. Fast and deterministic. +- **Decorator unit tests** (`infrastructure.cache.Caching*Test`): verify each decorator delegates on a + cache miss and doesn't re-invoke the delegate on a hit, against a mocked delegate with a plain + `ConcurrentMapCacheManager` (or an outright mock `Cache`) - no Spring context, no real Redis. Previously + this reasoning needed care (the old `DistanceCache` design in §2.1 had a self-invocation pitfall to + avoid); now it's a simple, mechanical test. **What this tier structurally cannot catch**: an in-memory + map never serializes anything, so a real Redis (de)serialization bug - e.g. the `GenericJacksonJsonRedis- + Serializer` type-metadata `ClassCastException` this project hit earlier - passes every one of these tests + while still breaking in production. That gap is closed in §10.2, not here. - **Controller tests**: `MockMvc` against mocked `application`-layer use-case interfaces (`@MockitoBean` - the current replacement for the older `@MockBean`, checked against the Boot 4.1 testing reference docs directly), covering request validation and `ProblemDetail` error-shape contracts. -- **CI**: GitHub Actions, matching `votee`'s existing workflow pattern - unit + decorator + integration - tests against the lightweight fixture only. -- **Load tests**: k6 (§8), run manually against the fully-seeded stack, not part of the CI gate. + +Classified by naming convention, not by directory: `maven-surefire-plugin` is configured in `pom.xml` to +exclude `**/*IntegrationTest.java` and `**/ImdbApplicationTests.java` (the Testcontainers-backed Spring +Boot smoke test), so everything else under `src/test/java` runs here by default - no file relocation +needed, matching the existing `*IntegrationTest.java` suffix convention already in place before this work. + +### 10.2 Integration tests (Maven Failsafe, `mvn failsafe:integration-test failsafe:verify`) + +- **Persistence integration tests** (`infrastructure.persistence.*IntegrationTest`): Testcontainers + running a plain `postgres:17` image, exercising the `infrastructure.persistence` implementations + directly against their `domain.repository` interface contracts. Flyway runs `V0`/`V1`/`V2` from §3 + automatically on context startup (`V0` is what actually creates the base tables here - see §3.4), then + the shared `fixture-data.sql` (loaded via `@Sql` on the test class, which runs after the context - and + therefore Flyway - is already up) seeds rows covering: a known multi-hop co-star chain (to exercise the + bidirectional CTE end-to-end, including a deliberate case where the true path requires more than one hop + on each side), a tied weighted-rating case, and an ambiguous shared name. Fast and deterministic. +- **Cache integration tests** (`infrastructure.cache.Caching*IntegrationTest`, one per decorator): the + same four decorators as §10.1, but wired against a **real Redis** via Testcontainers + (`TestcontainersConfiguration`) and a real `RedisCacheManager`, not `ConcurrentMapCacheManager`. Each + test calls the decorated method twice inside a `@Transactional @Sql("/fixtures/fixture-data.sql")` + context, asserts the second call's result equals the first, and asserts the entry is actually present in + the named cache region under its documented key (§6) via `CacheManager.getCache(region).get(key)`. This + tier exists specifically because §10.1's mock-backed decorator tests cannot exercise real serialization - + a `RedisCacheManager` is the only thing in this test plan that actually round-trips a value through + `GenericJacksonJsonRedisSerializer` the way production does. Four tests, one per region: `title-search` + (`search("Few Good Men", 0, 20)`), `title-detail` (`getDetail("tt0000100")`), `top-rated` + (`findTopRated("Action", 10, 100)`), `six-degrees` (`findShortestPath(1, 2)`, keyed `"1-2"` per §6's + `min-max` convention). +- `ImdbApplicationTests` (the Spring Boot context-loads smoke test, Testcontainers-backed) also runs here, + alongside the two tiers above - it doesn't match the `*IntegrationTest.java` suffix, so it's named + explicitly in both the Surefire exclude and the Failsafe include. + +`maven-failsafe-plugin` is configured with the mirror-image `` (`**/*IntegrationTest.java`, +`**/ImdbApplicationTests.java`) and bound to the `integration-test`/`verify` goals; `spring-boot-starter- +parent` manages both plugins' versions, so no explicit `` is pinned in `pom.xml` for either. + +### 10.3 E2E / contract tests (Postman + Newman, against `docker-compose.e2e.yaml`) + +A third tier below Testcontainers: a fully-built `imdb-service` Docker image, talking to real (if +minimally-seeded) Postgres and Redis containers over the network, hit with real HTTP requests - the only +tier that exercises the actual `Dockerfile` image and the full request path end-to-end, including the +`RequestLoggingFilter`/`ApiExceptionHandler` wiring from §7/§9. + +- **Stack**: `docker-compose.e2e.yaml`, a deliberately separate file from the main `docker-compose.yaml` + (own `name: imdb-e2e` and `imdb-e2e-net` network - see the file's own header comment for the project-name + collision this guards against). `postgres` is plain `postgres:17`, not `abanda/imdb-postgresql` - the + real image's 20-30 minute import is fine for local dev, not for a stage that runs on every push. Schema + is built the same way the integration tests build it: `imdb-service`'s own Flyway migrations + (`V0`-`V4`), not a hand-copied schema dump. +- **Seed**: a one-shot `seed` service (plain `postgres:17` image as a `psql` client, `depends_on: + imdb-service: condition: service_healthy` so Flyway has already run) loads the *same* + `src/test/resources/fixtures/fixture-data.sql` the integration tests use via a read-only bind mount - + one fixture dataset, not two to keep in sync, per the design discussion that settled on this over + hand-authoring a separate e2e-only dataset. +- **Contract tests**: `imdb/postman/imdb-e2e.postman_collection.json`, a Postman Collection v2.1 with + inline `pm.test`/`pm.expect` assertions, run via `npx --yes newman run ... --env-var + baseUrl=http://localhost:8080` (no separate npm install needed - GitHub-hosted runners ship Node.js). + Nine requests covering every endpoint in §4 plus their documented edge cases: health, fuzzy search, + title detail (found and 404), top-rated (weighted-rating ordering, not raw average), six-degrees direct + / multi-hop / no-path / ambiguous-name. Verified locally: 22/22 assertions passing. +- **CI orchestration** (`imdb-ci.yml`'s `e2e` job): bring the stack up with `-p imdb-e2e` (matching the + compose file's own `name:`), poll `/actuator/health` until healthy, poll `docker inspect` on the seed + container until it exits (failing loudly with its logs if the exit code is non-zero), run Newman, dump + `docker compose logs` on failure, and always tear the stack down (`down -v`) regardless of outcome. + +### 10.4 CI summary + +| Job | Command | Depends on | +|---|---|---| +| `unit` | `mvn -B test` | - | +| `integration` | `mvn -B failsafe:integration-test failsafe:verify` | `unit` | +| `e2e` | compose up -> health/seed poll -> `newman run` -> teardown | `integration` | + +Each job fails fast for the ones after it (`needs:` in GitHub Actions), so a broken unit test never pays +for a Docker build, and a broken integration test never pays for the e2e stack's bring-up time. + +- **Load tests**: k6 (§8), run manually against the fully-seeded, production-image stack, not part of the + CI gate - a different concern (performance under load) from the correctness tiers above. ## 11. Open Items for Implementation @@ -747,7 +832,11 @@ Done, verified against a real running stack (not just written and assumed correc - **`Dockerfile`**: multi-stage build (Maven build stage -> JRE runtime stage), confirmed with a real `docker build` (549MB final image, no errors). -- **Test suite** (§10): all 50 tests (unit, decorator, integration, controller) written and passing. +- **Test suite** (§10): 32 unit tests (Surefire: use-case, decorator-unit, controller) and 22 integration + tests (Failsafe: persistence, the 4 Redis-Testcontainers cache tests, and the Spring Boot smoke test), + all passing - plus the e2e tier's 9-request/22-assertion Postman/Newman collection, verified against a + live `docker-compose.e2e.yaml` stack. All three tiers wired into `imdb-ci.yml` as sequential + `unit` -> `integration` -> `e2e` jobs. - **Grafana dashboards** under `observability/grafana/provisioning/dashboards/json/` - four dashboards (HTTP overview, six-degrees latency breakdown, cache hit ratio, k6 load-test results), confirmed by actually bringing up Grafana and checking the provisioned dashboards via its API (`/api/search`, diff --git a/imdb/pom.xml b/imdb/pom.xml index 99923ab..c42292a 100644 --- a/imdb/pom.xml +++ b/imdb/pom.xml @@ -140,6 +140,42 @@ org.springframework.boot spring-boot-maven-plugin + + + org.apache.maven.plugins + maven-surefire-plugin + + + **/*IntegrationTest.java + **/ImdbApplicationTests.java + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + **/*IntegrationTest.java + **/ImdbApplicationTests.java + + + + + + integration-test + verify + + + + diff --git a/imdb/postman/imdb-e2e.postman_collection.json b/imdb/postman/imdb-e2e.postman_collection.json new file mode 100644 index 0000000..fcdf134 --- /dev/null +++ b/imdb/postman/imdb-e2e.postman_collection.json @@ -0,0 +1,205 @@ +{ + "info": { + "name": "imdb e2e", + "_postman_id": "b6a1e6f0-6b3e-4b6a-9f0a-imdb-e2e-collection", + "description": "Contract/e2e tests against a really-running imdb-service (docker-compose.e2e.yaml), asserting on the same known fixture dataset the Testcontainers integration tests use (src/test/resources/fixtures/fixture-data.sql) - one dataset kept in sync, not two. Run with Newman: newman run imdb-e2e.postman_collection.json --env-var baseUrl=http://localhost:8080", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "variable": [ + { "key": "baseUrl", "value": "http://localhost:8080" } + ], + "item": [ + { + "name": "Health check is UP", + "request": { + "method": "GET", + "url": "{{baseUrl}}/actuator/health" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "pm.test('status is UP', () => pm.expect(pm.response.json().status).to.eql('UP'));" + ] + } + } + ] + }, + { + "name": "Search finds a title by fuzzy title match", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/titles/search?title=Few Good Men&page=0&size=20" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('finds the fixture title', () => {", + " pm.expect(body.content.map(t => t.id)).to.include('tt0000100');", + "});" + ] + } + } + ] + }, + { + "name": "Title detail returns cast, crew and rating", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/titles/tt0000100" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('primary title matches fixture', () => pm.expect(body.primaryTitle).to.eql('A Few Good Men'));", + "pm.test('directors include Rob Reiner', () => {", + " pm.expect(body.directors.map(d => d.name)).to.include('Rob Reiner');", + "});", + "pm.test('writers include Aaron Sorkin', () => {", + " pm.expect(body.writers.map(w => w.name)).to.include('Aaron Sorkin');", + "});", + "pm.test('cast includes both principals', () => {", + " const names = body.cast.map(c => c.name);", + " pm.expect(names).to.include('Kevin Bacon');", + " pm.expect(names).to.include('Tom Cruise');", + "});" + ] + } + } + ] + }, + { + "name": "Title detail 404s for an unknown id", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/titles/tt9999999" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 404', () => pm.response.to.have.status(404));" + ] + } + } + ] + }, + { + "name": "Top rated ranks by weighted rating, not raw average", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/genres/Action/top-rated?limit=10&minVotes=100" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('200 outranks 201 once vote-count shrinkage is applied', () => {", + " pm.expect(body[0].id).to.eql('tt0000200');", + " pm.expect(body[1].id).to.eql('tt0000201');", + "});" + ] + } + } + ] + }, + { + "name": "Six degrees finds a direct co-star (degree 1)", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/people/six-degrees?personA=nm0000001&personB=nm0000002" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('degree is 1', () => pm.expect(body.degree).to.eql(1));", + "pm.test('within requested max', () => pm.expect(body.withinRequestedMax).to.eql(true));" + ] + } + } + ] + }, + { + "name": "Six degrees finds a multi-hop path (degree 5)", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/people/six-degrees?personA=nm0000001&personB=nm0000006" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('degree is 5 - the full co-star chain', () => pm.expect(body.degree).to.eql(5));", + "pm.test('path has 6 people', () => pm.expect(body.path).to.have.lengthOf(6));" + ] + } + } + ] + }, + { + "name": "Six degrees reports no path for the isolated actor", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/people/six-degrees?personA=nm0000001&personB=nm0000007" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('no path found', () => {", + " pm.expect(body.degree).to.be.null;", + " pm.expect(body.withinRequestedMax).to.eql(false);", + "});" + ] + } + } + ] + }, + { + "name": "Six degrees requires disambiguation for an ambiguous name", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/people/six-degrees?personA=Jamie Lee&personB=nm0000001" + }, + "event": [ + { + "listen": "test", + "script": { + "exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "const body = pm.response.json();", + "pm.test('requires disambiguation between the two fixture Jamie Lees', () => {", + " pm.expect(body.requiresDisambiguation).to.eql(true);", + " pm.expect(body.candidates).to.have.lengthOf(2);", + "});" + ] + } + } + ] + } + ] +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryIntegrationTest.java new file mode 100644 index 0000000..03925b6 --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingCoStarGraphRepositoryIntegrationTest.java @@ -0,0 +1,46 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.domain.repository.CoStarGraphRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +// See CachingTitleSearchUseCaseIntegrationTest for why this exists alongside the unit-level +// CachingCoStarGraphRepositoryTest - this exercises the real Redis serialization round trip that a +// ConcurrentMapCacheManager-backed unit test structurally cannot. +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class CachingCoStarGraphRepositoryIntegrationTest { + + @Autowired + CoStarGraphRepository coStarGraphRepository; + + @Autowired + CacheManager cacheManager; + + @BeforeEach + void clearCache() { + cacheManager.getCache("six-degrees").clear(); + } + + @Test + void secondCallIsServedFromRealRedisAndDeserializesToAnEqualResult() { + var first = coStarGraphRepository.findShortestPath(1, 2).orElseThrow(); + assertThat(first.degree()).isEqualTo(1); + assertThat(cacheManager.getCache("six-degrees").get("1-2")).isNotNull(); + + var second = coStarGraphRepository.findShortestPath(1, 2).orElseThrow(); + + assertThat(second).isEqualTo(first); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseIntegrationTest.java new file mode 100644 index 0000000..4c6a2df --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleDetailUseCaseIntegrationTest.java @@ -0,0 +1,46 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +// See CachingTitleSearchUseCaseIntegrationTest for why this exists alongside the unit-level +// CachingTitleDetailUseCaseTest - this exercises the real Redis serialization round trip that a +// ConcurrentMapCacheManager-backed unit test structurally cannot. +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class CachingTitleDetailUseCaseIntegrationTest { + + @Autowired + TitleDetailUseCase titleDetailUseCase; + + @Autowired + CacheManager cacheManager; + + @BeforeEach + void clearCache() { + cacheManager.getCache("title-detail").clear(); + } + + @Test + void secondCallIsServedFromRealRedisAndDeserializesToAnEqualResult() { + var first = titleDetailUseCase.getDetail("tt0000100"); + assertThat(first.primaryTitle()).isEqualTo("A Few Good Men"); + assertThat(cacheManager.getCache("title-detail").get("tt0000100")).isNotNull(); + + var second = titleDetailUseCase.getDetail("tt0000100"); + + assertThat(second).isEqualTo(first); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseIntegrationTest.java new file mode 100644 index 0000000..7c7cfee --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleSearchUseCaseIntegrationTest.java @@ -0,0 +1,51 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +// Complements the unit-level CachingTitleSearchUseCaseTest (ConcurrentMapCacheManager, mocked +// delegate) - that one proves the @Cacheable wiring is correct, but an in-memory map never +// serializes anything, so it structurally cannot catch a bug in the real CacheConfig/ +// RedisCacheManager path. This runs the real stack end to end (real repository, real Postgres +// fixture data, real Redis via Testcontainers) so the second call is a genuine deserialize-from- +// Redis read, not a Java reference handed back from a map - exactly the class of bug that surfaced +// live earlier (GenericJacksonJsonRedisSerializer missing type metadata -> ClassCastException on a +// cache hit) and that the unit test alone could never have caught. +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class CachingTitleSearchUseCaseIntegrationTest { + + @Autowired + TitleSearchUseCase titleSearchUseCase; + + @Autowired + CacheManager cacheManager; + + @BeforeEach + void clearCache() { + cacheManager.getCache("title-search").clear(); + } + + @Test + void secondCallIsServedFromRealRedisAndDeserializesToAnEqualResult() { + var first = titleSearchUseCase.search("Few Good Men", 0, 20); + assertThat(first.content()).extracting("id").contains("tt0000100"); + assertThat(cacheManager.getCache("title-search").get("Few Good Men:0:20")).isNotNull(); + + var second = titleSearchUseCase.search("Few Good Men", 0, 20); + + assertThat(second).isEqualTo(first); + } +} diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseIntegrationTest.java new file mode 100644 index 0000000..e531b0f --- /dev/null +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTopRatedUseCaseIntegrationTest.java @@ -0,0 +1,46 @@ +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +// See CachingTitleSearchUseCaseIntegrationTest for why this exists alongside the unit-level +// CachingTopRatedUseCaseTest - this exercises the real Redis serialization round trip that a +// ConcurrentMapCacheManager-backed unit test structurally cannot. +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class CachingTopRatedUseCaseIntegrationTest { + + @Autowired + TopRatedUseCase topRatedUseCase; + + @Autowired + CacheManager cacheManager; + + @BeforeEach + void clearCache() { + cacheManager.getCache("top-rated").clear(); + } + + @Test + void secondCallIsServedFromRealRedisAndDeserializesToAnEqualResult() { + var first = topRatedUseCase.findTopRated("Action", 10, 100); + assertThat(first).extracting("id").startsWith("tt0000200", "tt0000201"); + assertThat(cacheManager.getCache("top-rated").get("Action:10:100")).isNotNull(); + + var second = topRatedUseCase.findTopRated("Action", 10, 100); + + assertThat(second).isEqualTo(first); + } +} From 94a7347e651af04cfb5fc6f9d9fc69d783dfbdf5 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sat, 11 Jul 2026 18:52:21 +0200 Subject: [PATCH 17/42] Fixed grafana dashboards --- imdb/docker-compose.yaml | 16 +++- imdb/docs/low-level-design.md | 87 ++++++++++++++++--- .../dashboards/json/cache-hit-ratio.json | 2 +- .../dashboards/json/k6-load-test.json | 10 ++- .../infrastructure/cache/CacheConfig.java | 46 +++++++++- imdb/src/main/resources/application.yaml | 4 + 6 files changed, 146 insertions(+), 19 deletions(-) diff --git a/imdb/docker-compose.yaml b/imdb/docker-compose.yaml index 95f47a5..bd38af6 100644 --- a/imdb/docker-compose.yaml +++ b/imdb/docker-compose.yaml @@ -101,7 +101,11 @@ services: command: - --config.file=/etc/prometheus/prometheus.yml - --storage.tsdb.path=/prometheus - - --enable-feature=remote-write-receiver # accepts k6's experimental-prometheus-rw output + # NOT --enable-feature=remote-write-receiver - that's not a real --enable-feature value on this + # Prometheus version (3.11.3 as pulled here); confirmed via a live "Unknown option for + # --enable-feature" warning in the container's own logs, and the write endpoint 404ing until + # this was corrected. Remote write receiving has its own dedicated flag instead. + - --web.enable-remote-write-receiver # accepts k6's experimental-prometheus-rw output ports: - "9090:9090" volumes: @@ -216,6 +220,16 @@ services: profiles: ["load-test"] environment: K6_PROMETHEUS_RW_SERVER_URL: http://prometheus:9090/api/v1/write + # K6_PROMETHEUS_RW_SERVER_URL alone does not activate the output - confirmed empirically (a run + # without this completed with no errors and pushed nothing at all). K6_OUT is the env-var form + # of `k6 run --out experimental-prometheus-rw`, so the documented `docker compose --profile + # load-test run k6 run /scripts/.js` (LLD §8) works without needing that flag typed by hand. + K6_OUT: experimental-prometheus-rw + # Default trend-stat export is p99 only - the k6 dashboard's "p95 request duration" panel + # (LLD §7/§8) needs p95 specifically; confirmed empirically that only k6_..._p99 series existed + # under the default. Each Trend metric (http_req_duration, http_req_waiting, etc.) gets both + # suffixes once this is set. + K6_PROMETHEUS_RW_TREND_STATS: "p(95),p(99)" volumes: - ./k6:/scripts:ro networks: diff --git a/imdb/docs/low-level-design.md b/imdb/docs/low-level-design.md index 421f8af..a803cc4 100644 --- a/imdb/docs/low-level-design.md +++ b/imdb/docs/low-level-design.md @@ -610,10 +610,14 @@ instead of just measuring a warm Redis round-trip after the first request - see ## 7. Observability Wiring -- **Metrics**: `micrometer-registry-prometheus`, default HTTP/JVM metrics plus custom ones: a `Timer` per - endpoint's DB-query phase (so the six-degrees CTE's latency is visible as its own series, separate from - total request latency), and `Counter`s for cache hit/miss per cache region. Both are instrumentation - concerns and belong in `infrastructure` (the repository/decorator classes), not `application`. +- **Metrics**: `micrometer-registry-prometheus`. Default HTTP (`http.server.requests`, percentile-histogram + enabled - §7.1) and JVM/process metrics come from Boot's own auto-configuration; there is no separate + custom `Timer` for the six-degrees CTE's DB-query phase specifically - `uri`-filtering the standard + `http_server_requests_seconds` histogram (six-degrees latency dashboard, §7.1) already isolates it from + the other three endpoints without needing one, since this API has exactly one repository call per + request on the hot path anyway. Cache hit/miss/put `Counter`s per region are manually bound + (`infrastructure.cache.CacheConfig.cacheStatisticsMeterBinder`, §7.1) - Boot 4.1 removed the + auto-binding this design originally assumed. - **Tracing**: the `spring-boot-starter-opentelemetry` starter (Boot 4.1's unified tracing starter - supersedes the Boot 3-era `micrometer-tracing-bridge-otel` + `opentelemetry-exporter-otlp` combo) exports to Tempo via `management.opentelemetry.tracing.export.otlp.endpoint=http://tempo:4318/v1/traces` @@ -664,6 +668,68 @@ instead of just measuring a warm Redis round-trip after the first request - see breakdown, cache hit ratio, k6 load-test results) are authored during implementation, not shipped as part of this design (see §11). +### 7.1 Making the dashboards actually work: four real bugs, found by querying Prometheus directly + +All four dashboards were authored against assumed metric shapes and shipped without a live scrape ever +confirming them (§11's own caveat on the cache dashboard: "not confirmed against a live scrape at +authoring time"). Once actually queried against a running stack, every dashboard except three panels of +HTTP Overview turned out to be empty - not from a dashboard-JSON bug in most cases, but because the +metrics themselves didn't exist yet. Fixed in order of discovery: + +1. **No `_bucket` series at all, anywhere** - every `histogram_quantile(...)` panel (HTTP Overview's p95, + all three Six Degrees Latency panels) was empty because Micrometer only emits a Timer's `_count`/`_sum`/ + `_max`, never `_bucket`, unless percentile histograms are explicitly turned on. `application.yaml` never + set this. Fix: `management.metrics.distribution.percentiles-histogram.http.server.requests: true`. + Verified: `http_server_requests_seconds_bucket` appears in `/actuator/prometheus` immediately after + restart, and `histogram_quantile(0.95, ...)` returns real numbers once the target `uri` has recent + traffic in the query window (a `uri` with none still returns `NaN` - expected Prometheus behavior for + an all-zero-rate histogram, not a bug). +2. **`cache_gets_total`/`cache_puts_total` never existed at all** - not a naming or label mismatch, the + metrics were simply never registered. Root cause, confirmed by decompiling the actual jars rather than + trusting memory of older Boot versions: `spring-boot-actuator-autoconfigure-4.1.0.jar` contains no + `cache` package whatsoever - the `CacheMetricsRegistrar`/`CacheMeterBinderProvider` auto-binding this + design assumed (a real feature in Boot 2/3) does not exist in Boot 4.1. Fix, replicated manually in + `CacheConfig` rather than reintroducing Boot's removed mechanism: build the `RedisCacheManager`'s + `RedisCacheWriter` explicitly with `.collectStatistics()` (Spring Data Redis's own, independent + `CacheStatisticsCollector` - unaffected by the Boot-side removal), and register a `MeterBinder` bean + that exposes each region's `getHits()`/`getMisses()`/`getPuts()` as `FunctionCounter`s named + `cache.gets`/`cache.puts`, tagged `cache`/`result` to match the dashboard's existing (correctly + anticipated) query shape exactly. `initialCacheNames(...)` on the manager builder (added alongside this + fix) makes all four regions exist from startup rather than being created lazily on first use. + Verified: exercising each cached endpoint exactly twice produces precisely 1 miss + 1 hit + 1 put per + region in `/actuator/prometheus`. +3. **Prometheus's own remote-write receiver was never actually on** - `docker-compose.yaml` passed + `--enable-feature=remote-write-receiver`, which was never a valid `--enable-feature` value; Prometheus + 3.11.3's own startup log said so outright ("Unknown option for --enable-feature"), and the write + endpoint 404'd accordingly. The correct, and long-standing, flag is the dedicated + `--web.enable-remote-write-receiver` (confirmed against `prometheus --help` directly). This is why the + k6 dashboard had zero data even before its query-shape bugs (below) mattered at all. +4. **k6's `experimental-prometheus-rw` output doesn't emit what the dashboard assumed**, on two counts, + both confirmed by actually running `k6 run --out experimental-prometheus-rw` against the live stack and + inspecting exactly what landed in Prometheus: + - `K6_PROMETHEUS_RW_SERVER_URL` alone does not activate the output - a run with only that env var set + completed with no errors and pushed nothing. `K6_OUT: experimental-prometheus-rw` (the env-var + equivalent of `k6 run --out experimental-prometheus-rw`) is now set directly on the `k6` service in + `docker-compose.yaml`, so the plain documented invocation (`docker compose --profile load-test run k6 + run /scripts/.js`, §8) works without anyone needing to type that flag by hand. + - There is no `k6_http_req_duration_seconds_bucket` or `k6_http_req_failed_total` - k6's trend metrics + (`http_req_duration`, etc.) are exported as pre-computed percentile *gauges* per request URL + (`k6_http_req_duration_p99{name=...}` by default - `p99` only, until + `K6_PROMETHEUS_RW_TREND_STATS: "p(95),p(99)"` is set to also get `_p95`; the bare form `"p95"` is + rejected at k6 startup with "invalid trend stat", confirmed empirically - it has to be k6's own + `p(95)` threshold syntax), and `http_req_failed` - a k6 "rate" metric (a 0..1 boolean average, not a + counter) - only ever exists as `k6_http_req_failed_rate`, never a `_total` counter. Fixed + `k6-load-test.json`'s two affected panels to query `avg(k6_http_req_duration_p95)` and + `avg(k6_http_req_failed_rate)` respectively (averaged across the per-URL series, since `search.js` + deliberately spreads requests across many distinct query terms - §8), with the failed-rate panel's + unit corrected from `reqps` to `percentunit` to match. + +All four dashboards were re-verified after these fixes: queried every panel's exact PromQL expression +directly against Prometheus (both directly and through Grafana's own datasource-proxy API, to rule out a +Grafana-side provisioning-cache issue) with real traffic generated live (`curl` loops for the HTTP/cache +panels, an actual short `k6 run` for the k6 panels), and confirmed real, non-`NaN`, non-empty values back +for every one of them. + ## 8. k6 Load Testing Plan One script per endpoint under `imdb/k6/`, run one at a time (never concurrently) so each run's metrics @@ -840,11 +906,12 @@ Done, verified against a real running stack (not just written and assumed correc - **Grafana dashboards** under `observability/grafana/provisioning/dashboards/json/` - four dashboards (HTTP overview, six-degrees latency breakdown, cache hit ratio, k6 load-test results), confirmed by actually bringing up Grafana and checking the provisioned dashboards via its API (`/api/search`, - `/api/dashboards/uid/...`) rather than trusting hand-written JSON to be schema-correct. The cache - hit-ratio dashboard's `cache_gets_total`/`cache_puts_total` metric names come from Spring Boot's - documented auto-binding of cache metrics for `RedisCacheManager` - flagged in the dashboard's own - description to double check against a real scrape once the app has served traffic, since this wasn't - directly observed (see the next item for why). + `/api/dashboards/uid/...`), and - going further than schema-correctness - by generating real traffic + and confirming every panel's exact PromQL expression returns real, non-empty data through Prometheus + and through Grafana's own datasource-proxy API. Four real bugs surfaced by that verification and were + fixed (missing percentile-histogram config, Boot 4.1 having quietly dropped automatic cache-metrics + binding entirely, a Prometheus flag that was never valid, and wrong assumptions about k6's remote-write + metric shapes) - full writeup in §7.1. - **k6 scripts and `data/sampled-people.csv`** under `imdb/k6/` - `title-detail.js` and `six-degrees.js` discover real ids/people from the live API at `setup()` time rather than shipping a dataset-snapshot-specific list of hardcoded ids (a first attempt at hardcoding a few "well-known" real @@ -874,8 +941,6 @@ choice to run, not something to trigger incidentally: to arbitrarily drop neighbors to bound the search). - Decide the `co_star_edges` refresh cadence (PDD §11 open question) if this ever moves beyond a single-import deployment. -- Confirm the `cache_gets_total`/`cache_puts_total` metric names above against a real scrape once the app - has actually served cached traffic. - The onion layering in §2 is enforced today only by convention (import direction) and code review, not by a build-tool boundary. If this project grows past its current size, splitting `domain`/`application`/ `infrastructure`/`presentation` into separate Maven modules would make the dependency rule diff --git a/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json b/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json index e38a41b..d6a6a4b 100644 --- a/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json +++ b/imdb/observability/grafana/provisioning/dashboards/json/cache-hit-ratio.json @@ -6,7 +6,7 @@ "schemaVersion": 39, "refresh": "10s", "time": { "from": "now-15m", "to": "now" }, - "description": "Uses Spring Boot's auto-bound cache.gets/cache.puts metrics for RedisCacheManager (no custom instrumentation - LLD §7). Verify the cache_gets_total{result=...} label values once the app has actually served traffic; this was not confirmed against a live scrape at authoring time.", + "description": "cache.gets/cache.puts are manually bound (CacheConfig.cacheStatisticsMeterBinder, LLD §6/§7), not Spring Boot auto-binding - decompiling spring-boot-actuator-autoconfigure-4.1.0.jar showed the cache-metrics package Boot 2/3 used to ship (CacheMetricsRegistrar et al.) no longer exists in Boot 4.1 at all. The replacement reads Spring Data Redis's own RedisCacheWriter statistics collector directly. Verified live: exercising each cached endpoint twice produces the expected 1 miss + 1 hit + 1 put per region.", "panels": [ { "id": 1, diff --git a/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json b/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json index 8d832b1..fb0f43d 100644 --- a/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json +++ b/imdb/observability/grafana/provisioning/dashboards/json/k6-load-test.json @@ -43,13 +43,14 @@ "id": 3, "title": "p95 request duration", "type": "timeseries", + "description": "k6's experimental-prometheus-rw output pre-computes trend percentiles client-side and exports them as plain gauges per request URL (k6_http_req_duration_p95{name=...}, no _bucket series at all) - averaged across URLs here rather than histogram_quantile'd, since there's no histogram to quantile. K6_PROMETHEUS_RW_TREND_STATS=\"p(95),p(99)\" (docker-compose.yaml) is what makes the p95 series exist; the default is p99 only. Note the k6() call syntax - a bare \"p95\" is rejected at k6 startup with \"invalid trend stat\", confirmed empirically.", "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "targets": [ { "refId": "A", "datasource": { "type": "prometheus", "uid": "prometheus" }, - "expr": "histogram_quantile(0.95, sum by (le) (rate(k6_http_req_duration_seconds_bucket[$__rate_interval])))", + "expr": "avg(k6_http_req_duration_p95)", "legendFormat": "p95" } ], @@ -59,17 +60,18 @@ "id": 4, "title": "Failed request rate", "type": "timeseries", + "description": "k6's http_req_failed is itself a \"rate\" metric (a 0..1 boolean average, not a counter) - k6_http_req_failed_total never exists, only k6_http_req_failed_rate.", "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, "datasource": { "type": "prometheus", "uid": "prometheus" }, "targets": [ { "refId": "A", "datasource": { "type": "prometheus", "uid": "prometheus" }, - "expr": "sum(rate(k6_http_req_failed_total[$__rate_interval]))", - "legendFormat": "failures/s" + "expr": "avg(k6_http_req_failed_rate)", + "legendFormat": "failure rate" } ], - "fieldConfig": { "defaults": { "unit": "reqps" }, "overrides": [] } + "fieldConfig": { "defaults": { "unit": "percentunit", "min": 0, "max": 1 }, "overrides": [] } } ] } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java index 19653b6..44e30d2 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java @@ -1,10 +1,13 @@ package com.ludovictemgoua.imdb.infrastructure.cache; +import io.micrometer.core.instrument.FunctionCounter; +import io.micrometer.core.instrument.binder.MeterBinder; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.cache.RedisCacheWriter; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.serializer.GenericJacksonJsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; @@ -12,13 +15,51 @@ import tools.jackson.databind.jsontype.PolymorphicTypeValidator; import java.time.Duration; +import java.util.Set; @Configuration @EnableCaching public class CacheConfig { + // The four @Cacheable cacheNames (LLD §6). Passed to initialCacheNames below so each region + // exists in the manager from startup rather than being created lazily on its first @Cacheable + // call - required for cacheStatisticsMeterBinder below to have something to read immediately, + // and (independently) for RedisCacheManager.getCacheNames() to ever report these regions at all. + private static final Set CACHE_NAMES = + Set.of("title-search", "title-detail", "top-rated", "six-degrees"); + + @Bean + public RedisCacheWriter redisCacheWriter(RedisConnectionFactory connectionFactory) { + // .collectStatistics() turns on Spring Data Redis's own CacheStatisticsCollector (gets/hits/ + // misses/puts per cache name) - the same native source Spring Boot's now-removed + // CacheMetricsRegistrar/RedisCacheMeterBinderProvider used to read automatically pre-Boot-4.1 + // (confirmed absent by decompiling spring-boot-actuator-autoconfigure-4.1.0.jar: no "cache" + // package exists in it at all anymore). cacheStatisticsMeterBinder below is the manual + // replacement for that removed auto-binding, reading from this same writer. + return RedisCacheWriter.create(connectionFactory, + RedisCacheWriter.RedisCacheWriterConfigurer::collectStatistics); + } + + @Bean + public MeterBinder cacheStatisticsMeterBinder(RedisCacheWriter redisCacheWriter) { + return registry -> CACHE_NAMES.forEach(name -> { + FunctionCounter.builder("cache.gets", redisCacheWriter, + writer -> writer.getCacheStatistics(name).getHits()) + .tag("cache", name).tag("result", "hit") + .register(registry); + FunctionCounter.builder("cache.gets", redisCacheWriter, + writer -> writer.getCacheStatistics(name).getMisses()) + .tag("cache", name).tag("result", "miss") + .register(registry); + FunctionCounter.builder("cache.puts", redisCacheWriter, + writer -> writer.getCacheStatistics(name).getPuts()) + .tag("cache", name) + .register(registry); + }); + } + @Bean - public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) { + public RedisCacheManager cacheManager(RedisCacheWriter redisCacheWriter) { // GenericJacksonJsonRedisSerializer, not GenericJackson2JsonRedisSerializer: Boot 4.1's default // Jackson is Jackson 3 (tools.jackson.databind.*, a different Maven groupId/package than the // Jackson 2.x com.fasterxml.jackson.databind.* the "2"-suffixed serializer needs - the latter @@ -47,8 +88,9 @@ public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) .enableDefaultTyping(typeValidator) .build())); - return RedisCacheManager.builder(connectionFactory) + return RedisCacheManager.builder(redisCacheWriter) .cacheDefaults(defaults) + .initialCacheNames(CACHE_NAMES) .build(); } } diff --git a/imdb/src/main/resources/application.yaml b/imdb/src/main/resources/application.yaml index 56c480f..d85d49e 100644 --- a/imdb/src/main/resources/application.yaml +++ b/imdb/src/main/resources/application.yaml @@ -57,6 +57,10 @@ management: metrics: export: enabled: false + metrics: + distribution: + percentiles-histogram: + http.server.requests: true six-degrees: side-cap: 4 From 96f1173e9fc4157084f2524681610e72ba1f1bca Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Sat, 11 Jul 2026 20:00:52 +0200 Subject: [PATCH 18/42] Added readme to imdb project --- imdb/LICENSE | 201 ++++++++++++++++++++++++++++++++++++ imdb/README.md | 269 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+) create mode 100644 imdb/LICENSE create mode 100644 imdb/README.md diff --git a/imdb/LICENSE b/imdb/LICENSE new file mode 100644 index 0000000..ed2aee4 --- /dev/null +++ b/imdb/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2026] [Ludovic Temgou Abanda N.] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/imdb/README.md b/imdb/README.md new file mode 100644 index 0000000..f4f406b --- /dev/null +++ b/imdb/README.md @@ -0,0 +1,269 @@ +# imdb + +A production-shaped Spring Boot REST API over the full [IMDb Non-Commercial Dataset](https://www.imdb.com/interfaces/): title search with cast/crew, top-rated movies by genre, and a generalized "Six Degrees of Kevin Bacon" graph query. Part of a deliberate, professional-grade return to the Java ecosystem (see the [root README](../README.md)): real indexing decisions, a literature-grounded algorithm choice for the graph problem, full observability, and a three-tier test pipeline, not a toy CRUD example. + +[![imdb CI](https://github.com/icemc/java-backend-playground/actions/workflows/imdb-ci.yml/badge.svg)](https://github.com/icemc/java-backend-playground/actions/workflows/imdb-ci.yml) +![Java](https://img.shields.io/badge/Java-21-orange) +![Spring Boot](https://img.shields.io/badge/Spring%20Boot-4.1-brightgreen) +![Build](https://img.shields.io/badge/build-Maven-blue) +![License](https://img.shields.io/badge/license-Apache--2.0-green) + +## Table of contents + +- [What this is](#what-this-is) +- [Functional requirements](#functional-requirements) +- [Architecture](#architecture) + - [Onion layering](#onion-layering) + - [Package layout](#package-layout) + - [Key design decisions](#key-design-decisions) + - [Six Degrees of Kevin Bacon](#six-degrees-of-kevin-bacon) + - [Caching strategy](#caching-strategy) +- [API](#api) +- [Observability](#observability) +- [External services](#external-services) +- [Testing strategy](#testing-strategy) +- [DevOps](#devops) +- [Load testing](#load-testing) +- [Running it locally](#running-it-locally) +- [Project layout](#project-layout) +- [Design documents](#design-documents) +- [Known limitations](#known-limitations) +- [License](#license) + +## What this is + +Given the real, untruncated IMDb dataset (millions of titles and people, tens of millions of cast/crew credits), `imdb` exposes four read-only REST endpoints, backed by: + +- Hand-tuned native SQL (trigram fuzzy search, GIN array containment, a Bayesian weighted rating, a custom bidirectional-BFS PL/pgSQL function) instead of an ORM (see [Why plain JDBC](#key-design-decisions)). +- Redis cache-aside in front of every endpoint, since the dataset only changes on a one-time image reload. +- Full observability: structured JSON logs, Prometheus metrics, and OpenTelemetry traces, correlated in one Grafana instance. +- A three-tier test pipeline (unit → Testcontainers integration → Postman/Newman e2e) wired into CI. +- k6 load testing per endpoint, with results pushed into the same observability stack. + +## Functional requirements + +| # | Requirement | Endpoint | +|---|---|---| +| 1 | Search a movie by title; show related cast/crew | `GET /api/v1/titles/search`, `GET /api/v1/titles/{titleId}` | +| 2 | Top-rated movies in a given genre | `GET /api/v1/genres/{genre}/top-rated` | +| 3 | Degree of separation between any two people ("Six Degrees", generalized beyond a fixed Kevin Bacon root) | `GET /api/v1/people/six-degrees` | + +Full requirements and guidelines: [`docs/REQUIREMENTS.md`](docs/REQUIREMENTS.md). + +## Architecture + +### Onion layering + +`presentation → infrastructure → application → domain`, plus a dependency-free `utils` layer. Import direction alone enforces the dependency rule: `application` never imports `infrastructure`, and `domain` imports nothing. + +| Layer | Contains | +|---|---| +| `presentation` | Controllers, `ApiExceptionHandler`, `RequestLoggingFilter` | +| `infrastructure` | JDBC repository implementations, Redis caching decorators, `@Configuration` | +| `application` | Use-case interfaces + implementations | +| `domain` | Entities/value objects, repository **interfaces**, domain exceptions | +| `utils` | `ImdbIds`, `HeaderSanitizer`: pure, framework-free helpers | + +Every top-level use case a controller depends on is an interface (`TitleSearchUseCase`, `TitleDetailUseCase`, `TopRatedUseCase`, `SixDegreesUseCase`), with a plain `*Impl` and, where caching applies, an `infrastructure.cache` decorator marked `@Primary`: + +``` +application.contracts.TitleSearchUseCase (interface) + ├─ application.TitleSearchUseCaseImpl - plain orchestration, no caching + └─ infrastructure.cache.CachingTitleSearchUseCase - @Primary, @Cacheable, delegates to the Impl above +``` + +A controller depends on the interface and never learns which implementation it got. Swapping cache technology, or Postgres for another store, touches exactly one layer. + +### Package layout + +``` +imdb/ + src/main/java/com/ludovictemgoua/imdb/ + domain/ entities, repository interfaces, domain exceptions + application/ use-case interfaces (contracts/) + plain implementations + infrastructure/ + persistence/ JDBC repository implementations + cache/ Redis caching decorators, CacheConfig + presentation/ controllers, ApiExceptionHandler, RequestLoggingFilter + utils/ ImdbIds, HeaderSanitizer - dependency-free + src/main/resources/ + application.yaml + db/migration/ Flyway V0-V4 (base schema, indexes, materialized view, BFS function) + src/test/ unit + Testcontainers integration tests, shared fixtures + k6/ one load-test script per endpoint + postman/ e2e contract test collection + observability/ Prometheus/Loki/Tempo/Alloy/Grafana provisioning + docs/ REQUIREMENTS.md, product-design.md, low-level-design.md +``` + +### Key design decisions + +| Decision | Chosen approach | Why | +|---|---|---| +| Data access | Plain `NamedParameterJdbcTemplate`, no JPA/Hibernate | Every query is a hand-tuned native query (trigram search, array containment, a graph BFS function); no object graph is being mutated, only read projections. | +| Six Degrees algorithm | Bidirectional BFS as a PL/pgSQL function, meeting in the middle | A one-sided walk pays the graph's full branching factor per hop against hub actors with thousands of co-stars; meeting in the middle roughly squares down the search space, and the 7-degree cap means each side only expands ~4 hops. See [below](#six-degrees-of-kevin-bacon). | +| Result caching | Redis cache-aside, keyed by the **unordered** person pair, storing the true shortest distance up to the absolute 7-degree cap | A distance is a fact independent of the caller's requested `maxDegree`: one cache entry serves every request for that pair regardless of their bound. | +| Top-rated ranking | IMDb-style weighted (Bayesian) rating, not raw average | A raw average lets a movie with 3 votes at 10/10 outrank one with 500,000 votes at 8.9. | +| Title search | PostgreSQL `pg_trgm` similarity search, GIN-indexed | Tolerates typos/partial matches while staying index-backed against a multi-million-row table. | +| API ID format | Public API uses IMDb-style `tt`/`nm` string IDs, translated at the repository boundary (`utils.ImdbIds`) | The internal integer PK is an artifact of the seed image's import script, not a stable public contract. | +| Build tool | Maven | Consistent with [`votee`](../votee) elsewhere in this monorepo. | + +Full rationale, including alternatives considered (precomputed BFS, Pruned Landmark Labeling, Neo4j) and why they were rejected: [`docs/product-design.md`](docs/product-design.md) §9. + +### Six Degrees of Kevin Bacon + +The first working version was a single bidirectional recursive CTE. It passed review and its own tests, then failed under real data two distinct ways: a fixed fan-out cap could silently drop the true connecting co-star (a *wrong-answer* bug, not just slow), and cycle prevention only checked a single path's own history, so the same hub node got independently re-expanded by every path that reached it (a real hub-to-hub query took 3+ minutes and spilled to disk). + +The fix moved the traversal into a PL/pgSQL function (`find_shortest_co_star_path`, `V3__shortest_co_star_path_function.sql`) with genuine iterative state: two `TEMP TABLE`s hold a real, de-duplicated visited set and parent pointer per side, expanding whichever frontier is currently smaller, with no arbitrary neighbor cap. Verified against the exact pathological pair that broke the old query (two ~8,000-co-star hub nodes, no direct edge): **29-44ms and a correct degree-2 result, versus 3+ minutes and a disk spill before.** + +Full derivation, including the two specific bugs found and fixed: [`docs/low-level-design.md`](docs/low-level-design.md) §5. + +### Caching strategy + +| Cache region | Key | TTL | Cached at | +|---|---|---|---| +| `title-search` | `query, page, size` | 24h | Use-case decorator | +| `title-detail` | `titleId` | 24h | Use-case decorator (one entry for the fully-assembled detail, even though it fans out to five repository calls) | +| `top-rated` | `genre, limit, minVotes` | 24h | Use-case decorator | +| `six-degrees` | `min(personA,personB)-max(personA,personB)` | 24h | Repository decorator, cached one layer deeper than the other three, since the use case's raw inputs (names needing disambiguation, a variable `maxDegree`) make a poor cache key, while the repository's `findShortestPath(int, int)` doesn't | + +All TTLs are long because the dataset only changes on image reload; there is no write path invalidating entries mid-flight. + +## API + +| Method | Path | Description | +|---|---|---| +| GET | `/api/v1/titles/search?title=&page=&size=` | Fuzzy trigram search, paginated | +| GET | `/api/v1/titles/{titleId}` | Full detail: metadata, rating, directors/writers, top-billed cast | +| GET | `/api/v1/genres/{genre}/top-rated?limit=&minVotes=` | Top-rated movies by weighted rating | +| GET | `/api/v1/people/six-degrees?personA=&personB=&maxDegree=` | Degree of separation; returns a disambiguation payload (HTTP 200) instead of an error when a `name` matches more than one person | + +All errors are RFC 7807 `ProblemDetail` (404 for unknown IDs, 400 for malformed IDs/out-of-range `maxDegree`/missing params, 405 for the wrong HTTP method). Full contracts, request/response shapes, and error handling: [`docs/low-level-design.md`](docs/low-level-design.md) §4/§9. + +## Observability + +- **Metrics**: `micrometer-registry-prometheus`. Default HTTP (`http.server.requests`, with percentile-histogram buckets enabled) and JVM/process metrics via Boot's auto-configuration. Cache hit/miss/put counters per region are **manually** bound (`infrastructure.cache.CacheConfig`) via Spring Data Redis's own `RedisCacheWriter` statistics. Spring Boot 4.1 dropped its Boot-2/3-era automatic cache-metrics binding entirely (confirmed by decompiling the actual jar), so this design replicates it rather than relying on a feature that no longer exists. +- **Logging**: structured JSON via Spring Boot 4.1's native structured logging (`logging.structured.format.console: logstash`, no extra dependency). A `RequestLoggingFilter` assigns/honors a per-request `X-Request-Id`, independent of trace sampling, alongside Micrometer's `traceId`/`spanId`; both land in every log line's MDC automatically. `utils.HeaderSanitizer` redacts sensitive headers (`Authorization`, `Cookie`, `Set-Cookie`, `X-Api-Key`) before anything is logged. Shipped to Loki via Grafana Alloy. +- **Tracing**: `spring-boot-starter-opentelemetry` (Boot 4.1's unified tracing starter) exports to Tempo via OTLP, 100% sampled for this exercise. +- **Correlation**: Grafana's datasources are provisioned with Loki ⇄ Tempo ⇄ Prometheus derived-field wiring, so a trace opened in Grafana click-throughs to its log lines and vice versa. +- **Dashboards**: four Grafana dashboards, provisioned from `observability/grafana/provisioning/dashboards/json/`, verified against live traffic (every panel's PromQL checked against a real scrape, not just schema-checked): + + | Dashboard | Covers | + |---|---| + | HTTP Overview | Request rate by endpoint, p95 latency by endpoint, 5xx error rate, JVM heap used | + | Six Degrees Latency Breakdown | p50/p95/p99 latency for the six-degrees endpoint specifically, versus the other three endpoints, and its request rate; this is the one endpoint whose cost depends on graph shape, not a bounded index lookup | + | Cache Hit Ratio | Hit ratio by region, gets by region/result, puts by region | + | k6 Load Test Results | Virtual users, request rate, p95 request duration, failed request rate, fed by a k6 run's own Prometheus remote-write output | + + + +Full wiring details, including four real bugs found and fixed while verifying the dashboards against live data (missing percentile-histogram config, Boot 4.1's removed cache-metrics auto-binding, an invalid Prometheus flag, and wrong assumptions about k6's remote-write metric shapes): [`docs/low-level-design.md`](docs/low-level-design.md) §7/§7.1. + +## External services + +Brought up by `docker-compose.yaml` alongside the application itself: + +| Service | Image | Port(s) | Role | +|---|---|---|---| +| PostgreSQL | [`abanda/imdb-postgresql`](https://github.com/icemc/imdb-postgresql) | 5432 | The seeded IMDb dataset (full, untruncated) | +| Redis | `redis:7-alpine` | 6379 | Cache-aside store for all four endpoints | +| Prometheus | `prom/prometheus` | 9090 | Metrics scrape + k6 remote-write receiver | +| Grafana | `grafana/grafana` | 3001 (host) → 3000 | Dashboards, correlated logs/metrics/traces (anonymous admin access, local-only) | +| Loki | `grafana/loki` | 3100 | Log aggregation | +| Grafana Alloy | `grafana/alloy` | 12345 | Ships container logs to Loki | +| Tempo | `grafana/tempo` | 3200, 4317, 4318 | Distributed trace storage/query, OTLP receiver | +| postgres-exporter | `quay.io/prometheuscommunity/postgres-exporter` | 9187 | Postgres metrics for Prometheus | +| redis-exporter | `oliver006/redis_exporter` | 9121 | Redis metrics for Prometheus | +| k6 | `grafana/k6` | N/A | Load testing, opt-in via the `load-test` compose profile | + +## Testing strategy + +Three tiers, matching three sequential CI jobs (`unit` → `integration` → `e2e`); see [DevOps](#devops): + +| Tier | Tooling | Scope | +|---|---|---| +| **Unit** (`mvn test`, Surefire) | JUnit 5 + Mockito + AssertJ | `application`-layer use cases against mocked `domain.repository` interfaces (no Spring, no Docker); `infrastructure.cache` decorators against a mocked delegate; this verifies delegation behavior but **cannot** catch real (de)serialization bugs, since nothing is actually serialized. | +| **Integration** (`mvn failsafe:integration-test failsafe:verify`, Failsafe) | Testcontainers (Postgres + Redis) | `infrastructure.persistence` against real Postgres (Flyway-migrated, shared fixture data). Four cache integration tests wired against a **real Redis**; this tier exists specifically because a real Redis is the only place a serialization bug (like an earlier `GenericJacksonJsonRedisSerializer` type-metadata bug this project hit) actually surfaces. | +| **E2E / contract** (Postman + Newman) | `docker-compose.e2e.yaml`, a fully-built app image against plain `postgres:17` + Redis | The only tier exercising the real `Dockerfile` image end-to-end, including the logging filter and exception handler wiring. Seeded with the *same* fixture dataset the integration tests use, one source of truth, not two to keep in sync. Nine requests, 22 assertions, covering every endpoint and its documented edge cases. | + +Current counts: 32 unit tests, 22 integration tests, all passing; e2e collection verified 22/22 assertions against a live stack. + +Full test plan, including exactly why each tier exists and what it catches that the others can't: [`docs/low-level-design.md`](docs/low-level-design.md) §10. + +## DevOps + +- **Containerization**: multi-stage `Dockerfile` (`eclipse-temurin:21-jdk` build stage → `eclipse-temurin:21-jre` runtime stage), keeping the shipped image free of build tooling. +- **Local orchestration**: `docker-compose.yaml` brings up the full stack (database, cache, application, entire observability stack) with one command; a separate `docker-compose.e2e.yaml` (its own `name: imdb-e2e` and network) drives the CI e2e stage against a lightweight, fast-seeding Postgres instead of the ~20-30-minute full dataset import. Keeping the project name explicit here isn't cosmetic: two compose files in the same directory with matching service names and no distinct project name will make Compose *replace* one stack's containers with the other's, a real near-miss this project hit and fixed once and for all (see the compose file's own header comment). +- **CI**: [`imdb-ci.yml`](../.github/workflows/imdb-ci.yml), three sequential GitHub Actions jobs, each gated on the previous: + 1. `unit`: `mvn -B test` + 2. `integration`: `mvn -B failsafe:integration-test failsafe:verify` (Testcontainers) + 3. `e2e`: brings up `docker-compose.e2e.yaml`, polls for app health and seed completion, runs the Postman/Newman collection, dumps logs on failure, always tears down + +## Load testing + +One [k6](https://k6.io/) script per endpoint under `k6/`, run one at a time so results are attributable to a single endpoint, results pushed to Prometheus via `--out experimental-prometheus-rw` (visible in the k6 Load Test Results dashboard, [Observability](#observability)): + +| Script | Pattern | +|---|---| +| `search.js` | Ramping VUs (0 → 50 → 100 → 0), random query terms | +| `title-detail.js` | Ramping VUs, random `tconst` from a pre-fetched pool | +| `top-rated.js` | Ramping VUs, cycles through all genres | +| `six-degrees.js` | Ramping VUs, **a distinct person pair per iteration**, deliberately defeating the Redis cache so the bidirectional BFS's real behavior under load is what gets measured | + +``` +docker compose --profile load-test run k6 run /scripts/six-degrees.js +``` + +Full plan and per-endpoint thresholds: [`docs/low-level-design.md`](docs/low-level-design.md) §8. + +## Running it locally + +``` +docker-compose up +``` + +Brings up Postgres (seeded via `abanda/imdb-postgresql`), Redis, the application, and the full observability stack. The **first run takes 20-30 minutes** while Postgres imports the full dataset; `docker-compose logs -f postgres` shows progress. Once healthy: + +- API: `http://localhost:8080` (e.g. `curl http://localhost:8080/actuator/health`) +- Grafana: `http://localhost:3001` (anonymous admin access) +- Prometheus: `http://localhost:9090` + +For contributing/building from source: + +``` +mvn test # unit tests only, no Docker +mvn failsafe:integration-test failsafe:verify # + Testcontainers integration tests +mvn package # build the jar +``` + +## Project layout + +See [Package layout](#package-layout) above for the Java source tree; the repository root also has: + +``` +imdb/ + pom.xml, Dockerfile, docker-compose.yaml, docker-compose.e2e.yaml + k6/ load-test scripts + sampled person-pair data + postman/ e2e contract test collection + observability/ Prometheus/Loki/Tempo/Alloy/Grafana provisioning + docs/ REQUIREMENTS.md, product-design.md, low-level-design.md +``` + +## Design documents + +- [`docs/REQUIREMENTS.md`](docs/REQUIREMENTS.md): the original brief and guidelines +- [`docs/product-design.md`](docs/product-design.md): what is being built and why, including algorithm alternatives considered +- [`docs/low-level-design.md`](docs/low-level-design.md): schema, endpoint contracts, the bidirectional-BFS derivation, caching, observability wiring, and the full test plan + +## Known limitations + +- Under k6 load, six-degrees requests initially failed 83% of the time against a missing index (`title_principals.nconst` had only a partial, actor-only index: every path-enrichment call fell back to a parallel sequential scan over the 100M-row table). Adding a full index (`V4__title_principals_nconst_index.sql`) brought that down substantially, but a persistent ~25-30% failure rate remains for genuinely hard pairs (large hub actors reached mid-expansion with no intersection yet). Raising the query timeout doesn't help; it just fails slower instead of failing fast, so this is tracked as an open follow-up rather than solved by a timeout knob (`application.yaml`, `six-degrees.query-timeout-seconds`). +- `title_akas` (localized alternate titles) and `title_episode` (TV episode hierarchy) are loaded but not surfaced by any endpoint. +- No authentication/authorization: this is a read-only public API for the purposes of this exercise. +- Swagger/OpenAPI UI is deferred: `springdoc-openapi`'s Initializr `versionRange` doesn't yet cover Spring Boot 4.1. + +Full list, including deferred design alternatives (Pruned Landmark Labeling, a dedicated graph database): [`docs/product-design.md`](docs/product-design.md) §11/§12. + +## License + +Apache License 2.0. See [`LICENSE`](LICENSE), matching [`votee`](../votee) elsewhere in this monorepo. From 5997f2b736b8fd4fc680c4ef3125d88c41ec18fa Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 13 Jul 2026 01:38:04 +0200 Subject: [PATCH 19/42] Add CRUD expansion design doc for imdb Extends the read-only imdb API into a full CRUD RESTful API: JWT auth, a user-generated content layer (watchlists/reviews/custom lists), and admin CRUD over the core IMDb entities, plus the cross-cutting changes (optimistic locking, cache invalidation, soft deletes) that go with it. Co-Authored-By: Claude Sonnet 5 --- imdb/docs/crud-expansion-design.md | 307 +++++++++++++++++++++++++++++ 1 file changed, 307 insertions(+) create mode 100644 imdb/docs/crud-expansion-design.md diff --git a/imdb/docs/crud-expansion-design.md b/imdb/docs/crud-expansion-design.md new file mode 100644 index 0000000..d1626d4 --- /dev/null +++ b/imdb/docs/crud-expansion-design.md @@ -0,0 +1,307 @@ +# IMDb CRUD Expansion - Design Document + +| | | +|---|---| +| Author | Ludovic Temgoua Abanda | +| Status | Approved (brainstormed interactively; see decisions below) | +| Date | 2026-07-13 | +| Related docs | `imdb/docs/product-design.md`, `imdb/docs/low-level-design.md`, `imdb/docs/REQUIREMENTS.md` | +| Supersedes | PDD §4's original non-goals: "Authentication/authorization" and "Write endpoints of any kind" | + +## 1. Purpose and Scope + +The original `imdb` API (PDD/LLD) is a deliberately read-only layer over an externally-seeded, immutable +IMDb dataset - no auth, no writes, 24h cache TTLs justified entirely by "nothing ever changes." This +document extends that into a full CRUD RESTful API, adding two new layers on top of the existing +read-only core: + +1. **A user-generated content layer** - accounts, watchlists, reviews, and custom lists - entirely new + tables the app owns outright. +2. **An admin curation layer** - CRUD over the core IMDb entities themselves (titles, people, ratings, + cast/crew), gated behind an `ADMIN` role, writing into the same tables the original design treated as + permanently immutable. + +Everything in the original PDD/LLD (search, title detail, top-rated, six-degrees, the observability stack, +the three-tier test pipeline) stays as-is and stays public/unauthenticated. This is a strict addition, not +a breaking change. + +## 2. Decisions Made (interactive brainstorming) + +| Decision | Chosen | Rejected alternatives | +|---|---|---| +| CRUD scope | Both: user-generated layer AND admin CRUD over core entities | User-layer only; core-entity CRUD only | +| Auth mechanism | Self-issued JWT via Spring Security (hand-rolled filter, not a full OAuth2 resource server) | External OAuth2/OIDC IdP (Keycloak); static API keys | +| Delete semantics | Soft delete everywhere (`deleted_at`) | Hard delete everywhere; hybrid (soft for user content, hard for core) | +| List/watchlist visibility | Both PUBLIC and PRIVATE, owner's choice per list | Private-only | + +## 3. Authentication & Authorization + +- New dependency: `spring-boot-starter-security`. JWTs are both issued and validated by this app, so + authentication is a small hand-rolled `JwtAuthenticationFilter` (reads `Authorization: Bearer `, + validates signature/expiry, populates `SecurityContext`) rather than the full + `spring-boot-starter-oauth2-resource-server` machinery built for validating externally-issued tokens. +- `infrastructure.security.JwtService`: issues/parses HMAC-SHA256-signed tokens, secret from an env var + (`JWT_SECRET`, no default in any committed config). Claims: `sub` (userId), `roles` (`["USER"]` or + `["USER","ADMIN"]`), `exp`. +- Passwords hashed with BCrypt (`PasswordEncoder` bean, Spring Security's default). +- Two token types: a short-lived access token (15 min) and a longer-lived refresh token (7 days), issued + as a pair on login/refresh. +- A bootstrap admin account makes the `ADMIN` role reachable at all on a fresh stack (there is otherwise no + way to grant it). Flyway (`V5`, see §7) creates the `users` table but does **not** insert this row - a + Flyway migration runs before the Spring context (and its `PasswordEncoder` bean) exists, so it can't + BCrypt-hash a password cleanly. Instead, an `ApplicationRunner` bean + (`infrastructure.security.BootstrapAdminRunner`) runs once after the context is fully up: if no user with + the configured bootstrap email (`IMDB_BOOTSTRAP_ADMIN_EMAIL`) exists, it creates one with role `ADMIN`, + password BCrypt-hashed from `IMDB_BOOTSTRAP_ADMIN_PASSWORD` via the same `PasswordEncoder` bean every + other registration uses - idempotent on every restart, no separate migration-time password handling. +- **Error-shape consistency**: Spring Security's default 401/403 responses aren't RFC 7807 `ProblemDetail` + - they're a bare, framework-shaped response inconsistent with the rest of this API's error handling + (LLD §9's `ApiExceptionHandler` work). Fixed via custom `AuthenticationEntryPoint` (401) and + `AccessDeniedHandler` (403) beans that produce `ProblemDetail`, registered in `SecurityConfig`, so a + caller never sees two different error shapes depending on whether Spring MVC or Spring Security rejected + the request. +- Authorization is method-level (`@PreAuthorize("hasRole('ADMIN')")` on admin write methods, + `@PreAuthorize("isAuthenticated()")` on user-owned-resource methods), not a blanket URL-pattern rule - + this keeps the read endpoints (search, title detail, top-rated, six-degrees, and the new public + review/list-browsing endpoints) genuinely public with zero filter overhead, while write endpoints are + individually and explicitly protected. + +## 4. New Resources: Users, Watchlists, Reviews, Custom Lists + +### 4.1 Users (`users` table) + +| Endpoint | Auth | Description | +|---|---|---| +| `POST /api/v1/auth/register` | Public | Create account (`email`, `password`, `displayName`) -> role `USER`. 409 if email taken. | +| `POST /api/v1/auth/login` | Public | `{ email, password }` -> `{ accessToken, refreshToken }` | +| `POST /api/v1/auth/refresh` | Public (valid refresh token) | `{ refreshToken }` -> new access token | +| `GET /api/v1/users/me` | User | Own full profile | +| `PUT /api/v1/users/me` | User | Update own profile (`displayName`, `bio`) | +| `DELETE /api/v1/users/me` | User | Soft-delete own account | +| `GET /api/v1/users/{userId}` | Public | Limited public profile (`displayName` only) | +| `GET /api/v1/users` | Admin | Paginated list of all users | +| `PUT /api/v1/users/{userId}/role` | Admin | Grant/revoke `ADMIN` | +| `DELETE /api/v1/users/{userId}` | Admin | Moderation: soft-delete any account | + +### 4.2 Watchlist (`watchlists` + `watchlist_items`, one watchlist per user) + +| Endpoint | Auth | Description | +|---|---|---| +| `GET /api/v1/watchlist` | User | Own watchlist + items (auto-created on first access) | +| `POST /api/v1/watchlist/items` | User | Add `{ titleId }` | +| `DELETE /api/v1/watchlist/items/{titleId}` | User | Remove a title | +| `PUT /api/v1/watchlist/visibility` | User | `{ visibility: PUBLIC\|PRIVATE }` | +| `GET /api/v1/users/{userId}/watchlist` | Public if `PUBLIC` | View another user's watchlist | + +### 4.3 Reviews (`reviews` table, one per `(user, title)`, always public) + +| Endpoint | Auth | Description | +|---|---|---| +| `POST /api/v1/titles/{titleId}/reviews` | User | Create own review+rating. 409 if one already exists for this pair - use PUT instead. | +| `GET /api/v1/titles/{titleId}/reviews` | Public | Paginated reviews for a title | +| `GET /api/v1/titles/{titleId}/reviews/me` | User | Own review for that title | +| `PUT /api/v1/titles/{titleId}/reviews/me` | User | Update own review | +| `DELETE /api/v1/titles/{titleId}/reviews/me` | User | Soft-delete own review | +| `GET /api/v1/users/{userId}/reviews` | Public | All reviews a user has written | + +Title detail gains two new, additive fields derived from this table: `userRatingAverage` and +`userRatingCount`, shown alongside the existing IMDb `rating` field. Both are `null`/`0` if no reviews +exist yet. + +### 4.4 Custom lists (`lists` + `list_items`) + +| Endpoint | Auth | Description | +|---|---|---| +| `POST /api/v1/lists` | User | `{ name, visibility }` | +| `GET /api/v1/lists/me` | User | All own lists (any visibility) | +| `GET /api/v1/lists/public` | Public | Paginated discovery of public lists across all users | +| `GET /api/v1/lists/{listId}` | Public if `PUBLIC`, else owner-only | View a list + its items | +| `PUT /api/v1/lists/{listId}` | Owner | Rename / change visibility | +| `DELETE /api/v1/lists/{listId}` | Owner | Soft-delete | +| `POST /api/v1/lists/{listId}/items` | Owner | Add `{ titleId }` | +| `DELETE /api/v1/lists/{listId}/items/{titleId}` | Owner | Remove a title | + +Accessing a `PRIVATE` list/watchlist you don't own returns `404`, not `403` - existence of another user's +private list is not itself information this API discloses. + +## 5. Admin CRUD over the Core IMDb Entities + +**ID-collision wrinkle**: `tconst`/`nconst` are plain integers, seeded by the external +`abanda/imdb-postgresql` image and already densely allocated. Admin-created titles/people need IDs that +can never collide with an existing seeded row. Fix: two Postgres `SEQUENCE`s +(`title_id_seq`/`person_id_seq`), initialized once in `V6` to `MAX(tconst)+1`/`MAX(nconst)+1`, used *only* +for app-created rows. Seeded rows keep their original IDs untouched. New rows translate through the same +`utils.ImdbIds` formatter already at the API boundary - a caller never sees anything different from a +normal `tt`/`nm` ID. + +### 5.1 Titles + +| Endpoint | Description | +|---|---| +| `POST /api/v1/titles` | Create (`primaryTitle`, `originalTitle`, `titleType`, `startYear`, `endYear`, `runtimeMinutes`, `genres`) | +| `PUT /api/v1/titles/{titleId}` | Full update (requires current `version`, §6.1) | +| `PATCH /api/v1/titles/{titleId}` | Partial update (merge-patch: only send fields to change) | +| `DELETE /api/v1/titles/{titleId}` | Soft-delete | +| `PUT /api/v1/titles/{titleId}/crew` | Upsert `{ directors: [personId...], writers: [personId...] }` - a singleton per title, mirroring `title_crew` | + +### 5.2 People + +| Endpoint | Description | +|---|---| +| `POST /api/v1/people` | Create (`primaryName`, `birthYear`, `deathYear`, `primaryProfession`) | +| `PUT /api/v1/people/{personId}` | Full update | +| `PATCH /api/v1/people/{personId}` | Partial update | +| `DELETE /api/v1/people/{personId}` | Soft-delete | + +### 5.3 Ratings (singleton per title) + +| Endpoint | Description | +|---|---| +| `PUT /api/v1/titles/{titleId}/rating` | Set/replace `{ averageRating, numVotes }` | +| `DELETE /api/v1/titles/{titleId}/rating` | Remove the rating (title detail omits it) | + +### 5.4 Cast/crew credits (`title_principals`) + +| Endpoint | Auth | Description | +|---|---|---| +| `GET /api/v1/titles/{titleId}/principals` | Public | Full, uncapped credit list (title detail's own list stays capped at 20) | +| `POST /api/v1/titles/{titleId}/principals` | Admin | Add `{ personId, category, job, characters, ordering }` | +| `PUT /api/v1/titles/{titleId}/principals/{principalId}` | Admin | Update a credit | +| `DELETE /api/v1/titles/{titleId}/principals/{principalId}` | Admin | Soft-delete a credit | + +Genres stay a plain validated string array on the title itself (matching the current schema), not a +separate managed `Genre` resource - a full taxonomy-management feature isn't justified by anything in +scope here. + +Admin write endpoints are added to the *existing* `TitleController`/`PersonController`/`GenreController` +classes (`@PreAuthorize`-gated), not parallel `Admin*Controller` classes - the resource is the same, only +the allowed verb set differs by role. + +## 6. Cross-Cutting Concerns + +### 6.1 Optimistic locking + +Every entity with a `PUT`/`PATCH` update path gets a `version` integer column, incremented on each +successful write. The current `version` must be included in the update request body; a mismatch is a +`409 Conflict` (new `domain.exception.ConflictException`), not a silent overwrite. This applies to: +`title_basics`, `name_basics`, `title_ratings`, `title_principals`, `title_crew`, `reviews`, `lists`, +`users` (profile updates). Join/item-only tables (`watchlist_items`, `list_items`) don't get a version - +they're pure add/remove, not update-in-place. + +### 6.2 Cache invalidation on writes + +The original caching design's 24h TTLs and "no write path, so `FLUSHDB` on redeploy is fine" reasoning +(LLD §6) no longer holds once writes exist. Fixed per cache region, using Spring's existing `@Cacheable` +decorator classes (`infrastructure.cache`) extended with `@CacheEvict` methods - no new custom eviction +infrastructure needed, since this is exactly what the annotation-driven cache abstraction already does: + +| Cache region | Eviction on write | +|---|---| +| `title-detail` | Precise: `@CacheEvict(cacheNames = "title-detail", key = "#titleId")` on any title/rating/crew/principals/review write affecting that title | +| `title-search` | No precise key to evict (keyed by arbitrary `query:page:size` combos). TTL reduced from 24h to 15 minutes instead - the honest trade-off, since evicting "every search result that might now be stale" isn't feasible without scanning | +| `top-rated` | Coarse: `@CacheEvict(cacheNames = "top-rated", allEntries = true)` on any title/rating write - correct and cheap, since admin writes are expected to be infrequent | +| `six-degrees` | Coarse: `@CacheEvict(cacheNames = "six-degrees", allEntries = true)` on any people/principals write - a precise per-affected-pair eviction would need a reverse lookup this design doesn't build; full-region eviction favors correctness over cache efficiency for a rarely-written path | + +### 6.3 Error handling additions + +- `domain.exception.ConflictException` -> `409`: duplicate review, stale optimistic-lock version, duplicate + email at registration. +- `domain.exception.ForbiddenException` -> `403`: non-owner attempting to modify someone else's + watchlist/list/review. +- Both mapped in `ApiExceptionHandler` alongside the existing `NotFoundException`/`IllegalArgumentException` + handlers - same pattern, no change to the `extends ResponseEntityExceptionHandler` approach that fixed + the earlier 404/400/405 regression. +- Bean Validation (`jakarta.validation`, already a dependency) on every new request DTO. + +### 6.4 Soft-delete convention + +A `deleted_at TIMESTAMPTZ` column on every writable table (added in `V7` for the core tables, native on +every new table from `V5` onward). Every `SELECT` in `infrastructure.persistence` gains a +`WHERE deleted_at IS NULL` clause. A soft-deleted title's existing cast credits, reviews, and +watchlist/list items are left in place but the title itself stops appearing in search, detail, top-rated, +and six-degrees traversal - a watchlist/list item referencing a since-deleted title is filtered out of its +parent's item list rather than erroring. + +### 6.5 Pagination and PATCH conventions + +New collection endpoints (reviews, public lists, admin user list) reuse the existing hand-rolled +`PagedResult` (LLD §4.1) - no new pagination mechanism. `PATCH` uses merge-patch semantics (only +included fields change; omitted fields are left alone), not full JSON Patch (RFC 6902) - consistent with +this project's plain-DTO style elsewhere. + +## 7. Data Model / Schema Additions + +New Flyway migrations, `V5` onward (current latest is `V4__title_principals_nconst_index.sql`): + +| Migration | Adds | +|---|---| +| `V5__users_table.sql` | `users` (id, email, password_hash, display_name, bio, role, version, created_at, deleted_at) - schema only, no seed row (bootstrap admin handled by `BootstrapAdminRunner`, see §3) | +| `V6__admin_id_sequences.sql` | `title_id_seq` seeded to `MAX(tconst)+1`, `person_id_seq` seeded to `MAX(nconst)+1` | +| `V7__core_entity_version_and_soft_delete.sql` | `version`/`deleted_at` columns on `title_basics`, `name_basics`, `title_ratings`, `title_principals`, `title_crew` | +| `V8__watchlists.sql` | `watchlists` (id, user_id, visibility, version, deleted_at), `watchlist_items` (watchlist_id, title_id, added_at) | +| `V9__reviews.sql` | `reviews` (id, user_id, title_id, rating, body, version, deleted_at, created_at, updated_at); unique constraint on `(user_id, title_id)` where `deleted_at IS NULL` | +| `V10__lists.sql` | `lists` (id, user_id, name, visibility, version, deleted_at), `list_items` (list_id, title_id, added_at, ordering) | + +## 8. Architecture Impact + +New additions within the existing onion layering (LLD §2.1), no change to the dependency rule itself: + +``` +domain/ + model/ User, Role, Watchlist, WatchlistItem, Review, CustomList, ListItem, Visibility + repository/ UserRepository, WatchlistRepository, ReviewRepository, ListRepository (interfaces) + exception/ ConflictException, ForbiddenException +application/ + contracts/ AuthUseCase, UserUseCase, WatchlistUseCase, ReviewUseCase, ListUseCase, + TitleAdminUseCase, PersonAdminUseCase + *Impl plain orchestration for each, mirroring the existing use-case/decorator split +infrastructure/ + persistence/ JdbcUserRepository, JdbcWatchlistRepository, JdbcReviewRepository, JdbcListRepository + security/ JwtService, JwtAuthenticationFilter, SecurityConfig, + ProblemDetailAuthenticationEntryPoint, ProblemDetailAccessDeniedHandler + cache/ @CacheEvict additions to the existing Caching* decorators (§6.2) - no new decorator + classes, since eviction is added to the classes that already own each cache region +presentation/ + AuthController, UserController (new), WatchlistController, ReviewController, ListController + TitleController, PersonController, GenreController - gain @PreAuthorize-gated write methods (existing + classes, not new Admin* ones) +``` + +`TitleAdminUseCase` covers title CRUD + crew + rating + principals (all title-scoped admin operations, +grouped by domain cohesion rather than one interface per table); `PersonAdminUseCase` covers person CRUD. + +## 9. Testing Plan Additions + +- **Unit**: one test class per new use case (mocked repository interfaces), matching the existing pattern + exactly. `JwtService` gets dedicated unit tests (issue/parse/expiry/tampered-signature rejection). +- **Integration** (Testcontainers): new JDBC repository integration tests for `users`/`watchlists`/ + `reviews`/`lists`, following the existing `*IntegrationTest.java` convention. New integration tests + verifying `@CacheEvict` actually clears the affected Redis entry after a write - the same + Redis-Testcontainers rationale as the existing four cache integration tests (LLD §10.2): a mocked cache + can't prove an eviction call actually reached Redis. +- **E2E** (Postman/Newman): a full auth flow (register -> login -> use access token -> refresh), a full + CRUD lifecycle per new resource (watchlist, review, list), and negative cases specifically worth + contract-testing at this tier: a non-admin hitting an admin write endpoint (403), a stale-version update + (409), and access to another user's private list (404). + +## 10. Observability Additions + +Per the existing level policy (LLD §7): INFO for login success/failure and every admin write (business- +significant, same tier as the existing six-degrees timing/ambiguity logs); DEBUG for cache-eviction calls +(mirrors the existing cache-miss DEBUG convention); WARN for repeated failed-login attempts from the same +account, as a lightweight brute-force signal without building a full account-lockout feature. No new +dashboard is planned in this pass - the existing HTTP Overview dashboard's per-`uri` breakdown already +covers the new endpoints automatically. + +## 11. Out of Scope / Deferred + +- **Rate limiting** - a genuinely separate, infra-level concern (normally a gateway/proxy responsibility, + not application code); adding a Redis-backed token-bucket limiter now would meaningfully balloon this + pass's scope without being core to "CRUD expansion." Documented here as a deliberate boundary, the same + way the original PDD documented Pruned Landmark Labeling/Neo4j as evaluated-but-not-built. +- **Email verification / password reset flows** - registration creates a usable account immediately; a + real "verify your email" or "forgot password" flow is a distinct feature or its own pass. +- **A separate `Genre` managed resource** - genres stay a plain validated string array (§5.4). +- **Bulk import/export endpoints** - every write endpoint here is single-resource; batch operations aren't + part of this pass. +- **Full JSON Patch (RFC 6902)** - `PATCH` uses simple merge-patch semantics instead (§6.5). From 1b54d37a0cefc825d2ae321786b2819963a13354 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 13 Jul 2026 04:16:21 +0200 Subject: [PATCH 20/42] Add implementation plan for the imdb CRUD expansion Nine-phase, bite-sized TDD plan covering JWT auth, admin CRUD over the core IMDb entities, and the new user-generated content layer (watchlists/ reviews/lists), plus the optimistic locking, soft-delete, and cache- eviction conventions the writes need. Self-review caught and fixed three gaps: missing user profile/admin-management endpoints, a missing title-search cache TTL reduction, and missing cache-eviction test coverage. Co-Authored-By: Claude Sonnet 5 --- imdb/docs/crud-expansion-plan.md | 6649 ++++++++++++++++++++++++++++++ 1 file changed, 6649 insertions(+) create mode 100644 imdb/docs/crud-expansion-plan.md diff --git a/imdb/docs/crud-expansion-plan.md b/imdb/docs/crud-expansion-plan.md new file mode 100644 index 0000000..093878a --- /dev/null +++ b/imdb/docs/crud-expansion-plan.md @@ -0,0 +1,6649 @@ +# IMDb CRUD Expansion Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Extend the read-only `imdb` API into a full CRUD RESTful API: JWT-based auth, a user-generated content layer (watchlists/reviews/custom lists), and admin CRUD over the core IMDb entities (titles/people/ratings/cast-crew), plus the optimistic locking, cache invalidation, and soft-delete conventions that make those writes safe. + +**Architecture:** Strict addition on top of the existing onion layers (`presentation -> infrastructure -> application -> domain`, plus `utils`). New resources get the same interface/impl/decorator shape already used by the four read endpoints. Admin writes land in the existing `TitleController`/`PersonController`/`GenreController` classes, gated by `@PreAuthorize`, not new `Admin*` classes. + +**Tech Stack:** Spring Boot 4.1, Java 21, Maven, `spring-boot-starter-security` (new), plain JDBC (`NamedParameterJdbcTemplate`), PostgreSQL, Redis (Spring Cache), Flyway, JUnit 5 + Mockito + AssertJ, Testcontainers, Postman/Newman. + +## Global Constraints + +- Package root: `com.ludovictemgoua.imdb`. Follow the onion layering exactly: `domain` imports nothing; `application` imports only `domain`/`utils`; `infrastructure`/`presentation` may import inward layers only. +- Every writable table gets `version INTEGER NOT NULL DEFAULT 0` and `deleted_at TIMESTAMPTZ` (soft delete, per `docs/crud-expansion-design.md` §6.1/§6.4). Every read query filters `WHERE deleted_at IS NULL`. +- IDs at the API boundary are always IMDb-style `tt`/`nm` strings via `utils.ImdbIds`, never raw integers - matches the existing convention exactly. +- New Flyway migrations start at `V5` (current latest is `V4__title_principals_nconst_index.sql`). +- Domain models are Java records. Repositories are interfaces in `domain.repository`, implementations in `infrastructure.persistence` using `NamedParameterJdbcTemplate` + `MapSqlParameterSource`, row-mapped via static private methods - copy `JdbcTitleRepository`'s style exactly. +- Unit tests: JUnit 5 + `@ExtendWith(MockitoExtension.class)` + AssertJ, no Spring context, mocked repository interfaces - copy `TitleSearchUseCaseImplTest`'s style exactly. +- Integration tests: `@Import(TestcontainersConfiguration.class) @SpringBootTest @Transactional @Sql("/fixtures/fixture-data.sql")`, named `*IntegrationTest.java` (Surefire/Failsafe split depends on this suffix - see `pom.xml`). +- Controller tests: `@WebMvcTest(XController.class)` + `@MockitoBean` on the use-case interfaces - copy `TitleControllerTest`'s style exactly. +- New domain exceptions (`ConflictException`, `ForbiddenException`) get handlers added to the existing `ApiExceptionHandler` (which `extends ResponseEntityExceptionHandler` - do not replace this with a bare `@RestControllerAdvice`, see that class's own header comment for why). +- Run `JAVA_HOME="/c/Program Files/Java/jdk-21"` before any `./mvnw` command on this machine (sdkman's default `mvnw` resolves Java 8 otherwise). + +--- + +## Phase 1: Security & Auth Foundation + +### Task 1.1: `users` table, `User`/`Role` domain models, `UserRepository` + +**Files:** +- Create: `src/main/resources/db/migration/V5__users_table.sql` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/Role.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/User.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/repository/UserRepository.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcUserRepository.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcUserRepositoryIntegrationTest.java` + +**Interfaces:** +- Produces: `User(int id, String email, String passwordHash, String displayName, String bio, Role role, int version)`, `Role.USER`/`Role.ADMIN`, `UserRepository` with `insert`, `findById`, `findByEmail`, `existsByEmail`, `updateProfile`, `updateRole`, `softDelete`. `WriteResult` enum (`SUCCESS`, `NOT_FOUND`, `VERSION_CONFLICT`) used by every later versioned-update repository method in this plan. + +- [ ] **Step 1: Write the failing integration test** + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +class JdbcUserRepositoryIntegrationTest { + + @Autowired + JdbcUserRepository repository; + + @Test + void insertThenFindByEmailReturnsTheSameUser() { + var inserted = repository.insert("ada@example.com", "hash1", "Ada", Role.USER); + + var found = repository.findByEmail("ada@example.com").orElseThrow(); + + assertThat(found.id()).isEqualTo(inserted.id()); + assertThat(found.displayName()).isEqualTo("Ada"); + assertThat(found.role()).isEqualTo(Role.USER); + assertThat(found.version()).isEqualTo(0); + } + + @Test + void existsByEmailIsFalseForAnUnknownAddress() { + assertThat(repository.existsByEmail("nobody@example.com")).isFalse(); + } + + @Test + void updateProfileBumpsVersionAndPersistsChanges() { + var user = repository.insert("grace@example.com", "hash2", "Grace", Role.USER); + + var result = repository.updateProfile(user.id(), "Grace H.", "Compiler pioneer", user.version()); + + assertThat(result).isEqualTo(WriteResult.SUCCESS); + var updated = repository.findById(user.id()).orElseThrow(); + assertThat(updated.displayName()).isEqualTo("Grace H."); + assertThat(updated.bio()).isEqualTo("Compiler pioneer"); + assertThat(updated.version()).isEqualTo(1); + } + + @Test + void updateProfileReturnsVersionConflictOnStaleVersion() { + var user = repository.insert("alan@example.com", "hash3", "Alan", Role.USER); + + var result = repository.updateProfile(user.id(), "Alan T.", null, user.version() + 1); + + assertThat(result).isEqualTo(WriteResult.VERSION_CONFLICT); + } + + @Test + void softDeleteExcludesTheUserFromFindById() { + var user = repository.insert("delete-me@example.com", "hash4", "Temp", Role.USER); + + repository.softDelete(user.id()); + + assertThat(repository.findById(user.id())).isEmpty(); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcUserRepositoryIntegrationTest` +Expected: FAIL - compilation error, `JdbcUserRepository`/`Role`/`WriteResult` don't exist yet. + +- [ ] **Step 3: Create the migration** + +```sql +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + email TEXT NOT NULL, + password_hash TEXT NOT NULL, + display_name TEXT NOT NULL, + bio TEXT, + role TEXT NOT NULL DEFAULT 'USER', + version INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + deleted_at TIMESTAMPTZ +); + +CREATE UNIQUE INDEX idx_users_email ON users (email) WHERE deleted_at IS NULL; +``` + +- [ ] **Step 4: Create `Role`, `User`, `WriteResult`** + +```java +package com.ludovictemgoua.imdb.domain.model; + +public enum Role { USER, ADMIN } +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +public record User(int id, String email, String passwordHash, String displayName, String bio, + Role role, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.domain.repository; + +// Shared by every repository method backing a PUT/PATCH update or a DELETE on a versioned entity +// (users, titles, people, reviews, lists, ...) - lets the use-case layer distinguish "no such row" +// from "row exists but your version is stale" without the repository itself deciding which HTTP +// status or domain exception that becomes (that stays an application-layer decision, matching how +// NotFoundException is already thrown by use cases today, not repositories). +public enum WriteResult { SUCCESS, NOT_FOUND, VERSION_CONFLICT } +``` + +- [ ] **Step 5: Create `UserRepository` and `JdbcUserRepository`** + +```java +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.User; + +import java.util.Optional; + +public interface UserRepository { + + User insert(String email, String passwordHash, String displayName, Role role); + + Optional findById(int id); + + Optional findByEmail(String email); + + boolean existsByEmail(String email); + + WriteResult updateProfile(int id, String displayName, String bio, int expectedVersion); + + void updateRole(int id, Role role); + + void softDelete(int id); + + PagedResult findAll(int page, int size); +} +``` + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.User; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Repository +public class JdbcUserRepository implements UserRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public JdbcUserRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + @Override + public User insert(String email, String passwordHash, String displayName, Role role) { + String sql = """ + INSERT INTO users (email, password_hash, display_name, role) + VALUES (:email, :passwordHash, :displayName, :role) + """; + var params = new MapSqlParameterSource() + .addValue("email", email).addValue("passwordHash", passwordHash) + .addValue("displayName", displayName).addValue("role", role.name()); + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbc.update(sql, params, keyHolder, new String[]{"id"}); + int id = keyHolder.getKey().intValue(); + return new User(id, email, passwordHash, displayName, null, role, 0); + } + + @Override + public Optional findById(int id) { + String sql = "SELECT * FROM users WHERE id = :id AND deleted_at IS NULL"; + return jdbc.query(sql, Map.of("id", id), JdbcUserRepository::mapUser).stream().findFirst(); + } + + @Override + public Optional findByEmail(String email) { + String sql = "SELECT * FROM users WHERE email = :email AND deleted_at IS NULL"; + return jdbc.query(sql, Map.of("email", email), JdbcUserRepository::mapUser).stream().findFirst(); + } + + @Override + public boolean existsByEmail(String email) { + Integer count = jdbc.queryForObject( + "SELECT count(*) FROM users WHERE email = :email AND deleted_at IS NULL", + Map.of("email", email), Integer.class); + return count != null && count > 0; + } + + @Override + public WriteResult updateProfile(int id, String displayName, String bio, int expectedVersion) { + if (findById(id).isEmpty()) { + return WriteResult.NOT_FOUND; + } + String sql = """ + UPDATE users SET display_name = :displayName, bio = :bio, version = version + 1 + WHERE id = :id AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("displayName", displayName).addValue("bio", bio) + .addValue("id", id).addValue("expectedVersion", expectedVersion); + int updated = jdbc.update(sql, params); + return updated == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public void updateRole(int id, Role role) { + jdbc.update("UPDATE users SET role = :role, version = version + 1 WHERE id = :id", + new MapSqlParameterSource().addValue("role", role.name()).addValue("id", id)); + } + + @Override + public void softDelete(int id) { + jdbc.update("UPDATE users SET deleted_at = now() WHERE id = :id", Map.of("id", id)); + } + + @Override + public PagedResult findAll(int page, int size) { + String dataSql = "SELECT * FROM users WHERE deleted_at IS NULL ORDER BY id LIMIT :limit OFFSET :offset"; + String countSql = "SELECT count(*) FROM users WHERE deleted_at IS NULL"; + var params = new MapSqlParameterSource().addValue("limit", size).addValue("offset", (long) page * size); + List content = jdbc.query(dataSql, params, JdbcUserRepository::mapUser); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + private static User mapUser(ResultSet rs, int rowNum) throws SQLException { + return new User(rs.getInt("id"), rs.getString("email"), rs.getString("password_hash"), + rs.getString("display_name"), rs.getString("bio"), + Role.valueOf(rs.getString("role")), rs.getInt("version")); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcUserRepositoryIntegrationTest` +Expected: PASS, 5 tests green. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/resources/db/migration/V5__users_table.sql src/main/java/com/ludovictemgoua/imdb/domain/model/Role.java src/main/java/com/ludovictemgoua/imdb/domain/model/User.java src/main/java/com/ludovictemgoua/imdb/domain/repository/UserRepository.java src/main/java/com/ludovictemgoua/imdb/domain/repository/WriteResult.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcUserRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcUserRepositoryIntegrationTest.java +git commit -m "Add users table, User/Role domain models, and JdbcUserRepository" +``` + +### Task 1.2: Spring Security dependency, `PasswordEncoder`, `JwtService` + +**Files:** +- Modify: `pom.xml` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java` + +**Interfaces:** +- Consumes: `Role` (Task 1.1) +- Produces: `JwtService.issueAccessToken(int userId, Set roles)`, `issueRefreshToken(int userId)`, + `JwtService.Parsed(int userId, Set roles)` record, `parse(String token)` returning + `Optional` (empty on expired/tampered/malformed tokens - never throws). + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.ludovictemgoua.imdb.domain.model.Role; +import org.junit.jupiter.api.Test; + +import java.time.Duration; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; + +class JwtServiceTest { + + private final JwtService jwtService = new JwtService( + "test-secret-at-least-32-bytes-long-for-hs256", Duration.ofMinutes(15), Duration.ofDays(7)); + + @Test + void issuedAccessTokenParsesBackToTheSameUserAndRoles() { + String token = jwtService.issueAccessToken(42, Set.of(Role.USER, Role.ADMIN)); + + var parsed = jwtService.parse(token).orElseThrow(); + + assertThat(parsed.userId()).isEqualTo(42); + assertThat(parsed.roles()).containsExactlyInAnyOrder(Role.USER, Role.ADMIN); + } + + @Test + void parseReturnsEmptyForATamperedToken() { + String token = jwtService.issueAccessToken(1, Set.of(Role.USER)); + String tampered = token.substring(0, token.length() - 1) + (token.endsWith("A") ? "B" : "A"); + + assertThat(jwtService.parse(tampered)).isEmpty(); + } + + @Test + void parseReturnsEmptyForAnAlreadyExpiredToken() { + var shortLived = new JwtService( + "test-secret-at-least-32-bytes-long-for-hs256", Duration.ofMillis(1), Duration.ofDays(7)); + String token = shortLived.issueAccessToken(1, Set.of(Role.USER)); + + await(50); + + assertThat(shortLived.parse(token)).isEmpty(); + } + + private static void await(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=JwtServiceTest` +Expected: FAIL - `JwtService` doesn't exist yet. + +- [ ] **Step 3: Add the Spring Security and JJWT dependencies to `pom.xml`** + +Add inside ``, alongside the existing entries: + +```xml + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-security-test + test + + + io.jsonwebtoken + jjwt-api + 0.12.6 + + + io.jsonwebtoken + jjwt-impl + 0.12.6 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.12.6 + runtime + +``` + +- [ ] **Step 4: Create `JwtService`** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.ludovictemgoua.imdb.domain.model.Role; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.crypto.SecretKey; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +@Component +public class JwtService { + + private final SecretKey key; + private final Duration accessTokenTtl; + private final Duration refreshTokenTtl; + + public JwtService( + @Value("${imdb.jwt.secret}") String secret, + @Value("${imdb.jwt.access-token-ttl:PT15M}") Duration accessTokenTtl, + @Value("${imdb.jwt.refresh-token-ttl:P7D}") Duration refreshTokenTtl) { + this.key = Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)); + this.accessTokenTtl = accessTokenTtl; + this.refreshTokenTtl = refreshTokenTtl; + } + + public String issueAccessToken(int userId, Set roles) { + Instant now = Instant.now(); + return Jwts.builder() + .subject(String.valueOf(userId)) + .claim("roles", roles.stream().map(Role::name).collect(Collectors.toList())) + .issuedAt(Date.from(now)) + .expiration(Date.from(now.plus(accessTokenTtl))) + .signWith(key) + .compact(); + } + + public String issueRefreshToken(int userId) { + Instant now = Instant.now(); + return Jwts.builder() + .subject(String.valueOf(userId)) + .claim("type", "refresh") + .issuedAt(Date.from(now)) + .expiration(Date.from(now.plus(refreshTokenTtl))) + .signWith(key) + .compact(); + } + + public Optional parse(String token) { + try { + Claims claims = Jwts.parser().verifyWith(key).build() + .parseSignedClaims(token).getPayload(); + int userId = Integer.parseInt(claims.getSubject()); + @SuppressWarnings("unchecked") + List roleNames = claims.get("roles", List.class); + Set roles = roleNames == null ? Set.of() + : roleNames.stream().map(Role::valueOf).collect(Collectors.toSet()); + return Optional.of(new Parsed(userId, roles)); + } catch (JwtException | IllegalArgumentException e) { + return Optional.empty(); + } + } + + public record Parsed(int userId, Set roles) { + } +} +``` + +- [ ] **Step 5: Add `imdb.jwt.secret` to `application.yaml` and the `PasswordEncoder` bean** + +Append to `src/main/resources/application.yaml`: + +```yaml +imdb: + jwt: + # No default - must be set via JWT_SECRET env var (>= 32 bytes for HS256). Deliberately absent + # here rather than defaulted to something committed, since this signs every access/refresh token. + secret: ${JWT_SECRET} +``` + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=JwtServiceTest` +Expected: PASS, 3 tests green. + +- [ ] **Step 7: Commit** + +```bash +git add pom.xml src/main/resources/application.yaml src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java +git commit -m "Add Spring Security dependency, PasswordEncoder, and JwtService" +``` + +### Task 1.3: `JwtAuthenticationFilter`, security filter chain, `ProblemDetail` error handlers + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilter.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/ProblemDetailAuthenticationEntryPoint.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/ProblemDetailAccessDeniedHandler.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java` + +**Interfaces:** +- Consumes: `JwtService.parse(String)` (Task 1.2) +- Produces: a populated `SecurityContextHolder` (authorities `ROLE_USER`/`ROLE_ADMIN`) for any request + carrying a valid `Authorization: Bearer` token; the filter chain permits `/api/v1/auth/**`, GETs on the + existing read endpoints plus the new public browse endpoints, and `/actuator/**` with no token at all; + everything else requires authentication. Role-specific gating is `@PreAuthorize` on individual methods + (later tasks); ownership gating (e.g. "is this your list") is a use-case-level check, not done here. + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.ludovictemgoua.imdb.domain.model.Role; +import jakarta.servlet.FilterChain; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class JwtAuthenticationFilterTest { + + @Mock + JwtService jwtService; + @Mock + HttpServletRequest request; + @Mock + HttpServletResponse response; + @Mock + FilterChain chain; + + @AfterEach + void clearContext() { + SecurityContextHolder.clearContext(); + } + + @Test + void populatesSecurityContextForAValidBearerToken() throws Exception { + given(request.getHeader("Authorization")).willReturn("Bearer good-token"); + given(jwtService.parse("good-token")) + .willReturn(Optional.of(new JwtService.Parsed(7, Set.of(Role.USER)))); + + new JwtAuthenticationFilter(jwtService).doFilterInternal(request, response, chain); + + var auth = SecurityContextHolder.getContext().getAuthentication(); + assertThat(auth.getName()).isEqualTo("7"); + assertThat(auth.getAuthorities()).extracting(Object::toString).containsExactly("ROLE_USER"); + verify(chain).doFilter(request, response); + } + + @Test + void leavesSecurityContextEmptyWithNoAuthorizationHeader() throws Exception { + given(request.getHeader("Authorization")).willReturn(null); + + new JwtAuthenticationFilter(jwtService).doFilterInternal(request, response, chain); + + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + verify(chain).doFilter(request, response); + } + + @Test + void leavesSecurityContextEmptyForAnInvalidToken() throws Exception { + given(request.getHeader("Authorization")).willReturn("Bearer bad-token"); + given(jwtService.parse("bad-token")).willReturn(Optional.empty()); + + new JwtAuthenticationFilter(jwtService).doFilterInternal(request, response, chain); + + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + verify(chain).doFilter(request, response); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=JwtAuthenticationFilterTest` +Expected: FAIL - `JwtAuthenticationFilter` doesn't exist yet. + +- [ ] **Step 3: Create `JwtAuthenticationFilter`** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.ludovictemgoua.imdb.domain.model.Role; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.lang.NonNull; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import java.io.IOException; +import java.util.List; +import java.util.Set; + +@Component +public class JwtAuthenticationFilter extends OncePerRequestFilter { + + private final JwtService jwtService; + + public JwtAuthenticationFilter(JwtService jwtService) { + this.jwtService = jwtService; + } + + @Override + protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, + @NonNull FilterChain filterChain) throws ServletException, IOException { + String header = request.getHeader("Authorization"); + if (header != null && header.startsWith("Bearer ")) { + String token = header.substring("Bearer ".length()); + jwtService.parse(token).ifPresent(parsed -> authenticate(parsed.userId(), parsed.roles())); + } + filterChain.doFilter(request, response); + } + + private void authenticate(int userId, Set roles) { + List authorities = roles.stream() + .map(role -> (GrantedAuthority) new SimpleGrantedAuthority("ROLE_" + role.name())) + .toList(); + var auth = new UsernamePasswordAuthenticationToken(String.valueOf(userId), null, authorities); + SecurityContextHolder.getContext().setAuthentication(auth); + } +} +``` + +- [ ] **Step 4: Create the `ProblemDetail` entry point and access-denied handler** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ProblemDetail; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +// Spring Security's default 401 response isn't a ProblemDetail - it's a bare, framework-shaped +// response, inconsistent with every other error this API returns (ApiExceptionHandler). This keeps +// the shape consistent regardless of whether Spring MVC or Spring Security rejected the request. +@Component +public class ProblemDetailAuthenticationEntryPoint implements AuthenticationEntryPoint { + + private final ObjectMapper objectMapper; + + public ProblemDetailAuthenticationEntryPoint(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, + AuthenticationException authException) throws IOException { + ProblemDetail body = ProblemDetail.forStatusAndDetail( + HttpStatus.UNAUTHORIZED, "A valid Authorization: Bearer token is required"); + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE); + objectMapper.writeValue(response.getWriter(), body); + } +} +``` + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ProblemDetail; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import java.io.IOException; + +@Component +public class ProblemDetailAccessDeniedHandler implements AccessDeniedHandler { + + private final ObjectMapper objectMapper; + + public ProblemDetailAccessDeniedHandler(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, + AccessDeniedException accessDeniedException) throws IOException { + ProblemDetail body = ProblemDetail.forStatusAndDetail( + HttpStatus.FORBIDDEN, "You do not have permission to perform this action"); + response.setStatus(HttpStatus.FORBIDDEN.value()); + response.setContentType(MediaType.APPLICATION_PROBLEM_JSON_VALUE); + objectMapper.writeValue(response.getWriter(), body); + } +} +``` + +- [ ] **Step 5: Wire the filter chain into `SecurityConfig`** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + +@Configuration +@EnableMethodSecurity +public class SecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public SecurityFilterChain securityFilterChain( + HttpSecurity http, JwtAuthenticationFilter jwtAuthenticationFilter, + ProblemDetailAuthenticationEntryPoint authenticationEntryPoint, + ProblemDetailAccessDeniedHandler accessDeniedHandler) throws Exception { + return http + .csrf(AbstractHttpConfigurer::disable) + .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .authorizeHttpRequests(auth -> auth + .requestMatchers("/actuator/**", "/api/v1/auth/**").permitAll() + .requestMatchers(HttpMethod.GET, + "/api/v1/titles/**", "/api/v1/genres/**", "/api/v1/people/six-degrees", + "/api/v1/lists/public", "/api/v1/lists/*", "/api/v1/users/*", + "/api/v1/users/*/watchlist", "/api/v1/users/*/reviews").permitAll() + .anyRequest().authenticated()) + .exceptionHandling(handling -> handling + .authenticationEntryPoint(authenticationEntryPoint) + .accessDeniedHandler(accessDeniedHandler)) + .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) + .build(); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=JwtAuthenticationFilterTest` +Expected: PASS, 3 tests green. + +- [ ] **Step 7: Run the full unit suite to confirm nothing else broke** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test` +Expected: PASS - adding Spring Security can make existing `@WebMvcTest`s 401/403 if a test doesn't +authenticate; if any of the four existing controller tests fail here, add +`.with(SecurityMockMvcRequestPostProcessors.anonymous())` or confirm the failing path is already in the +`permitAll()` list above before proceeding - do not weaken the filter chain to make a test pass. + +- [ ] **Step 8: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/infrastructure/security/ +git add src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java +git commit -m "Add JwtAuthenticationFilter, security filter chain, and ProblemDetail error handlers" +``` + +### Task 1.4: `ConflictException`/`ForbiddenException`, `AuthUseCase`, `AuthController` + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/exception/ConflictException.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/exception/ForbiddenException.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/AuthUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/RegisterRequest.java`, `LoginRequest.java`, `TokenPair.java` (records) +- Create: `src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java` + +**Interfaces:** +- Consumes: `UserRepository` (Task 1.1), `JwtService` (Task 1.2), `PasswordEncoder` (Task 1.2) +- Produces: `AuthUseCase.register(RegisterRequest)`, `login(LoginRequest)`, `refresh(String refreshToken)`, + all returning `TokenPair(String accessToken, String refreshToken)`. `ConflictException`/ + `ForbiddenException` (both `RuntimeException`), used by every later task needing 409/403. + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.User; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.infrastructure.security.JwtService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class AuthUseCaseImplTest { + + @Mock + UserRepository userRepository; + @Mock + JwtService jwtService; + + private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + + @Test + void registerCreatesAUserWithRoleUser() { + given(userRepository.existsByEmail("ada@example.com")).willReturn(false); + given(userRepository.insert(any(), any(), any(), any())) + .willReturn(new User(1, "ada@example.com", "hash", "Ada", null, Role.USER, 0)); + given(jwtService.issueAccessToken(1, Set.of(Role.USER))).willReturn("access"); + given(jwtService.issueRefreshToken(1)).willReturn("refresh"); + + var tokens = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder) + .register(new RegisterRequest("ada@example.com", "password123", "Ada")); + + assertThat(tokens.accessToken()).isEqualTo("access"); + assertThat(tokens.refreshToken()).isEqualTo("refresh"); + verify(userRepository).insert("ada@example.com", any(), "Ada", Role.USER); + } + + @Test + void registerThrowsConflictWhenEmailAlreadyExists() { + given(userRepository.existsByEmail("ada@example.com")).willReturn(true); + var useCase = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder); + + assertThatThrownBy(() -> useCase.register(new RegisterRequest("ada@example.com", "pw", "Ada"))) + .isInstanceOf(ConflictException.class); + } + + @Test + void loginIssuesTokensForACorrectPassword() { + String hash = passwordEncoder.encode("password123"); + given(userRepository.findByEmail("ada@example.com")) + .willReturn(Optional.of(new User(1, "ada@example.com", hash, "Ada", null, Role.USER, 0))); + given(jwtService.issueAccessToken(1, Set.of(Role.USER))).willReturn("access"); + given(jwtService.issueRefreshToken(1)).willReturn("refresh"); + + var tokens = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder) + .login(new LoginRequest("ada@example.com", "password123")); + + assertThat(tokens.accessToken()).isEqualTo("access"); + } + + @Test + void loginThrowsForbiddenForAWrongPassword() { + String hash = passwordEncoder.encode("password123"); + given(userRepository.findByEmail("ada@example.com")) + .willReturn(Optional.of(new User(1, "ada@example.com", hash, "Ada", null, Role.USER, 0))); + var useCase = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder); + + assertThatThrownBy(() -> useCase.login(new LoginRequest("ada@example.com", "wrong"))) + .isInstanceOf(com.ludovictemgoua.imdb.domain.exception.ForbiddenException.class); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=AuthUseCaseImplTest` +Expected: FAIL - `AuthUseCaseImpl`/`RegisterRequest`/`LoginRequest`/`ConflictException`/`ForbiddenException` don't exist yet. + +- [ ] **Step 3: Create the two new domain exceptions** + +```java +package com.ludovictemgoua.imdb.domain.exception; + +public class ConflictException extends RuntimeException { + public ConflictException(String message) { + super(message); + } +} +``` + +```java +package com.ludovictemgoua.imdb.domain.exception; + +public class ForbiddenException extends RuntimeException { + public ForbiddenException(String message) { + super(message); + } +} +``` + +- [ ] **Step 4: Add handlers to `ApiExceptionHandler`** + +Add these two methods to the existing class, alongside `handleNotFound`/`handleBadId` (before the +catch-all `handleUnexpected`): + +```java + @ExceptionHandler(com.ludovictemgoua.imdb.domain.exception.ConflictException.class) + public ProblemDetail handleConflict(com.ludovictemgoua.imdb.domain.exception.ConflictException ex) { + log.debug("conflict: {}", ex.getMessage()); + return ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getMessage()); + } + + @ExceptionHandler(com.ludovictemgoua.imdb.domain.exception.ForbiddenException.class) + public ProblemDetail handleForbidden(com.ludovictemgoua.imdb.domain.exception.ForbiddenException ex) { + log.debug("forbidden: {}", ex.getMessage()); + return ProblemDetail.forStatusAndDetail(HttpStatus.FORBIDDEN, ex.getMessage()); + } +``` + +(Use the fully-qualified names as shown, or add proper `import` statements at the top of the file next to +the existing `NotFoundException` import - either is fine, match whichever style is already there.) + +- [ ] **Step 5: Create the request/response records and `AuthUseCase`/`AuthUseCaseImpl`** + +```java +package com.ludovictemgoua.imdb.application; + +public record RegisterRequest(String email, String password, String displayName) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +public record LoginRequest(String email, String password) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +public record TokenPair(String accessToken, String refreshToken) { +} +``` + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.LoginRequest; +import com.ludovictemgoua.imdb.application.RegisterRequest; +import com.ludovictemgoua.imdb.application.TokenPair; + +public interface AuthUseCase { + + TokenPair register(RegisterRequest request); + + TokenPair login(LoginRequest request); + + TokenPair refresh(String refreshToken); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.User; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.infrastructure.security.JwtService; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.util.Set; + +@Service +public class AuthUseCaseImpl implements AuthUseCase { + + private final UserRepository userRepository; + private final JwtService jwtService; + private final PasswordEncoder passwordEncoder; + + public AuthUseCaseImpl(UserRepository userRepository, JwtService jwtService, PasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.jwtService = jwtService; + this.passwordEncoder = passwordEncoder; + } + + @Override + public TokenPair register(RegisterRequest request) { + if (userRepository.existsByEmail(request.email())) { + throw new ConflictException("An account with this email already exists"); + } + String hash = passwordEncoder.encode(request.password()); + User user = userRepository.insert(request.email(), hash, request.displayName(), Role.USER); + return issueTokens(user); + } + + @Override + public TokenPair login(LoginRequest request) { + User user = userRepository.findByEmail(request.email()) + .orElseThrow(() -> new ForbiddenException("Invalid email or password")); + if (!passwordEncoder.matches(request.password(), user.passwordHash())) { + throw new ForbiddenException("Invalid email or password"); + } + return issueTokens(user); + } + + @Override + public TokenPair refresh(String refreshToken) { + var parsed = jwtService.parse(refreshToken) + .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); + User user = userRepository.findById(parsed.userId()) + .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); + return issueTokens(user); + } + + private TokenPair issueTokens(User user) { + String access = jwtService.issueAccessToken(user.id(), Set.of(user.role())); + String refresh = jwtService.issueRefreshToken(user.id()); + return new TokenPair(access, refresh); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=AuthUseCaseImplTest` +Expected: PASS, 4 tests green. + +- [ ] **Step 7: Write the failing controller test** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.LoginRequest; +import com.ludovictemgoua.imdb.application.RegisterRequest; +import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.security.test.context.support.WithAnonymousUser; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(AuthController.class) +@WithAnonymousUser +class AuthControllerTest { + + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @MockitoBean + AuthUseCase authUseCase; + + @Test + void registerReturns201WithTokens() throws Exception { + given(authUseCase.register(new RegisterRequest("ada@example.com", "password123", "Ada"))) + .willReturn(new TokenPair("access", "refresh")); + + mockMvc.perform(post("/api/v1/auth/register") + .contentType("application/json") + .content(objectMapper.writeValueAsString( + new RegisterRequest("ada@example.com", "password123", "Ada")))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.accessToken").value("access")); + } + + @Test + void registerReturns409ForADuplicateEmail() throws Exception { + given(authUseCase.register(new RegisterRequest("ada@example.com", "password123", "Ada"))) + .willThrow(new ConflictException("An account with this email already exists")); + + mockMvc.perform(post("/api/v1/auth/register") + .contentType("application/json") + .content(objectMapper.writeValueAsString( + new RegisterRequest("ada@example.com", "password123", "Ada")))) + .andExpect(status().isConflict()); + } + + @Test + void loginReturnsTokensForValidCredentials() throws Exception { + given(authUseCase.login(new LoginRequest("ada@example.com", "password123"))) + .willReturn(new TokenPair("access", "refresh")); + + mockMvc.perform(post("/api/v1/auth/login") + .contentType("application/json") + .content(objectMapper.writeValueAsString( + new LoginRequest("ada@example.com", "password123")))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.refreshToken").value("refresh")); + } +} +``` + +- [ ] **Step 8: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=AuthControllerTest` +Expected: FAIL - `AuthController` doesn't exist yet. + +- [ ] **Step 9: Create `AuthController`** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.LoginRequest; +import com.ludovictemgoua.imdb.application.RegisterRequest; +import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/auth") +public class AuthController { + + private final AuthUseCase authUseCase; + + public AuthController(AuthUseCase authUseCase) { + this.authUseCase = authUseCase; + } + + @PostMapping("/register") + @ResponseStatus(HttpStatus.CREATED) + public TokenPair register(@Valid @RequestBody RegisterRequest request) { + return authUseCase.register(request); + } + + @PostMapping("/login") + public TokenPair login(@Valid @RequestBody LoginRequest request) { + return authUseCase.login(request); + } + + @PostMapping("/refresh") + public TokenPair refresh(@RequestBody RefreshRequest request) { + return authUseCase.refresh(request.refreshToken()); + } + + public record RefreshRequest(@NotBlank String refreshToken) { + } +} +``` + +Add Bean Validation annotations to `RegisterRequest`/`LoginRequest` (both are plain records used as +`@RequestBody` types, so the annotations go directly on the record components): + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record RegisterRequest( + @NotBlank @Email String email, + @NotBlank @Size(min = 8) String password, + @NotBlank String displayName) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; + +public record LoginRequest(@NotBlank @Email String email, @NotBlank String password) { +} +``` + +- [ ] **Step 10: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=AuthControllerTest` +Expected: PASS, 3 tests green. + +- [ ] **Step 11: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/domain/exception/ConflictException.java src/main/java/com/ludovictemgoua/imdb/domain/exception/ForbiddenException.java src/main/java/com/ludovictemgoua/imdb/presentation/ApiExceptionHandler.java src/main/java/com/ludovictemgoua/imdb/application/ src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java +git commit -m "Add ConflictException/ForbiddenException and the auth register/login/refresh flow" +``` + +### Task 1.5: `BootstrapAdminRunner` + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/BootstrapAdminRunner.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/security/BootstrapAdminRunnerIntegrationTest.java` + +**Interfaces:** +- Consumes: `UserRepository` (Task 1.1), `PasswordEncoder` (Task 1.2) +- Produces: on application startup, exactly one `ADMIN` user exists with the configured bootstrap email + (idempotent - a restart never creates a second one). + +- [ ] **Step 1: Write the failing integration test** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@TestPropertySource(properties = { + "imdb.bootstrap-admin.email=admin@imdb.local", + "imdb.bootstrap-admin.password=change-me-please" +}) +class BootstrapAdminRunnerIntegrationTest { + + @Autowired + UserRepository userRepository; + + @Test + void bootstrapAdminExistsWithAdminRoleAfterStartup() { + var admin = userRepository.findByEmail("admin@imdb.local").orElseThrow(); + + assertThat(admin.role()).isEqualTo(Role.ADMIN); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=BootstrapAdminRunnerIntegrationTest` +Expected: FAIL - no bootstrap admin is created yet. + +- [ ] **Step 3: Add the bootstrap properties to `application.yaml`** + +```yaml +imdb: + bootstrap-admin: + # No defaults for either - a fresh stack with neither set simply never gets an admin account, + # which is the safe failure mode (an operator has to deliberately opt in), rather than shipping + # a guessable default admin password. + email: ${IMDB_BOOTSTRAP_ADMIN_EMAIL:} + password: ${IMDB_BOOTSTRAP_ADMIN_PASSWORD:} +``` + +- [ ] **Step 4: Create `BootstrapAdminRunner`** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +@Component +public class BootstrapAdminRunner implements ApplicationRunner { + + private static final Logger log = LoggerFactory.getLogger(BootstrapAdminRunner.class); + + private final UserRepository userRepository; + private final PasswordEncoder passwordEncoder; + private final String bootstrapEmail; + private final String bootstrapPassword; + + public BootstrapAdminRunner( + UserRepository userRepository, PasswordEncoder passwordEncoder, + @Value("${imdb.bootstrap-admin.email}") String bootstrapEmail, + @Value("${imdb.bootstrap-admin.password}") String bootstrapPassword) { + this.userRepository = userRepository; + this.passwordEncoder = passwordEncoder; + this.bootstrapEmail = bootstrapEmail; + this.bootstrapPassword = bootstrapPassword; + } + + @Override + public void run(ApplicationArguments args) { + if (!StringUtils.hasText(bootstrapEmail) || !StringUtils.hasText(bootstrapPassword)) { + log.debug("no bootstrap admin configured (imdb.bootstrap-admin.email/password unset)"); + return; + } + if (userRepository.existsByEmail(bootstrapEmail)) { + log.debug("bootstrap admin already exists: email={}", bootstrapEmail); + return; + } + userRepository.insert(bootstrapEmail, passwordEncoder.encode(bootstrapPassword), "Admin", Role.ADMIN); + log.info("bootstrap admin created: email={}", bootstrapEmail); + } +} +``` + +- [ ] **Step 5: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=BootstrapAdminRunnerIntegrationTest` +Expected: PASS. + +- [ ] **Step 6: Add the bootstrap env vars to `docker-compose.yaml`'s `imdb-service` environment block** + +```yaml + IMDB_BOOTSTRAP_ADMIN_EMAIL: "admin@imdb.local" + IMDB_BOOTSTRAP_ADMIN_PASSWORD: "change-me-please" + JWT_SECRET: "local-dev-only-secret-change-in-real-deployments-32bytes+" +``` + +- [ ] **Step 7: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/infrastructure/security/BootstrapAdminRunner.java src/test/java/com/ludovictemgoua/imdb/infrastructure/security/BootstrapAdminRunnerIntegrationTest.java src/main/resources/application.yaml docker-compose.yaml +git commit -m "Add BootstrapAdminRunner so the ADMIN role is reachable on a fresh stack" +``` + +### Task 1.6: `CurrentUser` helper, `UserUseCase`, `UserController` + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/CurrentUser.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/UserProfile.java`, `PublicUserProfile.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/UpdateProfileRequest.java`, `RoleRequest.java` (records) +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/security/CurrentUserTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/UserControllerTest.java` + +**Interfaces:** +- Consumes: `UserRepository` (Task 1.1 - `findById`, `updateProfile`, `updateRole`, `softDelete`, `findAll` + all already exist from that task) +- Produces: `CurrentUser.idOf(Authentication) -> Optional`, `requireId(Authentication) -> int` - + reused by every controller in Phases 6-8 needing "who is calling, if anyone" (this plan originally + placed this helper in Phase 6; it's built here instead since `UserController` needs it first + chronologically - Phase 6 Task 6.1 below has been corrected to consume it rather than create it). + `UserProfile(int id, String email, String displayName, String bio, Role role, int version)` (excludes + `passwordHash` - the API must never echo it back). `PublicUserProfile(int id, String displayName)`. + `GET/PUT/DELETE /api/v1/users/me`, `GET /api/v1/users/{userId}`, `GET /api/v1/users` (admin), + `PUT /api/v1/users/{userId}/role` (admin), `DELETE /api/v1/users/{userId}` (admin) - the remaining seven + endpoints from `docs/crud-expansion-design.md` §4.1 not already covered by `AuthController` (Task 1.4). + +- [ ] **Step 1: Write the failing `CurrentUser` unit test** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import org.junit.jupiter.api.Test; +import org.springframework.security.authentication.TestingAuthenticationToken; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +class CurrentUserTest { + + @Test + void idOfReturnsEmptyForNullAuthentication() { + assertThat(CurrentUser.idOf(null)).isEmpty(); + } + + @Test + void idOfReturnsTheParsedUserIdForARealToken() { + var auth = new TestingAuthenticationToken("42", null); + + assertThat(CurrentUser.idOf(auth)).contains(42); + } + + @Test + void idOfReturnsEmptyForAnonymousAuthentication() { + var auth = new TestingAuthenticationToken("anonymousUser", null); + + assertThat(CurrentUser.idOf(auth)).isEmpty(); + } + + @Test + void requireIdThrowsWhenNoUserIsAuthenticated() { + assertThatThrownBy(() -> CurrentUser.requireId(null)).isInstanceOf(IllegalStateException.class); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=CurrentUserTest` +Expected: FAIL - `CurrentUser` doesn't exist yet. + +- [ ] **Step 3: Create `CurrentUser`** + +```java +package com.ludovictemgoua.imdb.infrastructure.security; + +import org.springframework.security.core.Authentication; + +import java.util.Optional; + +public final class CurrentUser { + + private CurrentUser() { + } + + public static Optional idOf(Authentication authentication) { + if (authentication == null) { + return Optional.empty(); + } + try { + return Optional.of(Integer.parseInt(authentication.getName())); + } catch (NumberFormatException e) { + return Optional.empty(); + } + } + + public static int requireId(Authentication authentication) { + return idOf(authentication) + .orElseThrow(() -> new IllegalStateException("No authenticated user in this request")); + } +} +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=CurrentUserTest` +Expected: PASS, 4 tests green. + +- [ ] **Step 5: Write the failing `UserUseCaseImpl` unit test** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.User; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class UserUseCaseImplTest { + + @Mock + UserRepository userRepository; + + @Test + void getOwnProfileExcludesThePasswordHash() { + given(userRepository.findById(7)) + .willReturn(Optional.of(new User(7, "a@example.com", "secret-hash", "Ada", "bio", Role.USER, 0))); + + var profile = new UserUseCaseImpl(userRepository).getOwnProfile(7); + + assertThat(profile.email()).isEqualTo("a@example.com"); + assertThat(profile.displayName()).isEqualTo("Ada"); + } + + @Test + void getOwnProfileThrowsNotFoundForAnUnknownId() { + given(userRepository.findById(999)).willReturn(Optional.empty()); + + assertThatThrownBy(() -> new UserUseCaseImpl(userRepository).getOwnProfile(999)) + .isInstanceOf(NotFoundException.class); + } + + @Test + void updateOwnProfileThrowsConflictOnVersionMismatch() { + given(userRepository.updateProfile(7, "New Name", "New Bio", 0)).willReturn(WriteResult.VERSION_CONFLICT); + var useCase = new UserUseCaseImpl(userRepository); + + assertThatThrownBy(() -> useCase.updateOwnProfile(7, new UpdateProfileRequest("New Name", "New Bio", 0))) + .isInstanceOf(ConflictException.class); + } + + @Test + void updateRoleThrowsNotFoundForAnUnknownUser() { + given(userRepository.findById(999)).willReturn(Optional.empty()); + var useCase = new UserUseCaseImpl(userRepository); + + assertThatThrownBy(() -> useCase.updateRole(999, Role.ADMIN)).isInstanceOf(NotFoundException.class); + } +} +``` + +- [ ] **Step 6: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=UserUseCaseImplTest` +Expected: FAIL - `UserUseCaseImpl`/`UpdateProfileRequest` don't exist yet. + +- [ ] **Step 7: Create the domain/request records and `UserUseCase`/`Impl`** + +```java +package com.ludovictemgoua.imdb.domain.model; + +public record UserProfile(int id, String email, String displayName, String bio, Role role, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +public record PublicUserProfile(int id, String displayName) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +public record UpdateProfileRequest(@NotBlank String displayName, String bio, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.Role; +import jakarta.validation.constraints.NotNull; + +public record RoleRequest(@NotNull Role role) { +} +``` + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.UpdateProfileRequest; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.UserProfile; + +public interface UserUseCase { + + UserProfile getOwnProfile(int userId); + + UserProfile updateOwnProfile(int userId, UpdateProfileRequest request); + + void deleteOwnAccount(int userId); + + PublicUserProfile getPublicProfile(int userId); + + PagedResult listAll(int page, int size); + + void updateRole(int userId, Role role); + + void deleteAccount(int userId); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.UserUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.User; +import com.ludovictemgoua.imdb.domain.model.UserProfile; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.springframework.stereotype.Service; + +@Service +public class UserUseCaseImpl implements UserUseCase { + + private final UserRepository userRepository; + + public UserUseCaseImpl(UserRepository userRepository) { + this.userRepository = userRepository; + } + + @Override + public UserProfile getOwnProfile(int userId) { + return toProfile(findOrThrow(userId)); + } + + @Override + public UserProfile updateOwnProfile(int userId, UpdateProfileRequest request) { + WriteResult result = userRepository.updateProfile(userId, request.displayName(), request.bio(), request.version()); + switch (result) { + case NOT_FOUND -> throw new NotFoundException("No user with id " + userId); + case VERSION_CONFLICT -> throw new ConflictException("Your profile was modified concurrently - refresh and retry"); + case SUCCESS -> { } + } + return getOwnProfile(userId); + } + + @Override + public void deleteOwnAccount(int userId) { + userRepository.softDelete(userId); + } + + @Override + public PublicUserProfile getPublicProfile(int userId) { + User user = findOrThrow(userId); + return new PublicUserProfile(user.id(), user.displayName()); + } + + @Override + public PagedResult listAll(int page, int size) { + PagedResult users = userRepository.findAll(page, size); + return new PagedResult<>(users.content().stream().map(UserUseCaseImpl::toProfile).toList(), + users.totalElements(), users.page(), users.size()); + } + + @Override + public void updateRole(int userId, Role role) { + findOrThrow(userId); + userRepository.updateRole(userId, role); + } + + @Override + public void deleteAccount(int userId) { + findOrThrow(userId); + userRepository.softDelete(userId); + } + + private User findOrThrow(int userId) { + return userRepository.findById(userId).orElseThrow(() -> new NotFoundException("No user with id " + userId)); + } + + private static UserProfile toProfile(User user) { + return new UserProfile(user.id(), user.email(), user.displayName(), user.bio(), user.role(), user.version()); + } +} +``` + +- [ ] **Step 8: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=UserUseCaseImplTest` +Expected: PASS, 4 tests green. + +- [ ] **Step 9: Write the failing `UserController` test** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.UserUseCase; +import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.UserProfile; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(UserController.class) +class UserControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + UserUseCase userUseCase; + + @Test + void getOwnRequiresAuthentication() throws Exception { + mockMvc.perform(get("/api/v1/users/me")).andExpect(status().isUnauthorized()); + } + + @Test + void getOwnReturnsTheProfileForAnAuthenticatedUser() throws Exception { + given(userUseCase.getOwnProfile(7)) + .willReturn(new UserProfile(7, "a@example.com", "Ada", "bio", Role.USER, 0)); + + mockMvc.perform(get("/api/v1/users/me").with(SecurityMockMvcRequestPostProcessors.user("7").roles("USER"))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.displayName").value("Ada")); + } + + @Test + void getPublicProfileIsAccessibleAnonymously() throws Exception { + given(userUseCase.getPublicProfile(7)).willReturn(new PublicUserProfile(7, "Ada")); + + mockMvc.perform(get("/api/v1/users/7")).andExpect(status().isOk()); + } + + @Test + void deleteAccountRequiresAdminRole() throws Exception { + mockMvc.perform(delete("/api/v1/users/7") + .with(SecurityMockMvcRequestPostProcessors.user("1").roles("USER"))) + .andExpect(status().isForbidden()); + } +} +``` + +- [ ] **Step 10: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=UserControllerTest` +Expected: FAIL - `UserController` doesn't exist yet. + +- [ ] **Step 11: Create `UserController`** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.RoleRequest; +import com.ludovictemgoua.imdb.application.UpdateProfileRequest; +import com.ludovictemgoua.imdb.application.contracts.UserUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; +import com.ludovictemgoua.imdb.domain.model.UserProfile; +import com.ludovictemgoua.imdb.infrastructure.security.CurrentUser; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.http.HttpStatus; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Validated +public class UserController { + + private final UserUseCase userUseCase; + + public UserController(UserUseCase userUseCase) { + this.userUseCase = userUseCase; + } + + @GetMapping("/api/v1/users/me") + public UserProfile getOwn(Authentication authentication) { + return userUseCase.getOwnProfile(CurrentUser.requireId(authentication)); + } + + @PutMapping("/api/v1/users/me") + public UserProfile updateOwn(Authentication authentication, @Valid @RequestBody UpdateProfileRequest request) { + return userUseCase.updateOwnProfile(CurrentUser.requireId(authentication), request); + } + + @DeleteMapping("/api/v1/users/me") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteOwn(Authentication authentication) { + userUseCase.deleteOwnAccount(CurrentUser.requireId(authentication)); + } + + @GetMapping("/api/v1/users/{userId}") + public PublicUserProfile getPublicProfile(@PathVariable int userId) { + return userUseCase.getPublicProfile(userId); + } + + @GetMapping("/api/v1/users") + @PreAuthorize("hasRole('ADMIN')") + public PagedResult listAll( + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return userUseCase.listAll(page, size); + } + + @PutMapping("/api/v1/users/{userId}/role") + @PreAuthorize("hasRole('ADMIN')") + public void updateRole(@PathVariable int userId, @Valid @RequestBody RoleRequest request) { + userUseCase.updateRole(userId, request.role()); + } + + @DeleteMapping("/api/v1/users/{userId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + @PreAuthorize("hasRole('ADMIN')") + public void deleteAccount(@PathVariable int userId) { + userUseCase.deleteAccount(userId); + } +} +``` + +`GET /api/v1/users/{userId}` is already in the security filter chain's `permitAll()` GET list +(`"/api/v1/users/*"`, Task 1.3) - confirm `GET /api/v1/users/me` does **not** incorrectly match that same +wildcard the way `/api/v1/lists/me` did (Task 8.2, Step 7); if it does, apply the identical fix: declare +`.requestMatchers(HttpMethod.GET, "/api/v1/users/me").authenticated()` before the broader permit rule. + +- [ ] **Step 12: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=UserControllerTest` +Expected: PASS, 4 tests green. + +- [ ] **Step 13: Run the full unit and integration suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 14: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/infrastructure/security/CurrentUser.java src/main/java/com/ludovictemgoua/imdb/domain/model/UserProfile.java src/main/java/com/ludovictemgoua/imdb/domain/model/PublicUserProfile.java src/main/java/com/ludovictemgoua/imdb/application/UpdateProfileRequest.java src/main/java/com/ludovictemgoua/imdb/application/RoleRequest.java src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java src/test/java/com/ludovictemgoua/imdb/infrastructure/security/CurrentUserTest.java src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/UserControllerTest.java +git commit -m "Add UserUseCase/UserController: profile management and admin user management" +``` + +**Phase 1 checkpoint**: run the full suite (`mvn test` then `mvn failsafe:integration-test failsafe:verify`) +before moving to Phase 2 - registration, login, refresh, profile management, admin user management, and +the bootstrap admin are all real and tested at this point, independent of everything that follows. + +--- + +## Phase 2: Core Entity Versioning & Soft Delete + +### Task 2.1: Admin-created ID sequences (`V6`) + +**Files:** +- Create: `src/main/resources/db/migration/V6__admin_id_sequences.sql` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/AdminIdSequencesIntegrationTest.java` + +**Interfaces:** +- Produces: `title_id_seq`/`person_id_seq` Postgres sequences, usable via `nextval('title_id_seq')` / + `nextval('person_id_seq')` from any later JDBC insert (Phase 3/4). + +- [ ] **Step 1: Write the failing integration test** + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.jdbc.Sql; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Sql("/fixtures/fixture-data.sql") +class AdminIdSequencesIntegrationTest { + + @Autowired + JdbcTemplate jdbc; + + @Test + void titleIdSequenceStartsAboveTheHighestSeededTconst() { + Integer maxSeeded = jdbc.queryForObject("SELECT max(tconst) FROM title_basics", Integer.class); + Integer nextVal = jdbc.queryForObject("SELECT nextval('title_id_seq')", Integer.class); + + assertThat(nextVal).isGreaterThan(maxSeeded); + } + + @Test + void personIdSequenceStartsAboveTheHighestSeededNconst() { + Integer maxSeeded = jdbc.queryForObject("SELECT max(nconst) FROM name_basics", Integer.class); + Integer nextVal = jdbc.queryForObject("SELECT nextval('person_id_seq')", Integer.class); + + assertThat(nextVal).isGreaterThan(maxSeeded); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=AdminIdSequencesIntegrationTest` +Expected: FAIL - `title_id_seq`/`person_id_seq` don't exist. + +- [ ] **Step 3: Create the migration** + +```sql +-- Admin-created titles/people (Phase 3/4) need ids that can never collide with the seeded, already- +-- densely-allocated tconst/nconst range from abanda/imdb-postgresql. Starting each sequence one past +-- the current max is done in a DO block, not a plain CREATE SEQUENCE START WITH literal, since the +-- actual max differs across environments (the full dataset here vs. the small fixture Testcontainers +-- and the e2e stack seed) - this migration must work correctly against all three. +DO $$ +DECLARE + next_title_id BIGINT; + next_person_id BIGINT; +BEGIN + SELECT COALESCE(max(tconst), 0) + 1 INTO next_title_id FROM title_basics; + SELECT COALESCE(max(nconst), 0) + 1 INTO next_person_id FROM name_basics; + + EXECUTE format('CREATE SEQUENCE title_id_seq START WITH %s', next_title_id); + EXECUTE format('CREATE SEQUENCE person_id_seq START WITH %s', next_person_id); +END $$; +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=AdminIdSequencesIntegrationTest` +Expected: PASS. + +- [ ] **Step 5: Commit** + +```bash +git add src/main/resources/db/migration/V6__admin_id_sequences.sql src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/AdminIdSequencesIntegrationTest.java +git commit -m "Add title_id_seq/person_id_seq for admin-created rows (V6)" +``` + +### Task 2.2: `version`/`deleted_at` on core tables, soft-delete filtering in existing read queries + +**Files:** +- Create: `src/main/resources/db/migration/V7__core_entity_version_and_soft_delete.sql` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java` +- Modify: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java` +- Modify: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java` + +**Interfaces:** +- Produces: `version`/`deleted_at` columns on `title_basics`, `name_basics`, `title_ratings`, + `title_principals`, `title_crew`. A soft-deleted title/person is excluded from search, detail, + top-rated, and person-name-lookup-by-search - but NOT from `findAnyCommonTitle` enrichment being able + to reference it if it was already the connecting title before deletion, and NOT from + `findNameById`/`findNamesByIds` (existing cast/crew references still render a name rather than + breaking). Admin repository insert/update methods added in Phase 3/4 read/write these two columns + directly; nothing in this task writes to them yet (no writer exists before Phase 3). + +**Known limitation, stated here rather than solved**: `co_star_edges` (the six-degrees materialized view) +is built once from `title_principals`/`title_basics` and refreshed manually (LLD §3.3, PDD §11's open +question on refresh cadence) - a soft-deleted person/title can still appear in a six-degrees path until +the next refresh. This plan does not change that refresh cadence; it's an existing, already-documented +trade-off, not a new one introduced here. + +- [ ] **Step 1: Write the failing test additions** + +Add to `JdbcTitleRepositoryIntegrationTest`: + +```java + @Test + void findCoreExcludesASoftDeletedTitle() { + jdbc.update("UPDATE title_basics SET deleted_at = now() WHERE tconst = 100", Map.of()); + + assertThat(repository.findCore(100)).isEmpty(); + } + + @Test + void searchExcludesASoftDeletedTitle() { + jdbc.update("UPDATE title_basics SET deleted_at = now() WHERE tconst = 100", Map.of()); + + assertThat(repository.search("Few Good Men", 0, 20).content()).extracting("id").doesNotContain("tt0000100"); + } +``` + +(This requires autowiring a plain `JdbcTemplate jdbc` field in the test class alongside the existing +`JdbcTitleRepository repository` field, and `import org.springframework.jdbc.core.JdbcTemplate;` / +`import java.util.Map;` at the top.) + +Add to `JdbcPersonRepositoryIntegrationTest` (create this file if it doesn't already exist, following the +exact structure of `JdbcTitleRepositoryIntegrationTest` - `@Import(TestcontainersConfiguration.class) +@SpringBootTest @Transactional @Sql("/fixtures/fixture-data.sql")`, autowiring `JdbcPersonRepository`): + +```java + @Test + void findByNameExcludesASoftDeletedPerson() { + jdbc.update("UPDATE name_basics SET deleted_at = now() WHERE nconst = 1", Map.of()); + + assertThat(repository.findByName("Kevin Bacon")).isEmpty(); + } +``` + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcTitleRepositoryIntegrationTest,JdbcPersonRepositoryIntegrationTest` +Expected: FAIL - `deleted_at` column doesn't exist yet, so the `UPDATE` in each test itself errors. + +- [ ] **Step 3: Create the migration** + +```sql +ALTER TABLE title_basics ADD COLUMN version INTEGER NOT NULL DEFAULT 0, ADD COLUMN deleted_at TIMESTAMPTZ; +ALTER TABLE name_basics ADD COLUMN version INTEGER NOT NULL DEFAULT 0, ADD COLUMN deleted_at TIMESTAMPTZ; +ALTER TABLE title_ratings ADD COLUMN version INTEGER NOT NULL DEFAULT 0, ADD COLUMN deleted_at TIMESTAMPTZ; +ALTER TABLE title_principals ADD COLUMN version INTEGER NOT NULL DEFAULT 0, ADD COLUMN deleted_at TIMESTAMPTZ; +ALTER TABLE title_crew ADD COLUMN version INTEGER NOT NULL DEFAULT 0, ADD COLUMN deleted_at TIMESTAMPTZ; +``` + +- [ ] **Step 4: Add `AND deleted_at IS NULL` to the discovery queries in `JdbcTitleRepository`** + +In `search(...)`, both `dataSql` and `countSql` gain the filter: + +```java + String dataSql = """ + SELECT tconst, primary_title, original_title, title_type, start_year, end_year + FROM title_basics + WHERE (primary_title % :query OR original_title % :query) AND deleted_at IS NULL + ORDER BY similarity(primary_title, :query) DESC + LIMIT :limit OFFSET :offset + """; + String countSql = """ + SELECT count(*) FROM title_basics + WHERE (primary_title % :query OR original_title % :query) AND deleted_at IS NULL + """; +``` + +In `findCore(...)`: + +```java + String sql = """ + SELECT tb.tconst, tb.primary_title, tb.original_title, tb.title_type, + tb.start_year, tb.end_year, tb.runtime_minutes, tb.genres, + tr.average_rating, tr.num_votes + FROM title_basics tb + LEFT JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.tconst = :tconst AND tb.deleted_at IS NULL + """; +``` + +In `findTopRated(...)`, add `AND tb.deleted_at IS NULL` to the `pool` CTE's `WHERE` clause: + +```java + String sql = """ + WITH pool AS ( + SELECT tb.tconst, tb.primary_title, tb.start_year, tr.average_rating, tr.num_votes + FROM title_basics tb + JOIN title_ratings tr ON tr.tconst = tb.tconst + WHERE tb.title_type = 'movie' + AND genres_as_text(tb.genres) @> ARRAY[:genre]::text[] + AND tr.num_votes >= :minVotes + AND tb.deleted_at IS NULL + ), + stats AS (SELECT AVG(average_rating) AS mean_rating FROM pool) + SELECT p.tconst, p.primary_title, p.start_year, p.average_rating, p.num_votes, + (p.num_votes::numeric / (p.num_votes + :minVotes)) * p.average_rating + + (:minVotes::numeric / (p.num_votes + :minVotes)) * s.mean_rating AS weighted_rating + FROM pool p CROSS JOIN stats s + ORDER BY weighted_rating DESC + LIMIT :limit + """; +``` + +`findDirectors`/`findWriters`/`findTopCast`/`countCast`/`findAnyCommonTitle` are deliberately left +unchanged - they render or enrich *existing* references (a title/person that might have since been +soft-deleted but was real cast/crew at the time), matching the design decision that soft-deleting a title +doesn't retroactively break historical references to it (`docs/crud-expansion-design.md` §6.4). + +- [ ] **Step 5: Add `AND deleted_at IS NULL` to `findByName` in `JdbcPersonRepository`** + +```java + String sql = """ + SELECT nconst, primary_name, birth_year, known_for_titles + FROM name_basics + WHERE primary_name % :name AND deleted_at IS NULL + ORDER BY similarity(primary_name, :name) DESC + LIMIT 10 + """; +``` + +`findNameById`/`findNamesByIds` are left unchanged for the same historical-reference reason as above. + +- [ ] **Step 6: Run the tests to verify they pass** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcTitleRepositoryIntegrationTest,JdbcPersonRepositoryIntegrationTest` +Expected: PASS. + +- [ ] **Step 7: Run the full suite to confirm nothing regressed** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS - all existing tests remain green; the new `version`/`deleted_at` columns are additive +(`NOT NULL DEFAULT 0` / nullable) so no existing insert statement anywhere in the codebase needs to +change. + +- [ ] **Step 8: Commit** + +```bash +git add src/main/resources/db/migration/V7__core_entity_version_and_soft_delete.sql src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java +git commit -m "Add version/deleted_at to core tables; filter soft-deleted rows from discovery queries" +``` + +**Phase 2 checkpoint**: core tables can now support versioned updates and soft deletes, but nothing writes +to them yet - Phase 3 adds the first writer. + +--- + +## Phase 3: Admin CRUD - Titles + +### Task 3.1: `TitleRepository` write methods (insert/update/delete/crew/rating) + +**Files:** +- Modify: `src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java` +- Modify: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java` + +**Interfaces:** +- Produces: `TitleRepository.insertTitle(...) -> TitleCore`, `updateTitle(int tconst, ..., int expectedVersion) -> WriteResult`, `softDeleteTitle(int tconst) -> WriteResult`, `upsertCrew(int tconst, List directorIds, List writerIds) -> WriteResult`, `upsertRating(int tconst, double averageRating, int numVotes) -> WriteResult`, `deleteRating(int tconst) -> WriteResult`. `TitleCore.version()` - add a `version` component to the existing `TitleCore` record (Task's Step 1 shows the exact new record shape; every caller of the constructor - `mapCore` in this file, and the record's one other reader in `TitleDetailUseCaseImpl` - is updated in this same task). + +- [ ] **Step 1: Write the failing integration tests** + +Add to `JdbcTitleRepositoryIntegrationTest`: + +```java + @Test + void insertTitleCreatesARowWithVersionZero() { + var created = repository.insertTitle("New Movie", "New Movie", "movie", 2024, null, 120, List.of("Drama")); + + assertThat(created.version()).isEqualTo(0); + assertThat(repository.findCore(ImdbIds.parseTitleId(created.id())).orElseThrow().primaryTitle()) + .isEqualTo("New Movie"); + } + + @Test + void insertedTitleIdIsAboveTheSeededRange() { + var created = repository.insertTitle("Another Movie", "Another Movie", "movie", 2024, null, 90, List.of()); + + assertThat(ImdbIds.parseTitleId(created.id())).isGreaterThan(200); + } + + @Test + void updateTitleBumpsVersionAndPersists() { + var created = repository.insertTitle("Old Name", "Old Name", "movie", 2020, null, 100, List.of("Drama")); + int tconst = ImdbIds.parseTitleId(created.id()); + + var result = repository.updateTitle( + tconst, "New Name", "New Name", "movie", 2021, null, 110, List.of("Comedy"), created.version()); + + assertThat(result).isEqualTo(com.ludovictemgoua.imdb.domain.repository.WriteResult.SUCCESS); + var updated = repository.findCore(tconst).orElseThrow(); + assertThat(updated.primaryTitle()).isEqualTo("New Name"); + assertThat(updated.version()).isEqualTo(1); + } + + @Test + void updateTitleReturnsVersionConflictOnStaleVersion() { + var created = repository.insertTitle("Stale Test", "Stale Test", "movie", 2020, null, 100, List.of()); + int tconst = ImdbIds.parseTitleId(created.id()); + + var result = repository.updateTitle( + tconst, "New Name", "New Name", "movie", 2021, null, 110, List.of(), created.version() + 1); + + assertThat(result).isEqualTo(com.ludovictemgoua.imdb.domain.repository.WriteResult.VERSION_CONFLICT); + } + + @Test + void softDeleteTitleExcludesItFromFindCore() { + var created = repository.insertTitle("Delete Me", "Delete Me", "movie", 2020, null, 100, List.of()); + int tconst = ImdbIds.parseTitleId(created.id()); + + repository.softDeleteTitle(tconst); + + assertThat(repository.findCore(tconst)).isEmpty(); + } + + @Test + void upsertRatingThenDeleteRatingRoundTrips() { + var created = repository.insertTitle("Rating Test", "Rating Test", "movie", 2020, null, 100, List.of()); + int tconst = ImdbIds.parseTitleId(created.id()); + + repository.upsertRating(tconst, 7.5, 1000); + assertThat(repository.findCore(tconst).orElseThrow().averageRating()).isEqualTo(7.5); + + repository.deleteRating(tconst); + assertThat(repository.findCore(tconst).orElseThrow().averageRating()).isNull(); + } +``` + +Add `import com.ludovictemgoua.imdb.utils.ImdbIds;` and `import java.util.List;` to the test's imports if not +already present (`List` already is, via the existing `findTopRated` test). + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcTitleRepositoryIntegrationTest` +Expected: FAIL - the new repository methods don't exist yet. + +- [ ] **Step 3: Add `version` to `TitleCore` and update its two existing usages** + +`TitleCore` currently ends in `Integer runtimeMinutes, List genres, Double averageRating, Integer numVotes)` (check the actual file for its exact full signature) - add `, int version` as the final component. Update `JdbcTitleRepository.mapCore` to read `rs.getInt("version")` as the last constructor argument, and update `TitleDetailUseCaseImpl.getDetail` - it destructures `core` into a `TitleDetail`; `TitleDetail` itself does **not** need a `version` field (it's a read response, not a write target), so `TitleDetailUseCaseImpl` needs no change beyond compiling against the new `TitleCore` shape (it doesn't reference `core.version()`). + +- [ ] **Step 4: Add the new methods to `TitleRepository`** + +```java + TitleCore insertTitle(String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, List genres); + + WriteResult updateTitle(int tconst, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, int expectedVersion); + + WriteResult softDeleteTitle(int tconst); + + WriteResult upsertCrew(int tconst, List directorIds, List writerIds); + + WriteResult upsertRating(int tconst, double averageRating, int numVotes); + + WriteResult deleteRating(int tconst); +``` + +(Add `import com.ludovictemgoua.imdb.domain.repository.WriteResult;` is unnecessary since `WriteResult` is +already in this same package; add `import java.util.List;` if not already present.) + +- [ ] **Step 5: Implement the new methods in `JdbcTitleRepository`** + +```java + @Override + public TitleCore insertTitle(String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, List genres) { + String sql = """ + INSERT INTO title_basics (tconst, primary_title, original_title, title_type, + start_year, end_year, runtime_minutes, genres) + VALUES (nextval('title_id_seq'), :primaryTitle, :originalTitle, :titleType, + :startYear, :endYear, :runtimeMinutes, :genres) + RETURNING tconst + """; + var params = new MapSqlParameterSource() + .addValue("primaryTitle", primaryTitle).addValue("originalTitle", originalTitle) + .addValue("titleType", titleType).addValue("startYear", startYear) + .addValue("endYear", endYear).addValue("runtimeMinutes", runtimeMinutes) + .addValue("genres", genres.toArray(new String[0]), java.sql.Types.ARRAY, "text"); + int tconst = jdbc.queryForObject(sql, params, Integer.class); + return findCore(tconst).orElseThrow(); + } + + @Override + public WriteResult updateTitle(int tconst, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, int expectedVersion) { + if (findCore(tconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + String sql = """ + UPDATE title_basics + SET primary_title = :primaryTitle, original_title = :originalTitle, title_type = :titleType, + start_year = :startYear, end_year = :endYear, runtime_minutes = :runtimeMinutes, + genres = :genres, version = version + 1 + WHERE tconst = :tconst AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("primaryTitle", primaryTitle).addValue("originalTitle", originalTitle) + .addValue("titleType", titleType).addValue("startYear", startYear) + .addValue("endYear", endYear).addValue("runtimeMinutes", runtimeMinutes) + .addValue("genres", genres.toArray(new String[0]), java.sql.Types.ARRAY, "text") + .addValue("tconst", tconst).addValue("expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public WriteResult softDeleteTitle(int tconst) { + if (findCore(tconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + jdbc.update("UPDATE title_basics SET deleted_at = now() WHERE tconst = :tconst", Map.of("tconst", tconst)); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult upsertCrew(int tconst, List directorIds, List writerIds) { + if (findCore(tconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + String sql = """ + INSERT INTO title_crew (tconst, directors, writers) + VALUES (:tconst, :directors, :writers) + ON CONFLICT (tconst) DO UPDATE SET directors = :directors, writers = :writers, version = title_crew.version + 1 + """; + var params = new MapSqlParameterSource() + .addValue("tconst", tconst) + .addValue("directors", directorIds.toArray(new Integer[0]), java.sql.Types.ARRAY, "integer") + .addValue("writers", writerIds.toArray(new Integer[0]), java.sql.Types.ARRAY, "integer"); + jdbc.update(sql, params); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult upsertRating(int tconst, double averageRating, int numVotes) { + if (findCore(tconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + String sql = """ + INSERT INTO title_ratings (tconst, average_rating, num_votes) + VALUES (:tconst, :averageRating, :numVotes) + ON CONFLICT (tconst) DO UPDATE SET average_rating = :averageRating, num_votes = :numVotes, + version = title_ratings.version + 1 + """; + var params = new MapSqlParameterSource() + .addValue("tconst", tconst).addValue("averageRating", averageRating).addValue("numVotes", numVotes); + jdbc.update(sql, params); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult deleteRating(int tconst) { + int updated = jdbc.update("UPDATE title_ratings SET deleted_at = now() WHERE tconst = :tconst AND deleted_at IS NULL", + Map.of("tconst", tconst)); + return updated == 0 ? WriteResult.NOT_FOUND : WriteResult.SUCCESS; + } +``` + +`upsertRating`/`deleteRating` require `findCore`'s `LEFT JOIN title_ratings` to also filter +`(tr.deleted_at IS NULL OR tr.deleted_at IS NULL)` - add `AND (tr.tconst IS NULL OR tr.deleted_at IS NULL)` +to `findCore`'s `WHERE` clause so a deleted rating correctly shows as no rating rather than a stale one: + +```java + WHERE tb.tconst = :tconst AND tb.deleted_at IS NULL + AND (tr.tconst IS NULL OR tr.deleted_at IS NULL) +``` + +`title_ratings`/`title_crew` need a unique constraint on `tconst` for the `ON CONFLICT` clauses above to +work - add this to `V7__core_entity_version_and_soft_delete.sql` from Task 2.2 (both tables already have +`tconst` as their primary key per the `V0` base schema, so `ON CONFLICT (tconst)` already targets a real +unique constraint with no migration change needed - confirm this against `V0__base_schema.sql` before +writing Step 5's SQL; if either table's PK is composite instead, change `ON CONFLICT (tconst)` to that +table's actual primary key column list). + +- [ ] **Step 6: Run the tests to verify they pass** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcTitleRepositoryIntegrationTest` +Expected: PASS, all 6 new tests plus the existing ones green. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java src/main/java/com/ludovictemgoua/imdb/domain/model/TitleCore.java src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java +git commit -m "Add TitleRepository write methods: insert/update/soft-delete/crew/rating" +``` + +### Task 3.2: `TitleAdminUseCase`, cache-evicting decorator, `TitleController` admin endpoints + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleAdminUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/CreateTitleRequest.java`, `UpdateTitleRequest.java`, `PatchTitleRequest.java`, `CrewRequest.java`, `RatingRequest.java` (records) +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java` (extend) + +**Interfaces:** +- Consumes: `TitleRepository` write methods (Task 3.1), `WriteResult` (Task 1.1) +- Produces: `TitleAdminUseCase` with `create`, `update`, `patch`, `delete`, `upsertCrew`, `upsertRating`, + `deleteRating` - every admin write endpoint in `docs/crud-expansion-design.md` §5.1/§5.3 routes through + this one interface (title-scoped admin operations grouped by domain cohesion, per §8). + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.TitleCore; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class TitleAdminUseCaseImplTest { + + @Mock + TitleRepository titleRepository; + + @Test + void createDelegatesToInsertTitle() { + var created = new TitleCore("tt0000300", "New", "New", "movie", 2024, null, 100, List.of(), null, null, 0); + given(titleRepository.insertTitle("New", "New", "movie", 2024, null, 100, List.of())) + .willReturn(created); + + var result = new TitleAdminUseCaseImpl(titleRepository) + .create(new CreateTitleRequest("New", "New", "movie", 2024, null, 100, List.of())); + + assertThat(result.id()).isEqualTo("tt0000300"); + } + + @Test + void updateThrowsConflictOnVersionMismatch() { + given(titleRepository.updateTitle(300, "New", "New", "movie", 2024, null, 100, List.of(), 0)) + .willReturn(WriteResult.VERSION_CONFLICT); + var useCase = new TitleAdminUseCaseImpl(titleRepository); + + assertThatThrownBy(() -> useCase.update("tt0000300", + new UpdateTitleRequest("New", "New", "movie", 2024, null, 100, List.of(), 0))) + .isInstanceOf(ConflictException.class); + } + + @Test + void updateThrowsNotFoundWhenTheTitleDoesNotExist() { + given(titleRepository.updateTitle(300, "New", "New", "movie", 2024, null, 100, List.of(), 0)) + .willReturn(WriteResult.NOT_FOUND); + var useCase = new TitleAdminUseCaseImpl(titleRepository); + + assertThatThrownBy(() -> useCase.update("tt0000300", + new UpdateTitleRequest("New", "New", "movie", 2024, null, 100, List.of(), 0))) + .isInstanceOf(NotFoundException.class); + } + + @Test + void deleteThrowsNotFoundWhenTheTitleDoesNotExist() { + given(titleRepository.softDeleteTitle(300)).willReturn(WriteResult.NOT_FOUND); + var useCase = new TitleAdminUseCaseImpl(titleRepository); + + assertThatThrownBy(() -> useCase.delete("tt0000300")).isInstanceOf(NotFoundException.class); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=TitleAdminUseCaseImplTest` +Expected: FAIL - `TitleAdminUseCaseImpl`/the request records don't exist yet. + +- [ ] **Step 3: Create the request records** + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +import java.util.List; + +public record CreateTitleRequest(@NotBlank String primaryTitle, @NotBlank String originalTitle, + @NotBlank String titleType, Integer startYear, Integer endYear, + Integer runtimeMinutes, List genres) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +import java.util.List; + +public record UpdateTitleRequest(@NotBlank String primaryTitle, @NotBlank String originalTitle, + @NotBlank String titleType, Integer startYear, Integer endYear, + Integer runtimeMinutes, List genres, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import java.util.List; + +// Every field nullable/absent - merge-patch semantics (docs/crud-expansion-design.md §6.5): only +// fields present in the JSON body are applied, everything else is left as-is on the existing row. +public record PatchTitleRequest(String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import java.util.List; + +public record CrewRequest(List directors, List writers) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Min; + +public record RatingRequest(@DecimalMin("0.0") @DecimalMax("10.0") double averageRating, + @Min(0) int numVotes) { +} +``` + +- [ ] **Step 4: Create `TitleAdminUseCase`/`TitleAdminUseCaseImpl`** + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.CrewRequest; +import com.ludovictemgoua.imdb.application.PatchTitleRequest; +import com.ludovictemgoua.imdb.application.RatingRequest; +import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.domain.model.TitleCore; + +public interface TitleAdminUseCase { + + TitleCore create(CreateTitleRequest request); + + TitleCore update(String titleId, UpdateTitleRequest request); + + TitleCore patch(String titleId, PatchTitleRequest request); + + void delete(String titleId); + + void upsertCrew(String titleId, CrewRequest request); + + void upsertRating(String titleId, RatingRequest request); + + void deleteRating(String titleId); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.TitleCore; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class TitleAdminUseCaseImpl implements TitleAdminUseCase { + + private final TitleRepository titleRepository; + + public TitleAdminUseCaseImpl(TitleRepository titleRepository) { + this.titleRepository = titleRepository; + } + + @Override + public TitleCore create(CreateTitleRequest request) { + return titleRepository.insertTitle(request.primaryTitle(), request.originalTitle(), request.titleType(), + request.startYear(), request.endYear(), request.runtimeMinutes(), request.genres()); + } + + @Override + public TitleCore update(String titleId, UpdateTitleRequest request) { + int tconst = ImdbIds.parseTitleId(titleId); + handle(titleRepository.updateTitle(tconst, request.primaryTitle(), request.originalTitle(), + request.titleType(), request.startYear(), request.endYear(), request.runtimeMinutes(), + request.genres(), request.version()), titleId); + return titleRepository.findCore(tconst).orElseThrow(); + } + + @Override + public TitleCore patch(String titleId, PatchTitleRequest request) { + int tconst = ImdbIds.parseTitleId(titleId); + TitleCore current = titleRepository.findCore(tconst) + .orElseThrow(() -> new NotFoundException("No title with id " + titleId)); + handle(titleRepository.updateTitle(tconst, + request.primaryTitle() != null ? request.primaryTitle() : current.primaryTitle(), + request.originalTitle() != null ? request.originalTitle() : current.originalTitle(), + request.titleType() != null ? request.titleType() : current.titleType(), + request.startYear() != null ? request.startYear() : current.startYear(), + request.endYear() != null ? request.endYear() : current.endYear(), + request.runtimeMinutes() != null ? request.runtimeMinutes() : current.runtimeMinutes(), + request.genres() != null ? request.genres() : current.genres(), + request.version()), titleId); + return titleRepository.findCore(tconst).orElseThrow(); + } + + @Override + public void delete(String titleId) { + handle(titleRepository.softDeleteTitle(ImdbIds.parseTitleId(titleId)), titleId); + } + + @Override + public void upsertCrew(String titleId, CrewRequest request) { + int tconst = ImdbIds.parseTitleId(titleId); + List directorIds = toPersonIds(request.directors()); + List writerIds = toPersonIds(request.writers()); + handle(titleRepository.upsertCrew(tconst, directorIds, writerIds), titleId); + } + + @Override + public void upsertRating(String titleId, RatingRequest request) { + handle(titleRepository.upsertRating(ImdbIds.parseTitleId(titleId), + request.averageRating(), request.numVotes()), titleId); + } + + @Override + public void deleteRating(String titleId) { + handle(titleRepository.deleteRating(ImdbIds.parseTitleId(titleId)), titleId); + } + + private static List toPersonIds(List personIds) { + return personIds == null ? List.of() + : personIds.stream().map(ImdbIds::parsePersonId).collect(Collectors.toList()); + } + + private static void handle(WriteResult result, String titleId) { + switch (result) { + case NOT_FOUND -> throw new NotFoundException("No title with id " + titleId); + case VERSION_CONFLICT -> throw new ConflictException( + "Title " + titleId + " was modified by someone else - refresh and retry"); + case SUCCESS -> { } + } + } +} +``` + +- [ ] **Step 5: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=TitleAdminUseCaseImplTest` +Expected: PASS, 4 tests green. + +- [ ] **Step 6: Create the cache-evicting decorator** + +```java +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.CrewRequest; +import com.ludovictemgoua.imdb.application.PatchTitleRequest; +import com.ludovictemgoua.imdb.application.RatingRequest; +import com.ludovictemgoua.imdb.application.TitleAdminUseCaseImpl; +import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; +import com.ludovictemgoua.imdb.domain.model.TitleCore; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Caching; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +// Precise title-detail eviction on any write affecting that title; a rating write also clears the +// entire top-rated region (allEntries) since there's no cheap way to know which genre/limit/minVotes +// combinations it affects - the same coarse-but-correct trade-off documented in +// docs/crud-expansion-design.md §6.2. Admin writes are expected to be infrequent, so full-region +// eviction here is cheap in practice. +@Service +@Primary +public class CachingTitleAdminUseCase implements TitleAdminUseCase { + + private final TitleAdminUseCaseImpl delegate; + + public CachingTitleAdminUseCase(TitleAdminUseCaseImpl delegate) { + this.delegate = delegate; + } + + @Override + public TitleCore create(CreateTitleRequest request) { + return delegate.create(request); + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public TitleCore update(String titleId, UpdateTitleRequest request) { + return delegate.update(titleId, request); + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public TitleCore patch(String titleId, PatchTitleRequest request) { + return delegate.patch(titleId, request); + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public void delete(String titleId) { + delegate.delete(titleId); + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public void upsertCrew(String titleId, CrewRequest request) { + delegate.upsertCrew(titleId, request); + } + + @Override + @Caching(evict = { + @CacheEvict(cacheNames = "title-detail", key = "#titleId"), + @CacheEvict(cacheNames = "top-rated", allEntries = true) + }) + public void upsertRating(String titleId, RatingRequest request) { + delegate.upsertRating(titleId, request); + } + + @Override + @Caching(evict = { + @CacheEvict(cacheNames = "title-detail", key = "#titleId"), + @CacheEvict(cacheNames = "top-rated", allEntries = true) + }) + public void deleteRating(String titleId) { + delegate.deleteRating(titleId); + } +} +``` + +- [ ] **Step 7: Write the failing controller test additions** + +Add to `TitleControllerTest` (needs a new `@MockitoBean TitleAdminUseCase titleAdminUseCase;` field and +`@Import(...)` of nothing extra - `@WebMvcTest` auto-mocks any constructor dependency not already present): + +```java + @org.springframework.test.context.bean.override.mockito.MockitoBean + com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase titleAdminUseCase; + + @Test + void createTitleRequiresAdminRole() throws Exception { + mockMvc.perform(post("/api/v1/titles") + .with(org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user("1").roles("USER")) + .contentType("application/json") + .content(""" + {"primaryTitle":"New","originalTitle":"New","titleType":"movie","genres":[]} + """)) + .andExpect(status().isForbidden()); + } + + @Test + void createTitleSucceedsForAdmin() throws Exception { + var created = new com.ludovictemgoua.imdb.domain.model.TitleCore( + "tt0000300", "New", "New", "movie", 2024, null, 100, List.of(), null, null, 0); + given(titleAdminUseCase.create(org.mockito.ArgumentMatchers.any())).willReturn(created); + + mockMvc.perform(post("/api/v1/titles") + .with(org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user("1").roles("ADMIN")) + .contentType("application/json") + .content(""" + {"primaryTitle":"New","originalTitle":"New","titleType":"movie","genres":[]} + """)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value("tt0000300")); + } +``` + +Add `import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;` and +`import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;` to the test's +imports (`post`/`get` may already partially be there - add whichever verbs are missing). + +- [ ] **Step 8: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=TitleControllerTest` +Expected: FAIL - `TitleController` has no `POST /api/v1/titles` mapping yet. + +- [ ] **Step 9: Add the admin endpoints to `TitleController`** + +```java + private final TitleAdminUseCase titleAdminUseCase; + + public TitleController(TitleSearchUseCase searchUseCase, TitleDetailUseCase detailUseCase, + TitleAdminUseCase titleAdminUseCase) { + this.searchUseCase = searchUseCase; + this.detailUseCase = detailUseCase; + this.titleAdminUseCase = titleAdminUseCase; + } + + @PostMapping + @org.springframework.http.HttpStatus.CREATED // placeholder marker removed below - see @ResponseStatus line + @org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.CREATED) + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public TitleCore create(@jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.CreateTitleRequest request) { + return titleAdminUseCase.create(request); + } + + @org.springframework.web.bind.annotation.PutMapping("/{titleId}") + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public TitleCore update(@PathVariable String titleId, + @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.UpdateTitleRequest request) { + return titleAdminUseCase.update(titleId, request); + } + + @org.springframework.web.bind.annotation.PatchMapping("/{titleId}") + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public TitleCore patch(@PathVariable String titleId, + @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.PatchTitleRequest request) { + return titleAdminUseCase.patch(titleId, request); + } + + @org.springframework.web.bind.annotation.DeleteMapping("/{titleId}") + @org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT) + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public void delete(@PathVariable String titleId) { + titleAdminUseCase.delete(titleId); + } + + @org.springframework.web.bind.annotation.PutMapping("/{titleId}/crew") + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public void upsertCrew(@PathVariable String titleId, + @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.CrewRequest request) { + titleAdminUseCase.upsertCrew(titleId, request); + } + + @org.springframework.web.bind.annotation.PutMapping("/{titleId}/rating") + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public void upsertRating(@PathVariable String titleId, + @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.RatingRequest request) { + titleAdminUseCase.upsertRating(titleId, request); + } + + @org.springframework.web.bind.annotation.DeleteMapping("/{titleId}/rating") + @org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT) + @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") + public void deleteRating(@PathVariable String titleId) { + titleAdminUseCase.deleteRating(titleId); + } +``` + +Replace the fully-qualified names above with proper `import` statements at the top of the file (matching +the file's existing style - it already imports `PagedResult`/`TitleDetail`/`TitleSummary` etc. by name, so +do the same for every class used above: `TitleCore`, `TitleAdminUseCase`, `CreateTitleRequest`, +`UpdateTitleRequest`, `PatchTitleRequest`, `CrewRequest`, `RatingRequest`, `PostMapping`, `PutMapping`, +`PatchMapping`, `DeleteMapping`, `ResponseStatus`, `RequestBody`, `HttpStatus`, `Valid`, `PreAuthorize`). +Delete the stray `@org.springframework.http.HttpStatus.CREATED` marker line above - it isn't valid +annotation syntax and was left in only to flag "this is where `@ResponseStatus(CREATED)` goes" during +planning; the real code has just the one `@ResponseStatus` line beneath it. + +- [ ] **Step 10: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=TitleControllerTest` +Expected: PASS, all tests (existing + new) green. + +- [ ] **Step 11: Run the full unit suite, then the full integration suite** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 12: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/application/ src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java +git commit -m "Add admin CRUD for titles (create/update/patch/delete/crew/rating) with cache eviction" +``` + +### Task 3.3: Reduce the `title-search` cache TTL + +**Files:** +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java` + +**Interfaces:** none new - this only changes a `RedisCacheConfiguration` applied to the existing +`title-search` cache region. + +`title-search` is keyed by `query:page:size` (LLD §6) - an admin title write has no cheap way to know +which of those arbitrary combinations it affects, so precise eviction (like `title-detail`) isn't +possible and full-region eviction on every title write would defeat the cache almost entirely (title +writes and title searches share the same cache region's traffic). `docs/crud-expansion-design.md` §6.2's +resolution: accept a bounded staleness window instead, by shortening this one region's TTL from the +default 24h to 15 minutes. + +- [ ] **Step 1: Write the failing test** + +```java +package com.ludovictemgoua.imdb.infrastructure.cache; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.redis.cache.RedisCacheManager; + +import java.time.Duration; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +class CacheConfigTest { + + @Autowired + RedisCacheManager cacheManager; + + @Test + void titleSearchCacheHasAFifteenMinuteTtlNotTheDefaultTwentyFourHours() { + var ttl = cacheManager.getCache("title-search").getNativeCache().toString(); + // RedisCache doesn't expose its configured TTL directly via a public getter on getNativeCache(); + // assert against the cache's own configuration object instead: + var config = ((org.springframework.data.redis.cache.RedisCache) cacheManager.getCache("title-search")) + .getCacheConfiguration(); + + assertThat(config.getTtl()).isEqualTo(Duration.ofMinutes(15)); + } + + @Test + void titleDetailCacheKeepsTheDefaultTwentyFourHourTtl() { + var config = ((org.springframework.data.redis.cache.RedisCache) cacheManager.getCache("title-detail")) + .getCacheConfiguration(); + + assertThat(config.getTtl()).isEqualTo(Duration.ofHours(24)); + } +} +``` + +This test needs a real Spring context with the actual `RedisCacheManager` bean (not Testcontainers Redis +specifically - `@SpringBootTest` alone will fail to start without a Redis connection, so add +`@Import(com.ludovictemgoua.imdb.TestcontainersConfiguration.class)` to the class, matching every other +`@SpringBootTest` in this codebase). + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=CacheConfigTest` +Expected: FAIL - `title-search` still has the default 24h TTL. (Note: this test class needs to be named +`*IntegrationTest.java` or added to the Failsafe `` pattern in `pom.xml` to actually run under +`failsafe:verify` - rename it to `CacheConfigIntegrationTest` to match the existing convention rather than +adding a one-off Failsafe include pattern for a single class.) + +- [ ] **Step 3: Add the per-cache TTL override** + +```java + RedisCacheConfiguration searchCacheConfig = defaults.entryTtl(Duration.ofMinutes(15)); + + return RedisCacheManager.builder(redisCacheWriter) + .cacheDefaults(defaults) + .withCacheConfiguration("title-search", searchCacheConfig) + .initialCacheNames(CACHE_NAMES) + .build(); +``` + +(Replace the existing `return RedisCacheManager.builder(redisCacheWriter)...build();` block in +`cacheManager(...)` with the above - `searchCacheConfig` is `defaults` with just the TTL overridden, +inheriting the same serializer configuration.) + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=CacheConfigIntegrationTest` +Expected: PASS, both tests green. + +- [ ] **Step 5: Run the full unit and integration suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 6: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfig.java src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheConfigIntegrationTest.java +git commit -m "Shorten the title-search cache TTL to 15 minutes now that title writes exist" +``` + +**Phase 3 checkpoint**: admin title CRUD is fully live, gated by `@PreAuthorize("hasRole('ADMIN')")`, with +correct cache eviction (precise for `title-detail`/`top-rated`, a shortened TTL for the un-evictable +`title-search`). This is the template Phase 4 (People) follows. + +--- + +## Phase 4: Admin CRUD - People + +### Task 4.1: `PersonCore`, `PersonRepository` write methods + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/PersonCore.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/domain/repository/PersonRepository.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java` (create if Task 2.2 didn't already, extend either way) + +**Interfaces:** +- Produces: `PersonCore(String id, String primaryName, Integer birthYear, Integer deathYear, List primaryProfession, int version)`. `PersonRepository.findCore(int nconst) -> Optional`, `insertPerson(...) -> PersonCore`, `updatePerson(int nconst, ..., int expectedVersion) -> WriteResult`, `softDeletePerson(int nconst) -> WriteResult`. This `findCore` is internal-only (no controller exposes a plain "get person" read endpoint - matches `docs/crud-expansion-design.md` §5.2 exactly, which lists only the four write endpoints). + +- [ ] **Step 1: Write the failing integration tests** + +```java + @Test + void insertPersonThenFindCoreRoundTrips() { + var created = repository.insertPerson("Ada Lovelace", 1815, 1852, List.of("mathematician")); + + var found = repository.findCore(ImdbIds.parsePersonId(created.id())).orElseThrow(); + + assertThat(found.primaryName()).isEqualTo("Ada Lovelace"); + assertThat(found.version()).isEqualTo(0); + } + + @Test + void insertedPersonIdIsAboveTheSeededRange() { + var created = repository.insertPerson("New Person", null, null, List.of()); + + assertThat(ImdbIds.parsePersonId(created.id())).isGreaterThan(10); + } + + @Test + void updatePersonBumpsVersionAndPersists() { + var created = repository.insertPerson("Old Name", null, null, List.of()); + int nconst = ImdbIds.parsePersonId(created.id()); + + var result = repository.updatePerson(nconst, "New Name", 1990, null, List.of("actor"), created.version()); + + assertThat(result).isEqualTo(com.ludovictemgoua.imdb.domain.repository.WriteResult.SUCCESS); + assertThat(repository.findCore(nconst).orElseThrow().primaryName()).isEqualTo("New Name"); + } + + @Test + void updatePersonReturnsVersionConflictOnStaleVersion() { + var created = repository.insertPerson("Stale", null, null, List.of()); + int nconst = ImdbIds.parsePersonId(created.id()); + + var result = repository.updatePerson(nconst, "New Name", null, null, List.of(), created.version() + 1); + + assertThat(result).isEqualTo(com.ludovictemgoua.imdb.domain.repository.WriteResult.VERSION_CONFLICT); + } + + @Test + void softDeletePersonExcludesThemFromFindCore() { + var created = repository.insertPerson("Delete Me", null, null, List.of()); + int nconst = ImdbIds.parsePersonId(created.id()); + + repository.softDeletePerson(nconst); + + assertThat(repository.findCore(nconst)).isEmpty(); + } +``` + +If `JdbcPersonRepositoryIntegrationTest` doesn't exist yet, create it now with the full class structure +(copy `JdbcTitleRepositoryIntegrationTest`'s header exactly: +`@Import(TestcontainersConfiguration.class) @SpringBootTest @Transactional @Sql("/fixtures/fixture-data.sql")`, +autowiring `JdbcPersonRepository repository`), and include Task 2.2's `findByNameExcludesASoftDeletedPerson` +test in it too if that's still pending. + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcPersonRepositoryIntegrationTest` +Expected: FAIL - `PersonCore`/the new repository methods don't exist yet. + +- [ ] **Step 3: Create `PersonCore`** + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record PersonCore(String id, String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession, int version) { +} +``` + +- [ ] **Step 4: Add the new methods to `PersonRepository`** + +```java + PersonCore insertPerson(String primaryName, Integer birthYear, Integer deathYear, List primaryProfession); + + Optional findCore(int nconst); + + com.ludovictemgoua.imdb.domain.repository.WriteResult updatePerson( + int nconst, String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession, int expectedVersion); + + com.ludovictemgoua.imdb.domain.repository.WriteResult softDeletePerson(int nconst); +``` + +Add `import com.ludovictemgoua.imdb.domain.model.PersonCore;`, `import java.util.List;`, and +`import java.util.Optional;` to the top of `PersonRepository.java` (replace the fully-qualified +`WriteResult` references above with a plain `import com.ludovictemgoua.imdb.domain.repository.WriteResult;` +- it's the same package as this file, so a bare `WriteResult` reference works with no import at all; +either is fine, prefer the bare reference since it's simpler). + +- [ ] **Step 5: Implement the new methods in `JdbcPersonRepository`** + +```java + @Override + public PersonCore insertPerson(String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession) { + String sql = """ + INSERT INTO name_basics (nconst, primary_name, birth_year, death_year, primary_profession) + VALUES (nextval('person_id_seq'), :primaryName, :birthYear, :deathYear, :primaryProfession) + RETURNING nconst + """; + var params = new MapSqlParameterSource() + .addValue("primaryName", primaryName).addValue("birthYear", birthYear) + .addValue("deathYear", deathYear) + .addValue("primaryProfession", primaryProfession.toArray(new String[0]), java.sql.Types.ARRAY, "text"); + int nconst = jdbc.queryForObject(sql, params, Integer.class); + return findCore(nconst).orElseThrow(); + } + + @Override + public Optional findCore(int nconst) { + String sql = """ + SELECT nconst, primary_name, birth_year, death_year, primary_profession, version + FROM name_basics WHERE nconst = :nconst AND deleted_at IS NULL + """; + return jdbc.query(sql, Map.of("nconst", nconst), JdbcPersonRepository::mapCore).stream().findFirst(); + } + + @Override + public WriteResult updatePerson(int nconst, String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession, int expectedVersion) { + if (findCore(nconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + String sql = """ + UPDATE name_basics + SET primary_name = :primaryName, birth_year = :birthYear, death_year = :deathYear, + primary_profession = :primaryProfession, version = version + 1 + WHERE nconst = :nconst AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("primaryName", primaryName).addValue("birthYear", birthYear) + .addValue("deathYear", deathYear) + .addValue("primaryProfession", primaryProfession.toArray(new String[0]), java.sql.Types.ARRAY, "text") + .addValue("nconst", nconst).addValue("expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public WriteResult softDeletePerson(int nconst) { + if (findCore(nconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + jdbc.update("UPDATE name_basics SET deleted_at = now() WHERE nconst = :nconst", Map.of("nconst", nconst)); + return WriteResult.SUCCESS; + } + + private static PersonCore mapCore(ResultSet rs, int rowNum) throws SQLException { + return new PersonCore(ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"), + (Integer) rs.getObject("birth_year"), (Integer) rs.getObject("death_year"), + toStringList(rs.getArray("primary_profession")), rs.getInt("version")); + } + + private static List toStringList(java.sql.Array sqlArray) throws SQLException { + if (sqlArray == null) return List.of(); + return List.of((String[]) sqlArray.getArray()); + } +``` + +Add `import com.ludovictemgoua.imdb.domain.model.PersonCore;` and +`import com.ludovictemgoua.imdb.domain.repository.WriteResult;` to `JdbcPersonRepository.java`'s imports. + +- [ ] **Step 6: Run the tests to verify they pass** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcPersonRepositoryIntegrationTest` +Expected: PASS. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/domain/model/PersonCore.java src/main/java/com/ludovictemgoua/imdb/domain/repository/PersonRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcPersonRepositoryIntegrationTest.java +git commit -m "Add PersonRepository write methods: insert/update/soft-delete" +``` + +### Task 4.2: `PersonAdminUseCase`, `PersonController` admin endpoints + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/PersonAdminUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/CreatePersonRequest.java`, `UpdatePersonRequest.java`, `PatchPersonRequest.java` (records) +- Modify: `src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java` (extend) + +**Interfaces:** +- Consumes: `PersonRepository` write methods (Task 4.1) +- Produces: `PersonAdminUseCase.create/update/patch/delete`, all four gated `@PreAuthorize("hasRole('ADMIN')")` + on `PersonController`. No cache eviction needed here directly (nothing caches a person by id today - the + `six-degrees` cache is evicted from `CachingCoStarGraphRepository`, wired in Phase 5 alongside principals, + since that's the cache region a person write can actually invalidate). + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.PersonCore; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class PersonAdminUseCaseImplTest { + + @Mock + PersonRepository personRepository; + + @Test + void createDelegatesToInsertPerson() { + var created = new PersonCore("nm0000011", "New Person", null, null, List.of(), 0); + given(personRepository.insertPerson("New Person", null, null, List.of())).willReturn(created); + + var result = new PersonAdminUseCaseImpl(personRepository) + .create(new CreatePersonRequest("New Person", null, null, List.of())); + + assertThat(result.id()).isEqualTo("nm0000011"); + } + + @Test + void updateThrowsConflictOnVersionMismatch() { + given(personRepository.updatePerson(11, "New", null, null, List.of(), 0)) + .willReturn(WriteResult.VERSION_CONFLICT); + var useCase = new PersonAdminUseCaseImpl(personRepository); + + assertThatThrownBy(() -> useCase.update("nm0000011", + new UpdatePersonRequest("New", null, null, List.of(), 0))) + .isInstanceOf(ConflictException.class); + } + + @Test + void deleteThrowsNotFoundWhenThePersonDoesNotExist() { + given(personRepository.softDeletePerson(11)).willReturn(WriteResult.NOT_FOUND); + var useCase = new PersonAdminUseCaseImpl(personRepository); + + assertThatThrownBy(() -> useCase.delete("nm0000011")).isInstanceOf(NotFoundException.class); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=PersonAdminUseCaseImplTest` +Expected: FAIL. + +- [ ] **Step 3: Create the request records** + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +import java.util.List; + +public record CreatePersonRequest(@NotBlank String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +import java.util.List; + +public record UpdatePersonRequest(@NotBlank String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import java.util.List; + +public record PatchPersonRequest(String primaryName, Integer birthYear, Integer deathYear, + List primaryProfession, int version) { +} +``` + +- [ ] **Step 4: Create `PersonAdminUseCase`/`PersonAdminUseCaseImpl`** + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +import com.ludovictemgoua.imdb.domain.model.PersonCore; + +public interface PersonAdminUseCase { + + PersonCore create(CreatePersonRequest request); + + PersonCore update(String personId, UpdatePersonRequest request); + + PersonCore patch(String personId, PatchPersonRequest request); + + void delete(String personId); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.PersonCore; +import com.ludovictemgoua.imdb.domain.repository.PersonRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +@Service +public class PersonAdminUseCaseImpl implements PersonAdminUseCase { + + private final PersonRepository personRepository; + + public PersonAdminUseCaseImpl(PersonRepository personRepository) { + this.personRepository = personRepository; + } + + @Override + public PersonCore create(CreatePersonRequest request) { + return personRepository.insertPerson( + request.primaryName(), request.birthYear(), request.deathYear(), request.primaryProfession()); + } + + @Override + public PersonCore update(String personId, UpdatePersonRequest request) { + int nconst = ImdbIds.parsePersonId(personId); + handle(personRepository.updatePerson(nconst, request.primaryName(), request.birthYear(), + request.deathYear(), request.primaryProfession(), request.version()), personId); + return personRepository.findCore(nconst).orElseThrow(); + } + + @Override + public PersonCore patch(String personId, PatchPersonRequest request) { + int nconst = ImdbIds.parsePersonId(personId); + PersonCore current = personRepository.findCore(nconst) + .orElseThrow(() -> new NotFoundException("No person with id " + personId)); + handle(personRepository.updatePerson(nconst, + request.primaryName() != null ? request.primaryName() : current.primaryName(), + request.birthYear() != null ? request.birthYear() : current.birthYear(), + request.deathYear() != null ? request.deathYear() : current.deathYear(), + request.primaryProfession() != null ? request.primaryProfession() : current.primaryProfession(), + request.version()), personId); + return personRepository.findCore(nconst).orElseThrow(); + } + + @Override + public void delete(String personId) { + handle(personRepository.softDeletePerson(ImdbIds.parsePersonId(personId)), personId); + } + + private static void handle(WriteResult result, String personId) { + switch (result) { + case NOT_FOUND -> throw new NotFoundException("No person with id " + personId); + case VERSION_CONFLICT -> throw new ConflictException( + "Person " + personId + " was modified by someone else - refresh and retry"); + case SUCCESS -> { } + } + } +} +``` + +- [ ] **Step 5: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=PersonAdminUseCaseImplTest` +Expected: PASS, 3 tests green. + +- [ ] **Step 6: Write the failing controller test additions** + +Add to `PersonControllerTest` (create the file with the full `@WebMvcTest(PersonController.class)` +structure if it doesn't exist yet, mirroring `TitleControllerTest`): + +```java + @org.springframework.test.context.bean.override.mockito.MockitoBean + com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase personAdminUseCase; + + @Test + void createPersonRequiresAdminRole() throws Exception { + mockMvc.perform(org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post("/api/v1/people") + .with(org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user("1").roles("USER")) + .contentType("application/json") + .content(""" + {"primaryName":"New Person","primaryProfession":[]} + """)) + .andExpect(org.springframework.test.web.servlet.result.MockMvcResultMatchers.status().isForbidden()); + } +``` + +- [ ] **Step 7: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=PersonControllerTest` +Expected: FAIL - `PersonController` has no `POST /api/v1/people` mapping yet. + +- [ ] **Step 8: Add the admin endpoints to `PersonController`** + +Add these imports: `com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase`, +`com.ludovictemgoua.imdb.application.CreatePersonRequest`, `UpdatePersonRequest`, `PatchPersonRequest`, +`com.ludovictemgoua.imdb.domain.model.PersonCore`, `jakarta.validation.Valid`, +`org.springframework.http.HttpStatus`, `org.springframework.security.access.prepost.PreAuthorize`, +`org.springframework.web.bind.annotation.{PostMapping,PutMapping,PatchMapping,DeleteMapping,RequestBody,ResponseStatus}`: + +```java + private final PersonAdminUseCase personAdminUseCase; + + public PersonController(SixDegreesUseCase sixDegreesUseCase, PersonAdminUseCase personAdminUseCase) { + this.sixDegreesUseCase = sixDegreesUseCase; + this.personAdminUseCase = personAdminUseCase; + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + @PreAuthorize("hasRole('ADMIN')") + public PersonCore create(@Valid @RequestBody CreatePersonRequest request) { + return personAdminUseCase.create(request); + } + + @PutMapping("/{personId}") + @PreAuthorize("hasRole('ADMIN')") + public PersonCore update(@PathVariable String personId, @Valid @RequestBody UpdatePersonRequest request) { + return personAdminUseCase.update(personId, request); + } + + @PatchMapping("/{personId}") + @PreAuthorize("hasRole('ADMIN')") + public PersonCore patch(@PathVariable String personId, @RequestBody PatchPersonRequest request) { + return personAdminUseCase.patch(personId, request); + } + + @DeleteMapping("/{personId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + @PreAuthorize("hasRole('ADMIN')") + public void delete(@PathVariable String personId) { + personAdminUseCase.delete(personId); + } +``` + +(Add `import org.springframework.web.bind.annotation.PathVariable;` too if not already present in this +file - it likely isn't, since the existing `sixDegrees` method takes only `@RequestParam`s.) + +- [ ] **Step 9: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=PersonControllerTest` +Expected: PASS. + +- [ ] **Step 10: Run the full suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 11: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/application/ src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java src/test/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java +git commit -m "Add admin CRUD for people (create/update/patch/delete)" +``` + +--- + +## Phase 5: Admin CRUD - Cast/Crew Credits (Principals) + +`title_principals`' primary key is the composite `(tconst, ordering)` (`V0__base_schema.sql`) - no +surrogate id column is added in this phase. The `{principalId}` path segment in +`docs/crud-expansion-design.md` §5.4 maps directly to the `ordering` value, scoped under the existing +`{titleId}` path segment; no schema change needed beyond what `V7` already added. + +### Task 5.1: `PrincipalCredit`, `TitleRepository` principal methods + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/PrincipalCredit.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java` +- Modify: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java` + +**Interfaces:** +- Produces: `PrincipalCredit(String personId, String personName, String category, String job, List characters, int ordering, int version)`. `TitleRepository.findAllPrincipals(int tconst) -> List` (uncapped, unlike `findTopCast`), `insertPrincipal(int tconst, int personId, String category, String job, List characters, int ordering) -> WriteResult`, `updatePrincipal(int tconst, int ordering, String category, String job, List characters, int expectedVersion) -> WriteResult`, `softDeletePrincipal(int tconst, int ordering) -> WriteResult`. + +- [ ] **Step 1: Write the failing integration tests** + +```java + @Test + void insertPrincipalThenFindAllPrincipalsIncludesIt() { + var result = repository.insertPrincipal(100, 1, "actor", null, List.of("New Role"), 99); + + assertThat(result).isEqualTo(com.ludovictemgoua.imdb.domain.repository.WriteResult.SUCCESS); + assertThat(repository.findAllPrincipals(100)).extracting("ordering").contains(99); + } + + @Test + void updatePrincipalBumpsVersionAndPersists() { + repository.insertPrincipal(100, 1, "actor", null, List.of("Original"), 98); + + var result = repository.updatePrincipal(100, 98, "actor", null, List.of("Updated"), 0); + + assertThat(result).isEqualTo(com.ludovictemgoua.imdb.domain.repository.WriteResult.SUCCESS); + var updated = repository.findAllPrincipals(100).stream() + .filter(p -> p.ordering() == 98).findFirst().orElseThrow(); + assertThat(updated.characters()).containsExactly("Updated"); + assertThat(updated.version()).isEqualTo(1); + } + + @Test + void softDeletePrincipalExcludesItFromFindAllPrincipals() { + repository.insertPrincipal(100, 1, "actor", null, List.of("Temp"), 97); + + repository.softDeletePrincipal(100, 97); + + assertThat(repository.findAllPrincipals(100)).extracting("ordering").doesNotContain(97); + } +``` + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcTitleRepositoryIntegrationTest` +Expected: FAIL. + +- [ ] **Step 3: Create `PrincipalCredit`** + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record PrincipalCredit(String personId, String personName, String category, String job, + List characters, int ordering, int version) { +} +``` + +- [ ] **Step 4: Add the new methods to `TitleRepository`** + +```java + List findAllPrincipals(int tconst); + + WriteResult insertPrincipal(int tconst, int personId, String category, String job, + List characters, int ordering); + + WriteResult updatePrincipal(int tconst, int ordering, String category, String job, + List characters, int expectedVersion); + + WriteResult softDeletePrincipal(int tconst, int ordering); +``` + +Add `import com.ludovictemgoua.imdb.domain.model.PrincipalCredit;` to this file's imports. + +- [ ] **Step 5: Implement the new methods in `JdbcTitleRepository`** + +```java + @Override + public List findAllPrincipals(int tconst) { + String sql = """ + SELECT tp.nconst, nb.primary_name, tp.category, tp.job, tp.characters, tp.ordering, tp.version + FROM title_principals tp + JOIN name_basics nb ON nb.nconst = tp.nconst + WHERE tp.tconst = :tconst AND tp.deleted_at IS NULL + ORDER BY tp.ordering + """; + return jdbc.query(sql, Map.of("tconst", tconst), JdbcTitleRepository::mapPrincipal); + } + + @Override + public WriteResult insertPrincipal(int tconst, int personId, String category, String job, + List characters, int ordering) { + if (findCore(tconst).isEmpty()) { + return WriteResult.NOT_FOUND; + } + String sql = """ + INSERT INTO title_principals (tconst, ordering, nconst, category, job, characters) + VALUES (:tconst, :ordering, :nconst, :category, :job, :characters) + """; + var params = new MapSqlParameterSource() + .addValue("tconst", tconst).addValue("ordering", ordering).addValue("nconst", personId) + .addValue("category", category).addValue("job", job) + .addValue("characters", characters.toArray(new String[0]), java.sql.Types.ARRAY, "text"); + jdbc.update(sql, params); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult updatePrincipal(int tconst, int ordering, String category, String job, + List characters, int expectedVersion) { + String sql = """ + UPDATE title_principals + SET category = :category, job = :job, characters = :characters, version = version + 1 + WHERE tconst = :tconst AND ordering = :ordering AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("category", category).addValue("job", job) + .addValue("characters", characters.toArray(new String[0]), java.sql.Types.ARRAY, "text") + .addValue("tconst", tconst).addValue("ordering", ordering).addValue("expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public WriteResult softDeletePrincipal(int tconst, int ordering) { + var params = new MapSqlParameterSource().addValue("tconst", tconst).addValue("ordering", ordering); + int updated = jdbc.update( + "UPDATE title_principals SET deleted_at = now() WHERE tconst = :tconst AND ordering = :ordering AND deleted_at IS NULL", + params); + return updated == 0 ? WriteResult.NOT_FOUND : WriteResult.SUCCESS; + } + + private static PrincipalCredit mapPrincipal(ResultSet rs, int rowNum) throws SQLException { + return new PrincipalCredit(ImdbIds.formatPersonId(rs.getInt("nconst")), rs.getString("primary_name"), + rs.getString("category"), rs.getString("job"), toStringList(rs.getArray("characters")), + rs.getInt("ordering"), rs.getInt("version")); + } +``` + +`updatePrincipal`'s missing existence pre-check (unlike the other write methods in this file) is +deliberate - `(tconst, ordering)` has no separate lookup method worth adding just for this, so a +version-mismatch-shaped `0` and a not-found-shaped `0` are indistinguishable here; both correctly surface +as `VERSION_CONFLICT` to the caller, which - for a composite-keyed row a caller must already know the +`ordering` of - is an acceptable simplification over adding a dedicated existence check. + +- [ ] **Step 6: Run the tests to verify they pass** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcTitleRepositoryIntegrationTest` +Expected: PASS. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/domain/model/PrincipalCredit.java src/main/java/com/ludovictemgoua/imdb/domain/repository/TitleRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcTitleRepositoryIntegrationTest.java +git commit -m "Add TitleRepository principal-credit write methods" +``` + +### Task 5.2: `TitleAdminUseCase` principal methods, `TitleController` endpoints, six-degrees cache eviction + +**Files:** +- Modify: `src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleAdminUseCase.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/PrincipalRequest.java` (record) +- Modify: `src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingPersonAdminUseCase.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java` (extend) +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java` (extend) + +**Interfaces:** +- Consumes: `TitleRepository` principal methods (Task 5.1), `PersonAdminUseCaseImpl` (Task 4.2) +- Produces: `TitleAdminUseCase.getAllPrincipals/addPrincipal/updatePrincipal/deletePrincipal` - `getAllPrincipals` + is the one method on this interface **not** gated `@PreAuthorize` at the controller (it's the public + uncapped-cast-list endpoint, §5.4). `CachingPersonAdminUseCase` - the `@Primary` decorator missing since + Phase 4 - now evicts the `six-degrees` region (`allEntries`) on person update/delete, per + `docs/crud-expansion-design.md` §6.2's "any people/principals write" rule. + +- [ ] **Step 1: Write the failing unit test additions** + +Add to `TitleAdminUseCaseImplTest`: + +```java + @Test + void addPrincipalDelegatesToInsertPrincipal() { + given(titleRepository.insertPrincipal(300, 1, "actor", null, List.of("Role"), 5)) + .willReturn(WriteResult.SUCCESS); + var useCase = new TitleAdminUseCaseImpl(titleRepository); + + useCase.addPrincipal("tt0000300", new PrincipalRequest("nm0000001", "actor", null, List.of("Role"), 5)); + } + + @Test + void deletePrincipalThrowsNotFoundWhenMissing() { + given(titleRepository.softDeletePrincipal(300, 5)).willReturn(WriteResult.NOT_FOUND); + var useCase = new TitleAdminUseCaseImpl(titleRepository); + + assertThatThrownBy(() -> useCase.deletePrincipal("tt0000300", 5)).isInstanceOf(NotFoundException.class); + } +``` + +- [ ] **Step 2: Run the tests to verify they fail** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=TitleAdminUseCaseImplTest` +Expected: FAIL - the new interface methods don't exist yet. + +- [ ] **Step 3: Create `PrincipalRequest` and add the methods to `TitleAdminUseCase`/`Impl`** + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +import java.util.List; + +public record PrincipalRequest(@NotBlank String personId, @NotBlank String category, String job, + List characters, int ordering) { +} +``` + +Add to `TitleAdminUseCase`: + +```java + java.util.List getAllPrincipals(String titleId); + + void addPrincipal(String titleId, PrincipalRequest request); + + void updatePrincipal(String titleId, int ordering, PrincipalRequest request, int expectedVersion); + + void deletePrincipal(String titleId, int ordering); +``` + +Add to `TitleAdminUseCaseImpl`: + +```java + @Override + public java.util.List getAllPrincipals(String titleId) { + return titleRepository.findAllPrincipals(ImdbIds.parseTitleId(titleId)); + } + + @Override + public void addPrincipal(String titleId, PrincipalRequest request) { + int tconst = ImdbIds.parseTitleId(titleId); + handle(titleRepository.insertPrincipal(tconst, ImdbIds.parsePersonId(request.personId()), + request.category(), request.job(), request.characters(), request.ordering()), titleId); + } + + @Override + public void updatePrincipal(String titleId, int ordering, PrincipalRequest request, int expectedVersion) { + int tconst = ImdbIds.parseTitleId(titleId); + handle(titleRepository.updatePrincipal(tconst, ordering, request.category(), request.job(), + request.characters(), expectedVersion), titleId); + } + + @Override + public void deletePrincipal(String titleId, int ordering) { + handle(titleRepository.softDeletePrincipal(ImdbIds.parseTitleId(titleId), ordering), titleId); + } +``` + +- [ ] **Step 4: Run the tests to verify they pass** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=TitleAdminUseCaseImplTest` +Expected: PASS. + +- [ ] **Step 5: Add eviction methods to `CachingTitleAdminUseCase` and create `CachingPersonAdminUseCase`** + +Add to `CachingTitleAdminUseCase` (import `PrincipalRequest`, `PrincipalCredit`, `List`): + +```java + @Override + public List getAllPrincipals(String titleId) { + return delegate.getAllPrincipals(titleId); + } + + @Override + @Caching(evict = { + @CacheEvict(cacheNames = "title-detail", key = "#titleId"), + @CacheEvict(cacheNames = "six-degrees", allEntries = true) + }) + public void addPrincipal(String titleId, PrincipalRequest request) { + delegate.addPrincipal(titleId, request); + } + + @Override + @Caching(evict = { + @CacheEvict(cacheNames = "title-detail", key = "#titleId"), + @CacheEvict(cacheNames = "six-degrees", allEntries = true) + }) + public void updatePrincipal(String titleId, int ordering, PrincipalRequest request, int expectedVersion) { + delegate.updatePrincipal(titleId, ordering, request, expectedVersion); + } + + @Override + @Caching(evict = { + @CacheEvict(cacheNames = "title-detail", key = "#titleId"), + @CacheEvict(cacheNames = "six-degrees", allEntries = true) + }) + public void deletePrincipal(String titleId, int ordering) { + delegate.deletePrincipal(titleId, ordering); + } +``` + +Create `CachingPersonAdminUseCase`: + +```java +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.PersonAdminUseCaseImpl; +import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; +import com.ludovictemgoua.imdb.domain.model.PersonCore; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +// A renamed/removed person can change six-degrees path enrichment or its underlying graph edges - +// coarse full-region eviction on any update/delete, same trade-off as CachingTitleAdminUseCase's +// principal writes. create() needs no eviction: a brand-new person can't already be in any cached +// six-degrees result. +@Service +@Primary +public class CachingPersonAdminUseCase implements PersonAdminUseCase { + + private final PersonAdminUseCaseImpl delegate; + + public CachingPersonAdminUseCase(PersonAdminUseCaseImpl delegate) { + this.delegate = delegate; + } + + @Override + public PersonCore create(CreatePersonRequest request) { + return delegate.create(request); + } + + @Override + @CacheEvict(cacheNames = "six-degrees", allEntries = true) + public PersonCore update(String personId, UpdatePersonRequest request) { + return delegate.update(personId, request); + } + + @Override + @CacheEvict(cacheNames = "six-degrees", allEntries = true) + public PersonCore patch(String personId, PatchPersonRequest request) { + return delegate.patch(personId, request); + } + + @Override + @CacheEvict(cacheNames = "six-degrees", allEntries = true) + public void delete(String personId) { + delegate.delete(personId); + } +} +``` + +- [ ] **Step 6: Add the principal endpoints to `TitleController`** + +```java + @GetMapping("/{titleId}/principals") + public List getAllPrincipals(@PathVariable String titleId) { + return titleAdminUseCase.getAllPrincipals(titleId); + } + + @PostMapping("/{titleId}/principals") + @ResponseStatus(HttpStatus.CREATED) + @PreAuthorize("hasRole('ADMIN')") + public void addPrincipal(@PathVariable String titleId, @Valid @RequestBody PrincipalRequest request) { + titleAdminUseCase.addPrincipal(titleId, request); + } + + @PutMapping("/{titleId}/principals/{ordering}") + @PreAuthorize("hasRole('ADMIN')") + public void updatePrincipal(@PathVariable String titleId, @PathVariable int ordering, + @Valid @RequestBody PrincipalRequest request, + @RequestParam int expectedVersion) { + titleAdminUseCase.updatePrincipal(titleId, ordering, request, expectedVersion); + } + + @DeleteMapping("/{titleId}/principals/{ordering}") + @ResponseStatus(HttpStatus.NO_CONTENT) + @PreAuthorize("hasRole('ADMIN')") + public void deletePrincipal(@PathVariable String titleId, @PathVariable int ordering) { + titleAdminUseCase.deletePrincipal(titleId, ordering); + } +``` + +Add `import com.ludovictemgoua.imdb.domain.model.PrincipalCredit;` and +`import com.ludovictemgoua.imdb.application.PrincipalRequest;` to `TitleController.java`'s imports (all the +Spring annotation imports needed here were already added in Task 3.2's cleanup). + +- [ ] **Step 7: Run the full unit and integration suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 8: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/application/ src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/ src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/TitleControllerTest.java +git commit -m "Add admin CRUD for principals and six-degrees cache eviction for people/principal writes" +``` + +### Task 5.3: Prove `@CacheEvict` actually reaches Redis (integration test) + +**Files:** +- Create: `src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheEvictionIntegrationTest.java` + +**Interfaces:** none new - this task only adds test coverage over `CachingTitleAdminUseCase` (Tasks 3.2/5.2) +and `CachingPersonAdminUseCase` (Task 5.2). + +A mocked `CacheManager` in a unit test can prove a `@CacheEvict`-annotated method was *called*, but not +that it actually reached Redis - the same reasoning that motivated the four Redis-Testcontainers cache +integration tests already in this codebase (LLD §10.2) applies identically to eviction. This test primes +each of the three affected cache regions, performs the write that should evict them, then asserts the +specific previously-cached key is gone. + +- [ ] **Step 1: Write the failing integration test** + +```java +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.application.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.RatingRequest; +import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; +import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.application.contracts.TopRatedUseCase; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class CacheEvictionIntegrationTest { + + @Autowired + TitleDetailUseCase titleDetailUseCase; + @Autowired + TopRatedUseCase topRatedUseCase; + @Autowired + TitleAdminUseCase titleAdminUseCase; + @Autowired + PersonAdminUseCase personAdminUseCase; + @Autowired + CacheManager cacheManager; + + @Test + void updatingATitleEvictsItsTitleDetailCacheEntry() { + titleDetailUseCase.getDetail("tt0000100"); + assertThat(cacheManager.getCache("title-detail").get("tt0000100")).isNotNull(); + + var current = titleDetailUseCase.getDetail("tt0000100"); + titleAdminUseCase.update("tt0000100", new UpdateTitleRequest( + current.primaryTitle(), current.originalTitle(), current.titleType(), + current.startYear(), current.endYear(), current.runtimeMinutes(), current.genres(), 0)); + + assertThat(cacheManager.getCache("title-detail").get("tt0000100")).isNull(); + } + + @Test + void writingARatingEvictsTheEntireTopRatedRegion() { + topRatedUseCase.findTopRated("Action", 10, 100); + assertThat(cacheManager.getCache("top-rated").get("Action:10:100")).isNotNull(); + + titleAdminUseCase.upsertRating("tt0000200", new RatingRequest(9.0, 200000)); + + assertThat(cacheManager.getCache("top-rated").get("Action:10:100")).isNull(); + } + + @Test + void updatingAPersonEvictsTheEntireSixDegreesRegion() { + // Priming six-degrees requires a real SixDegreesUseCase call (personA=1, personB=2 per the + // fixture graph, LLD §3) - autowire com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase + // and call sixDegreesUseCase.compute("nm0000001", "nm0000002", 7) here, then assert + // cacheManager.getCache("six-degrees").get("1-2") is not null (matching the "min-max" key + // convention, LLD §6) before calling personAdminUseCase.patch(...) below and re-asserting null. + personAdminUseCase.patch("nm0000001", new PatchPersonRequest("Kevin Bacon Jr.", null, null, List.of(), 0)); + + assertThat(cacheManager.getCache("six-degrees").get("1-2")).isNull(); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=CacheEvictionIntegrationTest` +Expected: initially FAIL only if the eviction wiring from Tasks 3.2/5.2 has any bug - if Tasks 3.2/5.2 were +implemented and verified correctly already, this test should pass immediately; treat a failure here as a +signal to revisit those tasks' `@CacheEvict`/`@Caching` annotations, not as expected red-then-green TDD +churn (this task is a **verification** of already-built behavior, not new production code). + +- [ ] **Step 3: Fill in the `six-degrees` priming call from the comment above**, then re-run + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=CacheEvictionIntegrationTest` +Expected: PASS, all three tests green. + +- [ ] **Step 4: Commit** + +```bash +git add src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheEvictionIntegrationTest.java +git commit -m "Add integration test proving cache eviction reaches real Redis for title/rating/person writes" +``` + +**Phase 5 checkpoint**: all admin CRUD from `docs/crud-expansion-design.md` §5 is complete and cache-safe, +now verified against real Redis rather than assumed correct from the annotations alone. +Phases 3-5 are independent of Phases 6-8 below (both depend only on Phase 1/2) - if executing with +subagents, these two groups can run in parallel. + +--- + +## Phase 6: Watchlist + +### Task 6.1: `Visibility`, `WatchlistView`/`WatchlistItemView`, `WatchlistRepository` + +**Files:** +- Create: `src/main/resources/db/migration/V8__watchlists.sql` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/Visibility.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/WatchlistView.java`, `WatchlistItemView.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/repository/WatchlistRepository.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcWatchlistRepository.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcWatchlistRepositoryIntegrationTest.java` + +**Interfaces:** +- Consumes: `CurrentUser` (already built in Task 1.6 - `WatchlistController`, Task 6.2, uses it) +- Produces: `Visibility.PUBLIC`/`PRIVATE` (reused by Reviews/Lists, Phases 7-8). `WatchlistView(int id, int userId, Visibility visibility, int version, List items)`, `WatchlistItemView(String titleId, String primaryTitle, Instant addedAt)`. `WatchlistRepository.findOrCreateByUserId(int userId) -> WatchlistView`, `findByUserId(int userId) -> Optional`, `addItem`/`removeItem(int watchlistId, int titleId) -> WriteResult`, `updateVisibility(int watchlistId, Visibility, int expectedVersion) -> WriteResult`. + +- [ ] **Step 1: Write the failing test** + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class JdbcWatchlistRepositoryIntegrationTest { + + @Autowired + JdbcWatchlistRepository repository; + @Autowired + UserRepository userRepository; + + @Test + void findOrCreateByUserIdCreatesAnEmptyPrivateWatchlistOnFirstAccess() { + int userId = userRepository.insert("watchlist-user@example.com", "hash", "User", Role.USER).id(); + + var watchlist = repository.findOrCreateByUserId(userId); + + assertThat(watchlist.userId()).isEqualTo(userId); + assertThat(watchlist.visibility()).isEqualTo(Visibility.PRIVATE); + assertThat(watchlist.items()).isEmpty(); + } + + @Test + void findOrCreateByUserIdIsIdempotent() { + int userId = userRepository.insert("watchlist-user2@example.com", "hash", "User", Role.USER).id(); + + var first = repository.findOrCreateByUserId(userId); + var second = repository.findOrCreateByUserId(userId); + + assertThat(first.id()).isEqualTo(second.id()); + } + + @Test + void addItemThenFindOrCreateIncludesIt() { + int userId = userRepository.insert("watchlist-user3@example.com", "hash", "User", Role.USER).id(); + var watchlist = repository.findOrCreateByUserId(userId); + + repository.addItem(watchlist.id(), 100); + + assertThat(repository.findOrCreateByUserId(userId).items()).extracting("titleId").contains("tt0000100"); + } + + @Test + void removeItemExcludesItFromTheWatchlist() { + int userId = userRepository.insert("watchlist-user4@example.com", "hash", "User", Role.USER).id(); + var watchlist = repository.findOrCreateByUserId(userId); + repository.addItem(watchlist.id(), 100); + + repository.removeItem(watchlist.id(), 100); + + assertThat(repository.findOrCreateByUserId(userId).items()).isEmpty(); + } + + @Test + void updateVisibilityChangesItAndBumpsVersion() { + int userId = userRepository.insert("watchlist-user5@example.com", "hash", "User", Role.USER).id(); + var watchlist = repository.findOrCreateByUserId(userId); + + var result = repository.updateVisibility(watchlist.id(), Visibility.PUBLIC, watchlist.version()); + + assertThat(result).isEqualTo(WriteResult.SUCCESS); + assertThat(repository.findByUserId(userId).orElseThrow().visibility()).isEqualTo(Visibility.PUBLIC); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcWatchlistRepositoryIntegrationTest` +Expected: FAIL - none of these classes exist yet. + +- [ ] **Step 3: Create the migration** + +```sql +CREATE TABLE watchlists ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users (id), + visibility TEXT NOT NULL DEFAULT 'PRIVATE', + version INTEGER NOT NULL DEFAULT 0, + deleted_at TIMESTAMPTZ +); + +CREATE UNIQUE INDEX idx_watchlists_user_id ON watchlists (user_id) WHERE deleted_at IS NULL; + +CREATE TABLE watchlist_items ( + watchlist_id INTEGER NOT NULL REFERENCES watchlists (id), + title_id INTEGER NOT NULL REFERENCES title_basics (tconst), + added_at TIMESTAMPTZ NOT NULL DEFAULT now(), + PRIMARY KEY (watchlist_id, title_id) +); +``` + +- [ ] **Step 4: Create `Visibility`, `WatchlistView`, `WatchlistItemView`** + +```java +package com.ludovictemgoua.imdb.domain.model; + +public enum Visibility { PUBLIC, PRIVATE } +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.time.Instant; + +public record WatchlistItemView(String titleId, String primaryTitle, Instant addedAt) { +} +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record WatchlistView(int id, int userId, Visibility visibility, int version, List items) { +} +``` + +- [ ] **Step 5: Create `WatchlistRepository` and `JdbcWatchlistRepository`** + +```java +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; + +import java.util.Optional; + +public interface WatchlistRepository { + + WatchlistView findOrCreateByUserId(int userId); + + Optional findByUserId(int userId); + + WriteResult addItem(int watchlistId, int titleId); + + WriteResult removeItem(int watchlistId, int titleId); + + WriteResult updateVisibility(int watchlistId, Visibility visibility, int expectedVersion); +} +``` + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.model.WatchlistItemView; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; +import com.ludovictemgoua.imdb.domain.repository.WatchlistRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; + +import java.time.Instant; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Repository +public class JdbcWatchlistRepository implements WatchlistRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public JdbcWatchlistRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + @Override + public WatchlistView findOrCreateByUserId(int userId) { + return findByUserId(userId).orElseGet(() -> create(userId)); + } + + @Override + public Optional findByUserId(int userId) { + String sql = "SELECT id, user_id, visibility, version FROM watchlists WHERE user_id = :userId AND deleted_at IS NULL"; + return jdbc.query(sql, Map.of("userId", userId), (rs, rowNum) -> new int[]{rs.getInt("id")}) + .stream().findFirst() + .map(row -> hydrate(row[0], userId)); + } + + @Override + public WriteResult addItem(int watchlistId, int titleId) { + String sql = """ + INSERT INTO watchlist_items (watchlist_id, title_id) VALUES (:watchlistId, :titleId) + ON CONFLICT DO NOTHING + """; + jdbc.update(sql, Map.of("watchlistId", watchlistId, "titleId", titleId)); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult removeItem(int watchlistId, int titleId) { + jdbc.update("DELETE FROM watchlist_items WHERE watchlist_id = :watchlistId AND title_id = :titleId", + Map.of("watchlistId", watchlistId, "titleId", titleId)); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult updateVisibility(int watchlistId, Visibility visibility, int expectedVersion) { + String sql = """ + UPDATE watchlists SET visibility = :visibility, version = version + 1 + WHERE id = :id AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("visibility", visibility.name()).addValue("id", watchlistId) + .addValue("expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + private WatchlistView create(int userId) { + String sql = "INSERT INTO watchlists (user_id) VALUES (:userId)"; + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbc.update(sql, new MapSqlParameterSource("userId", userId), keyHolder, new String[]{"id"}); + return new WatchlistView(keyHolder.getKey().intValue(), userId, Visibility.PRIVATE, 0, List.of()); + } + + private WatchlistView hydrate(int watchlistId, int userId) { + String metaSql = "SELECT visibility, version FROM watchlists WHERE id = :id"; + var meta = jdbc.queryForMap(metaSql, Map.of("id", watchlistId)); + String itemsSql = """ + SELECT tb.tconst, tb.primary_title, wi.added_at + FROM watchlist_items wi JOIN title_basics tb ON tb.tconst = wi.title_id + WHERE wi.watchlist_id = :watchlistId AND tb.deleted_at IS NULL + ORDER BY wi.added_at + """; + List items = jdbc.query(itemsSql, Map.of("watchlistId", watchlistId), + (rs, rowNum) -> new WatchlistItemView(ImdbIds.formatTitleId(rs.getInt("tconst")), + rs.getString("primary_title"), rs.getTimestamp("added_at").toInstant())); + return new WatchlistView(watchlistId, userId, Visibility.valueOf((String) meta.get("visibility")), + ((Number) meta.get("version")).intValue(), items); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcWatchlistRepositoryIntegrationTest` +Expected: PASS. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/resources/db/migration/V8__watchlists.sql src/main/java/com/ludovictemgoua/imdb/domain/model/Visibility.java src/main/java/com/ludovictemgoua/imdb/domain/model/WatchlistView.java src/main/java/com/ludovictemgoua/imdb/domain/model/WatchlistItemView.java src/main/java/com/ludovictemgoua/imdb/domain/repository/WatchlistRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcWatchlistRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcWatchlistRepositoryIntegrationTest.java +git commit -m "Add watchlists/watchlist_items tables and WatchlistRepository" +``` + +### Task 6.2: `WatchlistUseCase`, `WatchlistController` + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/WatchlistUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/WatchlistUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/VisibilityRequest.java`, `AddWatchlistItemRequest.java` (records) +- Create: `src/main/java/com/ludovictemgoua/imdb/presentation/WatchlistController.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/WatchlistUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/WatchlistControllerTest.java` + +**Interfaces:** +- Consumes: `WatchlistRepository` (Task 6.1), `CurrentUser` (Task 1.6) +- Produces: `GET/PUT /api/v1/watchlist`, `POST/DELETE /api/v1/watchlist/items{,/{titleId}}`, + `GET /api/v1/users/{userId}/watchlist` - the full watchlist endpoint set from + `docs/crud-expansion-design.md` §4.2. + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; +import com.ludovictemgoua.imdb.domain.repository.WatchlistRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class WatchlistUseCaseImplTest { + + @Mock + WatchlistRepository watchlistRepository; + + @Test + void getOwnDelegatesToFindOrCreate() { + var view = new WatchlistView(1, 7, Visibility.PRIVATE, 0, List.of()); + given(watchlistRepository.findOrCreateByUserId(7)).willReturn(view); + + assertThat(new WatchlistUseCaseImpl(watchlistRepository).getOwn(7)).isSameAs(view); + } + + @Test + void getForUserReturnsThePublicWatchlistToAnyone() { + var view = new WatchlistView(1, 7, Visibility.PUBLIC, 0, List.of()); + given(watchlistRepository.findByUserId(7)).willReturn(Optional.of(view)); + + var result = new WatchlistUseCaseImpl(watchlistRepository).getForUser(Optional.empty(), 7); + + assertThat(result).isSameAs(view); + } + + @Test + void getForUserThrowsNotFoundForAPrivateWatchlistViewedByAStranger() { + var view = new WatchlistView(1, 7, Visibility.PRIVATE, 0, List.of()); + given(watchlistRepository.findByUserId(7)).willReturn(Optional.of(view)); + var useCase = new WatchlistUseCaseImpl(watchlistRepository); + + assertThatThrownBy(() -> useCase.getForUser(Optional.of(99), 7)) + .isInstanceOf(com.ludovictemgoua.imdb.domain.exception.NotFoundException.class); + } + + @Test + void getForUserAllowsTheOwnerToViewTheirOwnPrivateWatchlist() { + var view = new WatchlistView(1, 7, Visibility.PRIVATE, 0, List.of()); + given(watchlistRepository.findByUserId(7)).willReturn(Optional.of(view)); + + var result = new WatchlistUseCaseImpl(watchlistRepository).getForUser(Optional.of(7), 7); + + assertThat(result).isSameAs(view); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=WatchlistUseCaseImplTest` +Expected: FAIL - `WatchlistUseCaseImpl` doesn't exist yet. + +- [ ] **Step 3: Create the request records and `WatchlistUseCase`/`Impl`** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.Visibility; +import jakarta.validation.constraints.NotNull; + +public record VisibilityRequest(@NotNull Visibility visibility) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +public record AddWatchlistItemRequest(@NotBlank String titleId) { +} +``` + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; + +import java.util.Optional; + +public interface WatchlistUseCase { + + WatchlistView getOwn(int userId); + + WatchlistView getForUser(Optional viewerUserId, int targetUserId); + + void addItem(int userId, String titleId); + + void removeItem(int userId, String titleId); + + void updateVisibility(int userId, Visibility visibility); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.WatchlistUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; +import com.ludovictemgoua.imdb.domain.repository.WatchlistRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class WatchlistUseCaseImpl implements WatchlistUseCase { + + private final WatchlistRepository watchlistRepository; + + public WatchlistUseCaseImpl(WatchlistRepository watchlistRepository) { + this.watchlistRepository = watchlistRepository; + } + + @Override + public WatchlistView getOwn(int userId) { + return watchlistRepository.findOrCreateByUserId(userId); + } + + @Override + public WatchlistView getForUser(Optional viewerUserId, int targetUserId) { + WatchlistView view = watchlistRepository.findByUserId(targetUserId) + .orElseThrow(() -> new NotFoundException("No watchlist for that user")); + boolean isOwner = viewerUserId.isPresent() && viewerUserId.get() == targetUserId; + if (view.visibility() == Visibility.PRIVATE && !isOwner) { + throw new NotFoundException("No watchlist for that user"); + } + return view; + } + + @Override + public void addItem(int userId, String titleId) { + var watchlist = watchlistRepository.findOrCreateByUserId(userId); + watchlistRepository.addItem(watchlist.id(), ImdbIds.parseTitleId(titleId)); + } + + @Override + public void removeItem(int userId, String titleId) { + var watchlist = watchlistRepository.findOrCreateByUserId(userId); + watchlistRepository.removeItem(watchlist.id(), ImdbIds.parseTitleId(titleId)); + } + + @Override + public void updateVisibility(int userId, Visibility visibility) { + var watchlist = watchlistRepository.findOrCreateByUserId(userId); + var result = watchlistRepository.updateVisibility(watchlist.id(), visibility, watchlist.version()); + if (result == com.ludovictemgoua.imdb.domain.repository.WriteResult.VERSION_CONFLICT) { + throw new ConflictException("Watchlist was modified concurrently - retry"); + } + } +} +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=WatchlistUseCaseImplTest` +Expected: PASS, 4 tests green. + +- [ ] **Step 5: Write the failing controller test** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.WatchlistUseCase; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; +import java.util.Optional; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(WatchlistController.class) +class WatchlistControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + WatchlistUseCase watchlistUseCase; + + @Test + void getOwnWatchlistRequiresAuthentication() throws Exception { + mockMvc.perform(get("/api/v1/watchlist")) + .andExpect(status().isUnauthorized()); + } + + @Test + void getOwnWatchlistReturnsItForAnAuthenticatedUser() throws Exception { + given(watchlistUseCase.getOwn(7)).willReturn(new WatchlistView(1, 7, Visibility.PRIVATE, 0, List.of())); + + mockMvc.perform(get("/api/v1/watchlist").with(SecurityMockMvcRequestPostProcessors.user("7").roles("USER"))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.visibility").value("PRIVATE")); + } + + @Test + void getUserWatchlistIsAccessibleAnonymouslyWhenPublic() throws Exception { + given(watchlistUseCase.getForUser(Optional.empty(), 7)) + .willReturn(new WatchlistView(1, 7, Visibility.PUBLIC, 0, List.of())); + + mockMvc.perform(get("/api/v1/users/7/watchlist")) + .andExpect(status().isOk()); + } +} +``` + +- [ ] **Step 6: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=WatchlistControllerTest` +Expected: FAIL - `WatchlistController` doesn't exist yet. + +- [ ] **Step 7: Create `WatchlistController`** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.AddWatchlistItemRequest; +import com.ludovictemgoua.imdb.application.VisibilityRequest; +import com.ludovictemgoua.imdb.application.contracts.WatchlistUseCase; +import com.ludovictemgoua.imdb.domain.model.WatchlistView; +import com.ludovictemgoua.imdb.infrastructure.security.CurrentUser; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class WatchlistController { + + private final WatchlistUseCase watchlistUseCase; + + public WatchlistController(WatchlistUseCase watchlistUseCase) { + this.watchlistUseCase = watchlistUseCase; + } + + @GetMapping("/api/v1/watchlist") + public WatchlistView getOwn(Authentication authentication) { + return watchlistUseCase.getOwn(CurrentUser.requireId(authentication)); + } + + @PostMapping("/api/v1/watchlist/items") + @ResponseStatus(HttpStatus.CREATED) + public void addItem(Authentication authentication, @Valid @RequestBody AddWatchlistItemRequest request) { + watchlistUseCase.addItem(CurrentUser.requireId(authentication), request.titleId()); + } + + @DeleteMapping("/api/v1/watchlist/items/{titleId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void removeItem(Authentication authentication, @PathVariable String titleId) { + watchlistUseCase.removeItem(CurrentUser.requireId(authentication), titleId); + } + + @PutMapping("/api/v1/watchlist/visibility") + public void updateVisibility(Authentication authentication, @Valid @RequestBody VisibilityRequest request) { + watchlistUseCase.updateVisibility(CurrentUser.requireId(authentication), request.visibility()); + } + + @GetMapping("/api/v1/users/{userId}/watchlist") + public WatchlistView getForUser(Authentication authentication, @PathVariable int userId) { + return watchlistUseCase.getForUser(CurrentUser.idOf(authentication), userId); + } +} +``` + +`getOwn`/`addItem`/`removeItem`/`updateVisibility` are **not** in the security filter chain's `permitAll()` +list (Task 1.3), so Spring Security already rejects an anonymous request with `401` before this +controller ever runs, verified by `getOwnWatchlistRequiresAuthentication` above - +`CurrentUser.requireId`'s `IllegalStateException` for a missing user is an internal-consistency +safety net, not the primary 401 mechanism. + +- [ ] **Step 8: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=WatchlistControllerTest` +Expected: PASS, 3 tests green. + +- [ ] **Step 9: Run the full unit and integration suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 10: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/application/contracts/WatchlistUseCase.java src/main/java/com/ludovictemgoua/imdb/application/WatchlistUseCaseImpl.java src/main/java/com/ludovictemgoua/imdb/application/VisibilityRequest.java src/main/java/com/ludovictemgoua/imdb/application/AddWatchlistItemRequest.java src/main/java/com/ludovictemgoua/imdb/presentation/WatchlistController.java src/test/java/com/ludovictemgoua/imdb/application/WatchlistUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/WatchlistControllerTest.java +git commit -m "Add WatchlistUseCase and WatchlistController" +``` + +**Phase 6 checkpoint**: watchlists are fully live. This is the template Phase 8 (Custom Lists) follows +closely (public/private visibility, ownership checks, 404-not-403 for private resources). + +--- + +## Phase 7: Reviews + +### Task 7.1: `Review`/`RatingAggregate`, `ReviewRepository` + +**Files:** +- Create: `src/main/resources/db/migration/V9__reviews.sql` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/Review.java`, `RatingAggregate.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/repository/ReviewRepository.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcReviewRepository.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcReviewRepositoryIntegrationTest.java` + +**Interfaces:** +- Produces: `Review(int id, int userId, int titleId, int rating, String body, int version, Instant createdAt, Instant updatedAt)`, `RatingAggregate(double average, int count)`. `ReviewRepository.insert`, `findByUserAndTitle`, `update`, `softDelete`, `findByTitle`/`findByUser` (paged), `aggregateForTitle(int titleId) -> RatingAggregate` (average `0.0`/count `0` when no reviews exist). + +- [ ] **Step 1: Write the failing integration test** + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.within; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class JdbcReviewRepositoryIntegrationTest { + + @Autowired + JdbcReviewRepository repository; + @Autowired + UserRepository userRepository; + + @Test + void insertThenFindByUserAndTitleRoundTrips() { + int userId = userRepository.insert("reviewer1@example.com", "hash", "Reviewer", Role.USER).id(); + + var review = repository.insert(userId, 100, 9, "Great film"); + + var found = repository.findByUserAndTitle(userId, 100).orElseThrow(); + assertThat(found.id()).isEqualTo(review.id()); + assertThat(found.rating()).isEqualTo(9); + assertThat(found.version()).isEqualTo(0); + } + + @Test + void updateBumpsVersionAndPersists() { + int userId = userRepository.insert("reviewer2@example.com", "hash", "Reviewer", Role.USER).id(); + var review = repository.insert(userId, 100, 5, "Meh"); + + var result = repository.update(review.id(), 8, "Actually great", review.version()); + + assertThat(result).isEqualTo(WriteResult.SUCCESS); + var updated = repository.findByUserAndTitle(userId, 100).orElseThrow(); + assertThat(updated.rating()).isEqualTo(8); + assertThat(updated.version()).isEqualTo(1); + } + + @Test + void softDeleteExcludesItFromFindByUserAndTitle() { + int userId = userRepository.insert("reviewer3@example.com", "hash", "Reviewer", Role.USER).id(); + var review = repository.insert(userId, 100, 5, "Meh"); + + repository.softDelete(review.id(), review.version()); + + assertThat(repository.findByUserAndTitle(userId, 100)).isEmpty(); + } + + @Test + void aggregateForTitleAveragesAcrossReviewers() { + int user1 = userRepository.insert("reviewer4@example.com", "hash", "R4", Role.USER).id(); + int user2 = userRepository.insert("reviewer5@example.com", "hash", "R5", Role.USER).id(); + repository.insert(user1, 200, 10, null); + repository.insert(user2, 200, 6, null); + + var aggregate = repository.aggregateForTitle(200); + + assertThat(aggregate.count()).isEqualTo(2); + assertThat(aggregate.average()).isCloseTo(8.0, within(0.01)); + } + + @Test + void aggregateForTitleIsZeroWhenNoReviewsExist() { + var aggregate = repository.aggregateForTitle(999999); + + assertThat(aggregate.count()).isEqualTo(0); + assertThat(aggregate.average()).isEqualTo(0.0); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcReviewRepositoryIntegrationTest` +Expected: FAIL. + +- [ ] **Step 3: Create the migration** + +```sql +CREATE TABLE reviews ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users (id), + title_id INTEGER NOT NULL REFERENCES title_basics (tconst), + rating INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 10), + body TEXT, + version INTEGER NOT NULL DEFAULT 0, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + deleted_at TIMESTAMPTZ +); + +CREATE UNIQUE INDEX idx_reviews_user_title ON reviews (user_id, title_id) WHERE deleted_at IS NULL; +``` + +- [ ] **Step 4: Create `Review`/`RatingAggregate`** + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.time.Instant; + +public record Review(int id, int userId, int titleId, int rating, String body, int version, + Instant createdAt, Instant updatedAt) { +} +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +public record RatingAggregate(double average, int count) { +} +``` + +- [ ] **Step 5: Create `ReviewRepository` and `JdbcReviewRepository`** + +```java +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.RatingAggregate; +import com.ludovictemgoua.imdb.domain.model.Review; + +import java.util.Optional; + +public interface ReviewRepository { + + Review insert(int userId, int titleId, int rating, String body); + + Optional findByUserAndTitle(int userId, int titleId); + + WriteResult update(int reviewId, int rating, String body, int expectedVersion); + + WriteResult softDelete(int reviewId, int expectedVersion); + + PagedResult findByTitle(int titleId, int page, int size); + + PagedResult findByUser(int userId, int page, int size); + + RatingAggregate aggregateForTitle(int titleId); +} +``` + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.RatingAggregate; +import com.ludovictemgoua.imdb.domain.model.Review; +import com.ludovictemgoua.imdb.domain.repository.ReviewRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Repository +public class JdbcReviewRepository implements ReviewRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public JdbcReviewRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + @Override + public Review insert(int userId, int titleId, int rating, String body) { + String sql = """ + INSERT INTO reviews (user_id, title_id, rating, body) VALUES (:userId, :titleId, :rating, :body) + """; + var params = new MapSqlParameterSource() + .addValue("userId", userId).addValue("titleId", titleId) + .addValue("rating", rating).addValue("body", body); + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbc.update(sql, params, keyHolder, new String[]{"id"}); + return findByUserAndTitle(userId, titleId).orElseThrow(); + } + + @Override + public Optional findByUserAndTitle(int userId, int titleId) { + String sql = """ + SELECT * FROM reviews WHERE user_id = :userId AND title_id = :titleId AND deleted_at IS NULL + """; + return jdbc.query(sql, Map.of("userId", userId, "titleId", titleId), JdbcReviewRepository::mapReview) + .stream().findFirst(); + } + + @Override + public WriteResult update(int reviewId, int rating, String body, int expectedVersion) { + String sql = """ + UPDATE reviews SET rating = :rating, body = :body, version = version + 1, updated_at = now() + WHERE id = :id AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("rating", rating).addValue("body", body) + .addValue("id", reviewId).addValue("expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public WriteResult softDelete(int reviewId, int expectedVersion) { + String sql = """ + UPDATE reviews SET deleted_at = now() WHERE id = :id AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = Map.of("id", reviewId, "expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public PagedResult findByTitle(int titleId, int page, int size) { + String dataSql = """ + SELECT * FROM reviews WHERE title_id = :titleId AND deleted_at IS NULL + ORDER BY created_at DESC LIMIT :limit OFFSET :offset + """; + String countSql = "SELECT count(*) FROM reviews WHERE title_id = :titleId AND deleted_at IS NULL"; + var params = new MapSqlParameterSource() + .addValue("titleId", titleId).addValue("limit", size).addValue("offset", (long) page * size); + List content = jdbc.query(dataSql, params, JdbcReviewRepository::mapReview); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + @Override + public PagedResult findByUser(int userId, int page, int size) { + String dataSql = """ + SELECT * FROM reviews WHERE user_id = :userId AND deleted_at IS NULL + ORDER BY created_at DESC LIMIT :limit OFFSET :offset + """; + String countSql = "SELECT count(*) FROM reviews WHERE user_id = :userId AND deleted_at IS NULL"; + var params = new MapSqlParameterSource() + .addValue("userId", userId).addValue("limit", size).addValue("offset", (long) page * size); + List content = jdbc.query(dataSql, params, JdbcReviewRepository::mapReview); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + @Override + public RatingAggregate aggregateForTitle(int titleId) { + String sql = """ + SELECT COALESCE(AVG(rating), 0) AS avg_rating, COUNT(*) AS review_count + FROM reviews WHERE title_id = :titleId AND deleted_at IS NULL + """; + return jdbc.queryForObject(sql, Map.of("titleId", titleId), (rs, rowNum) -> + new RatingAggregate(rs.getDouble("avg_rating"), rs.getInt("review_count"))); + } + + private static Review mapReview(ResultSet rs, int rowNum) throws SQLException { + return new Review(rs.getInt("id"), rs.getInt("user_id"), rs.getInt("title_id"), rs.getInt("rating"), + rs.getString("body"), rs.getInt("version"), + rs.getTimestamp("created_at").toInstant(), rs.getTimestamp("updated_at").toInstant()); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcReviewRepositoryIntegrationTest` +Expected: PASS, 5 tests green. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/resources/db/migration/V9__reviews.sql src/main/java/com/ludovictemgoua/imdb/domain/model/Review.java src/main/java/com/ludovictemgoua/imdb/domain/model/RatingAggregate.java src/main/java/com/ludovictemgoua/imdb/domain/repository/ReviewRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcReviewRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcReviewRepositoryIntegrationTest.java +git commit -m "Add reviews table and ReviewRepository" +``` + +### Task 7.2: `ReviewUseCase`, `ReviewController`, `TitleDetail.userRating*` wiring, cache eviction + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/ReviewUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/ReviewRequest.java` (record) +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingReviewUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/presentation/ReviewController.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/domain/model/TitleDetail.java` +- Modify: `src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImplTest.java` (extend) +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/ReviewControllerTest.java` + +**Interfaces:** +- Consumes: `ReviewRepository` (Task 7.1), `CurrentUser` (Task 1.6) +- Produces: the full reviews endpoint set (`docs/crud-expansion-design.md` §4.3), and + `TitleDetail.userRatingAverage()`/`userRatingCount()` populated from `ReviewRepository.aggregateForTitle`. + +- [ ] **Step 1: Write the failing unit tests** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.model.Review; +import com.ludovictemgoua.imdb.domain.repository.ReviewRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.Instant; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class ReviewUseCaseImplTest { + + @Mock + ReviewRepository reviewRepository; + + @Test + void createThrowsConflictWhenAReviewAlreadyExists() { + given(reviewRepository.findByUserAndTitle(7, 100)).willReturn( + Optional.of(new Review(1, 7, 100, 8, "Existing", 0, Instant.now(), Instant.now()))); + var useCase = new ReviewUseCaseImpl(reviewRepository); + + assertThatThrownBy(() -> useCase.create(7, "tt0000100", new ReviewRequest(9, "New", 0))) + .isInstanceOf(ConflictException.class); + } + + @Test + void createInsertsWhenNoneExistsYet() { + given(reviewRepository.findByUserAndTitle(7, 100)).willReturn(Optional.empty()); + var created = new Review(1, 7, 100, 9, "New", 0, Instant.now(), Instant.now()); + given(reviewRepository.insert(7, 100, 9, "New")).willReturn(created); + + var result = new ReviewUseCaseImpl(reviewRepository).create(7, "tt0000100", new ReviewRequest(9, "New", 0)); + + assertThat(result.rating()).isEqualTo(9); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ReviewUseCaseImplTest` +Expected: FAIL. + +- [ ] **Step 3: Create `ReviewRequest`, `ReviewUseCase`/`Impl`** + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; + +public record ReviewRequest(@Min(1) @Max(10) int rating, String body, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Review; + +public interface ReviewUseCase { + + Review create(int userId, String titleId, ReviewRequest request); + + Review getMine(int userId, String titleId); + + Review update(int userId, String titleId, ReviewRequest request); + + void delete(int userId, String titleId, int expectedVersion); + + PagedResult listForTitle(String titleId, int page, int size); + + PagedResult listForUser(int userId, int page, int size); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Review; +import com.ludovictemgoua.imdb.domain.repository.ReviewRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +@Service +public class ReviewUseCaseImpl implements ReviewUseCase { + + private final ReviewRepository reviewRepository; + + public ReviewUseCaseImpl(ReviewRepository reviewRepository) { + this.reviewRepository = reviewRepository; + } + + @Override + public Review create(int userId, String titleId, ReviewRequest request) { + int tconst = ImdbIds.parseTitleId(titleId); + if (reviewRepository.findByUserAndTitle(userId, tconst).isPresent()) { + throw new ConflictException("You already reviewed this title - use PUT to update it"); + } + return reviewRepository.insert(userId, tconst, request.rating(), request.body()); + } + + @Override + public Review getMine(int userId, String titleId) { + return reviewRepository.findByUserAndTitle(userId, ImdbIds.parseTitleId(titleId)) + .orElseThrow(() -> new NotFoundException("You haven't reviewed this title")); + } + + @Override + public Review update(int userId, String titleId, ReviewRequest request) { + Review existing = getMine(userId, titleId); + WriteResult result = reviewRepository.update(existing.id(), request.rating(), request.body(), request.version()); + if (result == WriteResult.VERSION_CONFLICT) { + throw new ConflictException("Your review was modified concurrently - refresh and retry"); + } + return getMine(userId, titleId); + } + + @Override + public void delete(int userId, String titleId, int expectedVersion) { + Review existing = getMine(userId, titleId); + WriteResult result = reviewRepository.softDelete(existing.id(), expectedVersion); + if (result == WriteResult.VERSION_CONFLICT) { + throw new ConflictException("Your review was modified concurrently - refresh and retry"); + } + } + + @Override + public PagedResult listForTitle(String titleId, int page, int size) { + return reviewRepository.findByTitle(ImdbIds.parseTitleId(titleId), page, size); + } + + @Override + public PagedResult listForUser(int userId, int page, int size) { + return reviewRepository.findByUser(userId, page, size); + } +} +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ReviewUseCaseImplTest` +Expected: PASS. + +- [ ] **Step 5: Add `userRatingAverage`/`userRatingCount` to `TitleDetail` and wire them in `TitleDetailUseCaseImpl`** + +`TitleDetail` gains two components at the end: + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record TitleDetail(String id, String primaryTitle, String originalTitle, String titleType, + Integer startYear, Integer endYear, Integer runtimeMinutes, + List genres, RatingView rating, + List directors, List writers, + List cast, int castTotalCount, + double userRatingAverage, int userRatingCount) { +} +``` + +`TitleDetailUseCaseImpl` gains a `ReviewRepository` dependency and populates the two new fields: + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.RatingView; +import com.ludovictemgoua.imdb.domain.model.TitleDetail; +import com.ludovictemgoua.imdb.domain.repository.ReviewRepository; +import com.ludovictemgoua.imdb.domain.repository.TitleRepository; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +@Service +public class TitleDetailUseCaseImpl implements TitleDetailUseCase { + + private static final int CAST_LIMIT = 20; + + private final TitleRepository titleRepository; + private final ReviewRepository reviewRepository; + + public TitleDetailUseCaseImpl(TitleRepository titleRepository, ReviewRepository reviewRepository) { + this.titleRepository = titleRepository; + this.reviewRepository = reviewRepository; + } + + @Override + public TitleDetail getDetail(String titleId) { + int tconst = ImdbIds.parseTitleId(titleId); + var core = titleRepository.findCore(tconst) + .orElseThrow(() -> new NotFoundException("No title with id " + titleId)); + var directors = titleRepository.findDirectors(tconst); + var writers = titleRepository.findWriters(tconst); + var cast = titleRepository.findTopCast(tconst, CAST_LIMIT); + int castTotal = titleRepository.countCast(tconst); + var userRating = reviewRepository.aggregateForTitle(tconst); + return new TitleDetail( + core.id(), core.primaryTitle(), core.originalTitle(), core.titleType(), + core.startYear(), core.endYear(), core.runtimeMinutes(), core.genres(), + new RatingView(core.averageRating() == null ? 0 : core.averageRating(), + core.numVotes() == null ? 0 : core.numVotes()), + directors, writers, cast, castTotal, + userRating.average(), userRating.count()); + } +} +``` + +Update the existing `TitleDetailUseCaseImplTest` (if one exists; if not, this is the first test for this +class - either way, the existing four-argument `TitleDetail` assertions elsewhere in the test suite need +a `ReviewRepository` mock added and a stubbed `aggregateForTitle` call). Add to that test class: + +```java + @Mock + ReviewRepository reviewRepository; + + // In every existing test method that constructs `new TitleDetailUseCaseImpl(titleRepository)`, + // change the constructor call to `new TitleDetailUseCaseImpl(titleRepository, reviewRepository)` + // and stub `given(reviewRepository.aggregateForTitle(100)).willReturn(new RatingAggregate(0, 0));` + // (or the appropriate tconst or a lenient stub) before each call, matching whatever fixture tconst + // that test already uses. +``` + +- [ ] **Step 6: Run the full unit suite to catch every other place `TitleDetail`'s constructor is called** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test` +Expected: FAIL initially with compile errors everywhere `new TitleDetail(...)` or +`new TitleDetailUseCaseImpl(...)` is called with the old arity - fix each call site the compiler reports +(likely `TitleControllerTest` and any fixture-building test helper) by adding the two new arguments +(`0.0, 0` for a plain stub, or real aggregate values where the test cares). Re-run until green. + +- [ ] **Step 7: Create the cache-evicting decorator and `ReviewController`** + +```java +package com.ludovictemgoua.imdb.infrastructure.cache; + +import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.ReviewUseCaseImpl; +import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Review; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.context.annotation.Primary; +import org.springframework.stereotype.Service; + +// title-detail embeds userRatingAverage/userRatingCount (Step 5 above) - any review write must evict +// the affected title's cache entry the same way an admin rating write does (CachingTitleAdminUseCase). +@Service +@Primary +public class CachingReviewUseCase implements ReviewUseCase { + + private final ReviewUseCaseImpl delegate; + + public CachingReviewUseCase(ReviewUseCaseImpl delegate) { + this.delegate = delegate; + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public Review create(int userId, String titleId, ReviewRequest request) { + return delegate.create(userId, titleId, request); + } + + @Override + public Review getMine(int userId, String titleId) { + return delegate.getMine(userId, titleId); + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public Review update(int userId, String titleId, ReviewRequest request) { + return delegate.update(userId, titleId, request); + } + + @Override + @CacheEvict(cacheNames = "title-detail", key = "#titleId") + public void delete(int userId, String titleId, int expectedVersion) { + delegate.delete(userId, titleId, expectedVersion); + } + + @Override + public PagedResult listForTitle(String titleId, int page, int size) { + return delegate.listForTitle(titleId, page, size); + } + + @Override + public PagedResult listForUser(int userId, int page, int size) { + return delegate.listForUser(userId, page, size); + } +} +``` + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Review; +import com.ludovictemgoua.imdb.infrastructure.security.CurrentUser; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@Validated +public class ReviewController { + + private final ReviewUseCase reviewUseCase; + + public ReviewController(ReviewUseCase reviewUseCase) { + this.reviewUseCase = reviewUseCase; + } + + @PostMapping("/api/v1/titles/{titleId}/reviews") + @ResponseStatus(HttpStatus.CREATED) + public Review create(Authentication authentication, @PathVariable String titleId, + @Valid @RequestBody ReviewRequest request) { + return reviewUseCase.create(CurrentUser.requireId(authentication), titleId, request); + } + + @GetMapping("/api/v1/titles/{titleId}/reviews") + public PagedResult listForTitle( + @PathVariable String titleId, + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return reviewUseCase.listForTitle(titleId, page, size); + } + + @GetMapping("/api/v1/titles/{titleId}/reviews/me") + public Review getMine(Authentication authentication, @PathVariable String titleId) { + return reviewUseCase.getMine(CurrentUser.requireId(authentication), titleId); + } + + @PutMapping("/api/v1/titles/{titleId}/reviews/me") + public Review update(Authentication authentication, @PathVariable String titleId, + @Valid @RequestBody ReviewRequest request) { + return reviewUseCase.update(CurrentUser.requireId(authentication), titleId, request); + } + + @DeleteMapping("/api/v1/titles/{titleId}/reviews/me") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void delete(Authentication authentication, @PathVariable String titleId, @RequestParam int expectedVersion) { + reviewUseCase.delete(CurrentUser.requireId(authentication), titleId, expectedVersion); + } + + @GetMapping("/api/v1/users/{userId}/reviews") + public PagedResult listForUser( + @PathVariable int userId, + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return reviewUseCase.listForUser(userId, page, size); + } +} +``` + +Add `GET /api/v1/titles/*/reviews` (note: **not** `/reviews/me`, which needs auth) and +`GET /api/v1/users/*/reviews` to the security filter chain's `permitAll()` GET list (Task 1.3) if either +was missed there - `/api/v1/users/*/reviews` is already listed; add +`"/api/v1/titles/*/reviews"` alongside it now (`/api/v1/titles/**` already covers this as a prefix match, +so no change is actually needed - confirm this by testing `listForTitleIsPubliclyAccessible` below before +assuming so). + +- [ ] **Step 8: Write and run the controller test** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(ReviewController.class) +class ReviewControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + ReviewUseCase reviewUseCase; + + @Test + void listForTitleIsPubliclyAccessible() throws Exception { + given(reviewUseCase.listForTitle("tt0000100", 0, 20)).willReturn(new PagedResult<>(List.of(), 0, 0, 20)); + + mockMvc.perform(get("/api/v1/titles/tt0000100/reviews")) + .andExpect(status().isOk()); + } + + @Test + void getMineRequiresAuthentication() throws Exception { + mockMvc.perform(get("/api/v1/titles/tt0000100/reviews/me")) + .andExpect(status().isUnauthorized()); + } +} +``` + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ReviewControllerTest` +Expected: PASS. If `listForTitleIsPubliclyAccessible` instead returns `401`, add +`"/api/v1/titles/**"` is already present as a GET-permitted prefix (Task 1.3) - the likely real cause is +`/reviews/me` also incorrectly matching that same prefix and being wrongly public; if so, order Spring +Security's matchers so the more specific `/reviews/me` pattern is declared **before** the broader +`/api/v1/titles/**` pattern (Spring Security evaluates `authorizeHttpRequests` matchers in declaration +order, first match wins), moving `"/api/v1/titles/*/reviews/me"` is not itself a GET-permitted pattern +today so this should not occur - if it does, it means the broad `/api/v1/titles/**` permit is matching +`/me` unintentionally, and the fix is adding an explicit +`.requestMatchers(HttpMethod.GET, "/api/v1/titles/*/reviews/me").authenticated()` **above** the broader +permit rule in `SecurityConfig`. + +- [ ] **Step 9: Run the full unit and integration suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 10: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/application/contracts/ReviewUseCase.java src/main/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImpl.java src/main/java/com/ludovictemgoua/imdb/application/ReviewRequest.java src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingReviewUseCase.java src/main/java/com/ludovictemgoua/imdb/presentation/ReviewController.java src/main/java/com/ludovictemgoua/imdb/domain/model/TitleDetail.java src/main/java/com/ludovictemgoua/imdb/application/TitleDetailUseCaseImpl.java src/test/ +git commit -m "Add ReviewUseCase/ReviewController and wire user ratings into title detail" +``` + +**Phase 7 checkpoint**: reviews are fully live, and title detail now shows both the original IMDb rating +and the aggregate user rating side by side. + +--- + +## Phase 8: Custom Lists + +### Task 8.1: `CustomList`/`CustomListView`/`ListItemView`, `CustomListRepository` + +**Files:** +- Create: `src/main/resources/db/migration/V10__lists.sql` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/model/CustomList.java`, `CustomListView.java`, `ListItemView.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/domain/repository/CustomListRepository.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCustomListRepository.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCustomListRepositoryIntegrationTest.java` + +**Interfaces:** +- Produces: `CustomList(int id, int userId, String name, Visibility visibility, int version)`, + `ListItemView(String titleId, String primaryTitle, Instant addedAt)`, + `CustomListView(int id, int userId, String name, Visibility visibility, int version, List items)`. + `CustomListRepository.insert(int userId, String name, Visibility) -> CustomList`, + `findById(int listId) -> Optional`, + `update(int listId, String name, Visibility, int expectedVersion) -> WriteResult`, + `softDelete(int listId, int expectedVersion) -> WriteResult`, + `findByUser(int userId, int page, int size) -> PagedResult`, + `findPublic(int page, int size) -> PagedResult`, + `addItem(int listId, int titleId) -> WriteResult`, `removeItem(int listId, int titleId) -> WriteResult`. + +- [ ] **Step 1: Write the failing integration test** + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.TestcontainersConfiguration; +import com.ludovictemgoua.imdb.domain.model.Role; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.repository.UserRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.transaction.annotation.Transactional; + +import static org.assertj.core.api.Assertions.assertThat; + +@Import(TestcontainersConfiguration.class) +@SpringBootTest +@Transactional +@Sql("/fixtures/fixture-data.sql") +class JdbcCustomListRepositoryIntegrationTest { + + @Autowired + JdbcCustomListRepository repository; + @Autowired + UserRepository userRepository; + + @Test + void insertThenFindByIdRoundTrips() { + int userId = userRepository.insert("lister1@example.com", "hash", "Lister", Role.USER).id(); + + var created = repository.insert(userId, "Best of 2024", Visibility.PRIVATE); + + var found = repository.findById(created.id()).orElseThrow(); + assertThat(found.name()).isEqualTo("Best of 2024"); + assertThat(found.items()).isEmpty(); + } + + @Test + void addItemThenFindByIdIncludesIt() { + int userId = userRepository.insert("lister2@example.com", "hash", "Lister", Role.USER).id(); + var created = repository.insert(userId, "Watch Later", Visibility.PUBLIC); + + repository.addItem(created.id(), 100); + + assertThat(repository.findById(created.id()).orElseThrow().items()) + .extracting("titleId").contains("tt0000100"); + } + + @Test + void removeItemExcludesItFromTheList() { + int userId = userRepository.insert("lister3@example.com", "hash", "Lister", Role.USER).id(); + var created = repository.insert(userId, "Watch Later", Visibility.PUBLIC); + repository.addItem(created.id(), 100); + + repository.removeItem(created.id(), 100); + + assertThat(repository.findById(created.id()).orElseThrow().items()).isEmpty(); + } + + @Test + void updateRenamesAndBumpsVersion() { + int userId = userRepository.insert("lister4@example.com", "hash", "Lister", Role.USER).id(); + var created = repository.insert(userId, "Old Name", Visibility.PRIVATE); + + var result = repository.update(created.id(), "New Name", Visibility.PUBLIC, created.version()); + + assertThat(result).isEqualTo(WriteResult.SUCCESS); + var updated = repository.findById(created.id()).orElseThrow(); + assertThat(updated.name()).isEqualTo("New Name"); + assertThat(updated.visibility()).isEqualTo(Visibility.PUBLIC); + } + + @Test + void softDeleteExcludesItFromFindById() { + int userId = userRepository.insert("lister5@example.com", "hash", "Lister", Role.USER).id(); + var created = repository.insert(userId, "Delete Me", Visibility.PRIVATE); + + repository.softDelete(created.id(), created.version()); + + assertThat(repository.findById(created.id())).isEmpty(); + } + + @Test + void findPublicOnlyReturnsPublicLists() { + int userId = userRepository.insert("lister6@example.com", "hash", "Lister", Role.USER).id(); + repository.insert(userId, "Public List", Visibility.PUBLIC); + repository.insert(userId, "Private List", Visibility.PRIVATE); + + var publicLists = repository.findPublic(0, 20); + + assertThat(publicLists.content()).extracting("name").contains("Public List").doesNotContain("Private List"); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcCustomListRepositoryIntegrationTest` +Expected: FAIL. + +- [ ] **Step 3: Create the migration** + +```sql +CREATE TABLE lists ( + id SERIAL PRIMARY KEY, + user_id INTEGER NOT NULL REFERENCES users (id), + name TEXT NOT NULL, + visibility TEXT NOT NULL DEFAULT 'PRIVATE', + version INTEGER NOT NULL DEFAULT 0, + deleted_at TIMESTAMPTZ +); + +CREATE TABLE list_items ( + list_id INTEGER NOT NULL REFERENCES lists (id), + title_id INTEGER NOT NULL REFERENCES title_basics (tconst), + added_at TIMESTAMPTZ NOT NULL DEFAULT now(), + ordering SERIAL, + PRIMARY KEY (list_id, title_id) +); +``` + +- [ ] **Step 4: Create the domain models** + +```java +package com.ludovictemgoua.imdb.domain.model; + +public record CustomList(int id, int userId, String name, Visibility visibility, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.time.Instant; + +public record ListItemView(String titleId, String primaryTitle, Instant addedAt) { +} +``` + +```java +package com.ludovictemgoua.imdb.domain.model; + +import java.util.List; + +public record CustomListView(int id, int userId, String name, Visibility visibility, int version, + List items) { +} +``` + +- [ ] **Step 5: Create `CustomListRepository` and `JdbcCustomListRepository`** + +```java +package com.ludovictemgoua.imdb.domain.repository; + +import com.ludovictemgoua.imdb.domain.model.CustomList; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Visibility; + +import java.util.Optional; + +public interface CustomListRepository { + + CustomList insert(int userId, String name, Visibility visibility); + + Optional findById(int listId); + + WriteResult update(int listId, String name, Visibility visibility, int expectedVersion); + + WriteResult softDelete(int listId, int expectedVersion); + + PagedResult findByUser(int userId, int page, int size); + + PagedResult findPublic(int page, int size); + + WriteResult addItem(int listId, int titleId); + + WriteResult removeItem(int listId, int titleId); +} +``` + +```java +package com.ludovictemgoua.imdb.infrastructure.persistence; + +import com.ludovictemgoua.imdb.domain.model.CustomList; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.ListItemView; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.repository.CustomListRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; +import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; +import org.springframework.jdbc.support.GeneratedKeyHolder; +import org.springframework.jdbc.support.KeyHolder; +import org.springframework.stereotype.Repository; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +@Repository +public class JdbcCustomListRepository implements CustomListRepository { + + private final NamedParameterJdbcTemplate jdbc; + + public JdbcCustomListRepository(NamedParameterJdbcTemplate jdbc) { + this.jdbc = jdbc; + } + + @Override + public CustomList insert(int userId, String name, Visibility visibility) { + String sql = "INSERT INTO lists (user_id, name, visibility) VALUES (:userId, :name, :visibility)"; + var params = new MapSqlParameterSource() + .addValue("userId", userId).addValue("name", name).addValue("visibility", visibility.name()); + KeyHolder keyHolder = new GeneratedKeyHolder(); + jdbc.update(sql, params, keyHolder, new String[]{"id"}); + return new CustomList(keyHolder.getKey().intValue(), userId, name, visibility, 0); + } + + @Override + public Optional findById(int listId) { + String sql = "SELECT * FROM lists WHERE id = :id AND deleted_at IS NULL"; + return jdbc.query(sql, Map.of("id", listId), (rs, rowNum) -> rs.getInt("user_id")) + .stream().findFirst() + .flatMap(ownerId -> hydrate(listId)); + } + + @Override + public WriteResult update(int listId, String name, Visibility visibility, int expectedVersion) { + String sql = """ + UPDATE lists SET name = :name, visibility = :visibility, version = version + 1 + WHERE id = :id AND version = :expectedVersion AND deleted_at IS NULL + """; + var params = new MapSqlParameterSource() + .addValue("name", name).addValue("visibility", visibility.name()) + .addValue("id", listId).addValue("expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public WriteResult softDelete(int listId, int expectedVersion) { + String sql = "UPDATE lists SET deleted_at = now() WHERE id = :id AND version = :expectedVersion AND deleted_at IS NULL"; + var params = Map.of("id", listId, "expectedVersion", expectedVersion); + return jdbc.update(sql, params) == 0 ? WriteResult.VERSION_CONFLICT : WriteResult.SUCCESS; + } + + @Override + public PagedResult findByUser(int userId, int page, int size) { + String dataSql = """ + SELECT * FROM lists WHERE user_id = :userId AND deleted_at IS NULL + ORDER BY id LIMIT :limit OFFSET :offset + """; + String countSql = "SELECT count(*) FROM lists WHERE user_id = :userId AND deleted_at IS NULL"; + var params = new MapSqlParameterSource() + .addValue("userId", userId).addValue("limit", size).addValue("offset", (long) page * size); + List content = jdbc.query(dataSql, params, JdbcCustomListRepository::mapList); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + @Override + public PagedResult findPublic(int page, int size) { + String dataSql = """ + SELECT * FROM lists WHERE visibility = 'PUBLIC' AND deleted_at IS NULL + ORDER BY id LIMIT :limit OFFSET :offset + """; + String countSql = "SELECT count(*) FROM lists WHERE visibility = 'PUBLIC' AND deleted_at IS NULL"; + var params = new MapSqlParameterSource().addValue("limit", size).addValue("offset", (long) page * size); + List content = jdbc.query(dataSql, params, JdbcCustomListRepository::mapList); + Long total = jdbc.queryForObject(countSql, params, Long.class); + return new PagedResult<>(content, total == null ? 0 : total, page, size); + } + + @Override + public WriteResult addItem(int listId, int titleId) { + String sql = "INSERT INTO list_items (list_id, title_id) VALUES (:listId, :titleId) ON CONFLICT DO NOTHING"; + jdbc.update(sql, Map.of("listId", listId, "titleId", titleId)); + return WriteResult.SUCCESS; + } + + @Override + public WriteResult removeItem(int listId, int titleId) { + jdbc.update("DELETE FROM list_items WHERE list_id = :listId AND title_id = :titleId", + Map.of("listId", listId, "titleId", titleId)); + return WriteResult.SUCCESS; + } + + private Optional hydrate(int listId) { + String metaSql = "SELECT * FROM lists WHERE id = :id AND deleted_at IS NULL"; + List meta = jdbc.query(metaSql, Map.of("id", listId), JdbcCustomListRepository::mapList); + if (meta.isEmpty()) { + return Optional.empty(); + } + String itemsSql = """ + SELECT tb.tconst, tb.primary_title, li.added_at + FROM list_items li JOIN title_basics tb ON tb.tconst = li.title_id + WHERE li.list_id = :listId AND tb.deleted_at IS NULL + ORDER BY li.ordering + """; + List items = jdbc.query(itemsSql, Map.of("listId", listId), + (rs, rowNum) -> new ListItemView(ImdbIds.formatTitleId(rs.getInt("tconst")), + rs.getString("primary_title"), rs.getTimestamp("added_at").toInstant())); + CustomList list = meta.get(0); + return Optional.of(new CustomListView(list.id(), list.userId(), list.name(), list.visibility(), + list.version(), items)); + } + + private static CustomList mapList(ResultSet rs, int rowNum) throws SQLException { + return new CustomList(rs.getInt("id"), rs.getInt("user_id"), rs.getString("name"), + Visibility.valueOf(rs.getString("visibility")), rs.getInt("version")); + } +} +``` + +- [ ] **Step 6: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify -Dit.test=JdbcCustomListRepositoryIntegrationTest` +Expected: PASS, 6 tests green. + +- [ ] **Step 7: Commit** + +```bash +git add src/main/resources/db/migration/V10__lists.sql src/main/java/com/ludovictemgoua/imdb/domain/model/CustomList.java src/main/java/com/ludovictemgoua/imdb/domain/model/CustomListView.java src/main/java/com/ludovictemgoua/imdb/domain/model/ListItemView.java src/main/java/com/ludovictemgoua/imdb/domain/repository/CustomListRepository.java src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCustomListRepository.java src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcCustomListRepositoryIntegrationTest.java +git commit -m "Add lists/list_items tables and CustomListRepository" +``` + +### Task 8.2: `ListUseCase` (ownership/visibility rules), `ListController` + +**Files:** +- Create: `src/main/java/com/ludovictemgoua/imdb/application/contracts/ListUseCase.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/ListUseCaseImpl.java` +- Create: `src/main/java/com/ludovictemgoua/imdb/application/CreateListRequest.java`, `UpdateListRequest.java`, `AddListItemRequest.java` (records) +- Create: `src/main/java/com/ludovictemgoua/imdb/presentation/ListController.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/application/ListUseCaseImplTest.java` +- Test: `src/test/java/com/ludovictemgoua/imdb/presentation/ListControllerTest.java` + +**Interfaces:** +- Consumes: `CustomListRepository` (Task 8.1), `CurrentUser` (Task 1.6) +- Produces: the full custom-lists endpoint set (`docs/crud-expansion-design.md` §4.4), with the exact + privacy rule stated there: viewing a `PRIVATE` list you don't own is `404`; *writing* to a list you + don't own is `403` if it's `PUBLIC` (its existence is already visible) and `404` if it's `PRIVATE` + (existence stays hidden either way). + +- [ ] **Step 1: Write the failing unit test** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.repository.CustomListRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.BDDMockito.given; + +@ExtendWith(MockitoExtension.class) +class ListUseCaseImplTest { + + @Mock + CustomListRepository customListRepository; + + @Test + void getByIdReturnsAPublicListToAnyone() { + var view = new CustomListView(1, 7, "Public", Visibility.PUBLIC, 0, List.of()); + given(customListRepository.findById(1)).willReturn(Optional.of(view)); + + assertThat(new ListUseCaseImpl(customListRepository).getById(1, Optional.empty())).isSameAs(view); + } + + @Test + void getByIdThrowsNotFoundForAPrivateListViewedByAStranger() { + var view = new CustomListView(1, 7, "Private", Visibility.PRIVATE, 0, List.of()); + given(customListRepository.findById(1)).willReturn(Optional.of(view)); + var useCase = new ListUseCaseImpl(customListRepository); + + assertThatThrownBy(() -> useCase.getById(1, Optional.of(99))).isInstanceOf(NotFoundException.class); + } + + @Test + void addItemThrowsForbiddenWhenAStrangerWritesToAPublicList() { + var view = new CustomListView(1, 7, "Public", Visibility.PUBLIC, 0, List.of()); + given(customListRepository.findById(1)).willReturn(Optional.of(view)); + var useCase = new ListUseCaseImpl(customListRepository); + + assertThatThrownBy(() -> useCase.addItem(1, 99, "tt0000100")).isInstanceOf(ForbiddenException.class); + } + + @Test + void addItemThrowsNotFoundWhenAStrangerWritesToAPrivateList() { + var view = new CustomListView(1, 7, "Private", Visibility.PRIVATE, 0, List.of()); + given(customListRepository.findById(1)).willReturn(Optional.of(view)); + var useCase = new ListUseCaseImpl(customListRepository); + + assertThatThrownBy(() -> useCase.addItem(1, 99, "tt0000100")).isInstanceOf(NotFoundException.class); + } + + @Test + void addItemSucceedsForTheOwner() { + var view = new CustomListView(1, 7, "Private", Visibility.PRIVATE, 0, List.of()); + given(customListRepository.findById(1)).willReturn(Optional.of(view)); + + new ListUseCaseImpl(customListRepository).addItem(1, 7, "tt0000100"); + } +} +``` + +- [ ] **Step 2: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ListUseCaseImplTest` +Expected: FAIL. + +- [ ] **Step 3: Create the request records and `ListUseCase`/`Impl`** + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.Visibility; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +public record CreateListRequest(@NotBlank String name, @NotNull Visibility visibility) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.domain.model.Visibility; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; + +public record UpdateListRequest(@NotBlank String name, @NotNull Visibility visibility, int version) { +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import jakarta.validation.constraints.NotBlank; + +public record AddListItemRequest(@NotBlank String titleId) { +} +``` + +```java +package com.ludovictemgoua.imdb.application.contracts; + +import com.ludovictemgoua.imdb.application.CreateListRequest; +import com.ludovictemgoua.imdb.application.UpdateListRequest; +import com.ludovictemgoua.imdb.domain.model.CustomList; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.PagedResult; + +import java.util.Optional; + +public interface ListUseCase { + + CustomList create(int userId, CreateListRequest request); + + CustomListView getById(int listId, Optional viewerUserId); + + PagedResult getMine(int userId, int page, int size); + + PagedResult getPublic(int page, int size); + + void update(int listId, int userId, UpdateListRequest request); + + void delete(int listId, int userId, int expectedVersion); + + void addItem(int listId, int userId, String titleId); + + void removeItem(int listId, int userId, String titleId); +} +``` + +```java +package com.ludovictemgoua.imdb.application; + +import com.ludovictemgoua.imdb.application.contracts.ListUseCase; +import com.ludovictemgoua.imdb.domain.exception.ConflictException; +import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; +import com.ludovictemgoua.imdb.domain.exception.NotFoundException; +import com.ludovictemgoua.imdb.domain.model.CustomList; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import com.ludovictemgoua.imdb.domain.repository.CustomListRepository; +import com.ludovictemgoua.imdb.domain.repository.WriteResult; +import com.ludovictemgoua.imdb.utils.ImdbIds; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +@Service +public class ListUseCaseImpl implements ListUseCase { + + private final CustomListRepository customListRepository; + + public ListUseCaseImpl(CustomListRepository customListRepository) { + this.customListRepository = customListRepository; + } + + @Override + public CustomList create(int userId, CreateListRequest request) { + return customListRepository.insert(userId, request.name(), request.visibility()); + } + + @Override + public CustomListView getById(int listId, Optional viewerUserId) { + CustomListView list = findOrThrow(listId); + boolean isOwner = viewerUserId.isPresent() && viewerUserId.get() == list.userId(); + if (list.visibility() == Visibility.PRIVATE && !isOwner) { + throw new NotFoundException("No list with id " + listId); + } + return list; + } + + @Override + public PagedResult getMine(int userId, int page, int size) { + return customListRepository.findByUser(userId, page, size); + } + + @Override + public PagedResult getPublic(int page, int size) { + return customListRepository.findPublic(page, size); + } + + @Override + public void update(int listId, int userId, UpdateListRequest request) { + CustomListView list = requireOwner(listId, userId); + WriteResult result = customListRepository.update(listId, request.name(), request.visibility(), request.version()); + if (result == WriteResult.VERSION_CONFLICT) { + throw new ConflictException("List " + list.id() + " was modified concurrently - refresh and retry"); + } + } + + @Override + public void delete(int listId, int userId, int expectedVersion) { + requireOwner(listId, userId); + WriteResult result = customListRepository.softDelete(listId, expectedVersion); + if (result == WriteResult.VERSION_CONFLICT) { + throw new ConflictException("List " + listId + " was modified concurrently - refresh and retry"); + } + } + + @Override + public void addItem(int listId, int userId, String titleId) { + requireOwner(listId, userId); + customListRepository.addItem(listId, ImdbIds.parseTitleId(titleId)); + } + + @Override + public void removeItem(int listId, int userId, String titleId) { + requireOwner(listId, userId); + customListRepository.removeItem(listId, ImdbIds.parseTitleId(titleId)); + } + + private CustomListView findOrThrow(int listId) { + return customListRepository.findById(listId) + .orElseThrow(() -> new NotFoundException("No list with id " + listId)); + } + + // A non-owner writing to a PRIVATE list gets 404 (existence hidden, same as a read); a non-owner + // writing to a PUBLIC list gets 403 (existence is already visible, the action is what's denied). + // docs/crud-expansion-design.md §4.4. + private CustomListView requireOwner(int listId, int userId) { + CustomListView list = findOrThrow(listId); + if (list.userId() == userId) { + return list; + } + if (list.visibility() == Visibility.PRIVATE) { + throw new NotFoundException("No list with id " + listId); + } + throw new ForbiddenException("You do not own list " + listId); + } +} +``` + +- [ ] **Step 4: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ListUseCaseImplTest` +Expected: PASS, 5 tests green. + +- [ ] **Step 5: Write the failing controller test** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.contracts.ListUseCase; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.Visibility; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; +import java.util.Optional; + +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(ListController.class) +class ListControllerTest { + + @Autowired + MockMvc mockMvc; + @MockitoBean + ListUseCase listUseCase; + + @Test + void getPublicListsIsAccessibleAnonymously() throws Exception { + given(listUseCase.getPublic(0, 20)).willReturn(new com.ludovictemgoua.imdb.domain.model.PagedResult<>(List.of(), 0, 0, 20)); + + mockMvc.perform(get("/api/v1/lists/public")) + .andExpect(status().isOk()); + } + + @Test + void getByIdIsAccessibleAnonymouslyForAPublicList() throws Exception { + given(listUseCase.getById(1, Optional.empty())) + .willReturn(new CustomListView(1, 7, "Public", Visibility.PUBLIC, 0, List.of())); + + mockMvc.perform(get("/api/v1/lists/1")) + .andExpect(status().isOk()); + } + + @Test + void createRequiresAuthentication() throws Exception { + mockMvc.perform(org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post("/api/v1/lists") + .contentType("application/json") + .content(""" + {"name":"My List","visibility":"PRIVATE"} + """)) + .andExpect(status().isUnauthorized()); + } +} +``` + +- [ ] **Step 6: Run the test to verify it fails** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ListControllerTest` +Expected: FAIL - `ListController` doesn't exist yet. + +- [ ] **Step 7: Create `ListController`** + +```java +package com.ludovictemgoua.imdb.presentation; + +import com.ludovictemgoua.imdb.application.AddListItemRequest; +import com.ludovictemgoua.imdb.application.CreateListRequest; +import com.ludovictemgoua.imdb.application.UpdateListRequest; +import com.ludovictemgoua.imdb.application.contracts.ListUseCase; +import com.ludovictemgoua.imdb.domain.model.CustomList; +import com.ludovictemgoua.imdb.domain.model.CustomListView; +import com.ludovictemgoua.imdb.domain.model.PagedResult; +import com.ludovictemgoua.imdb.infrastructure.security.CurrentUser; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/api/v1/lists") +@Validated +public class ListController { + + private final ListUseCase listUseCase; + + public ListController(ListUseCase listUseCase) { + this.listUseCase = listUseCase; + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + public CustomList create(Authentication authentication, @Valid @RequestBody CreateListRequest request) { + return listUseCase.create(CurrentUser.requireId(authentication), request); + } + + @GetMapping("/me") + public PagedResult getMine( + Authentication authentication, + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return listUseCase.getMine(CurrentUser.requireId(authentication), page, size); + } + + @GetMapping("/public") + public PagedResult getPublic( + @RequestParam(defaultValue = "0") @Min(0) int page, + @RequestParam(defaultValue = "20") @Min(1) @Max(100) int size) { + return listUseCase.getPublic(page, size); + } + + @GetMapping("/{listId}") + public CustomListView getById(Authentication authentication, @PathVariable int listId) { + return listUseCase.getById(listId, CurrentUser.idOf(authentication)); + } + + @PutMapping("/{listId}") + public void update(Authentication authentication, @PathVariable int listId, + @Valid @RequestBody UpdateListRequest request) { + listUseCase.update(listId, CurrentUser.requireId(authentication), request); + } + + @DeleteMapping("/{listId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void delete(Authentication authentication, @PathVariable int listId, @RequestParam int expectedVersion) { + listUseCase.delete(listId, CurrentUser.requireId(authentication), expectedVersion); + } + + @PostMapping("/{listId}/items") + @ResponseStatus(HttpStatus.CREATED) + public void addItem(Authentication authentication, @PathVariable int listId, + @Valid @RequestBody AddListItemRequest request) { + listUseCase.addItem(listId, CurrentUser.requireId(authentication), request.titleId()); + } + + @DeleteMapping("/{listId}/items/{titleId}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void removeItem(Authentication authentication, @PathVariable int listId, @PathVariable String titleId) { + listUseCase.removeItem(listId, CurrentUser.requireId(authentication), titleId); + } +} +``` + +Add `import org.springframework.web.bind.annotation.RequestMapping;` to the imports above (used by the +class-level `@RequestMapping("/api/v1/lists")` annotation). + +`GET /api/v1/lists/public` and `GET /api/v1/lists/{listId}` (i.e. `/api/v1/lists/*`) must be in the +security filter chain's `permitAll()` GET list (Task 1.3) - both already are; `GET /api/v1/lists/me` +must **not** be public (it's already excluded, since `/api/v1/lists/*` with a single path segment does not +match the two-segment... actually `/api/v1/lists/*` DOES match `/api/v1/lists/me` as a single-segment +wildcard. Fix this now: change `SecurityConfig`'s pattern from `"/api/v1/lists/*"` to a request-matcher +that excludes `me` - simplest fix is to list `/api/v1/lists/me` explicitly under `.authenticated()` by +declaring it **before** the broader permit rule (Spring evaluates matchers in order, first match wins): + +```java + .requestMatchers(HttpMethod.GET, "/api/v1/lists/me").authenticated() + .requestMatchers(HttpMethod.GET, + "/api/v1/titles/**", "/api/v1/genres/**", "/api/v1/people/six-degrees", + "/api/v1/lists/public", "/api/v1/lists/*", "/api/v1/users/*", + "/api/v1/users/*/watchlist", "/api/v1/users/*/reviews").permitAll() +``` + +(Move the new `/api/v1/lists/me` line to sit above the existing broad-permit block in `SecurityConfig`.) + +- [ ] **Step 8: Run the test to verify it passes** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ListControllerTest` +Expected: PASS, 3 tests green. + +- [ ] **Step 9: Add a `getMineRequiresAuthentication` regression test** + +Add to `ListControllerTest`: + +```java + @Test + void getMineRequiresAuthentication() throws Exception { + mockMvc.perform(get("/api/v1/lists/me")) + .andExpect(status().isUnauthorized()); + } +``` + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test -Dtest=ListControllerTest` +Expected: PASS - this is exactly the matcher-ordering fix from Step 7 being verified. + +- [ ] **Step 10: Run the full unit and integration suites** + +Run: `JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test && JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify` +Expected: PASS. + +- [ ] **Step 11: Commit** + +```bash +git add src/main/java/com/ludovictemgoua/imdb/application/contracts/ListUseCase.java src/main/java/com/ludovictemgoua/imdb/application/ListUseCaseImpl.java src/main/java/com/ludovictemgoua/imdb/application/CreateListRequest.java src/main/java/com/ludovictemgoua/imdb/application/UpdateListRequest.java src/main/java/com/ludovictemgoua/imdb/application/AddListItemRequest.java src/main/java/com/ludovictemgoua/imdb/presentation/ListController.java src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java src/test/java/com/ludovictemgoua/imdb/application/ListUseCaseImplTest.java src/test/java/com/ludovictemgoua/imdb/presentation/ListControllerTest.java +git commit -m "Add ListUseCase/ListController with ownership and visibility rules" +``` + +**Phase 8 checkpoint**: all four new user-generated resources (users/watchlist/reviews/lists) and all +admin CRUD are complete. Only E2E contract tests and a final full-suite pass remain. + +--- + +## Phase 9: E2E/Postman Additions and Final Verification + +### Task 9.1: `docker-compose.e2e.yaml` env vars for auth + +**Files:** +- Modify: `docker-compose.e2e.yaml` + +**Interfaces:** +- Produces: the e2e stack's `imdb-service` boots with a valid `JWT_SECRET` and a bootstrap admin, so the + Postman collection's admin-gated requests (Task 9.2) have real ADMIN credentials to authenticate with. + +- [ ] **Step 1: Add the env vars to the `imdb-service` block in `docker-compose.e2e.yaml`** + +```yaml + JWT_SECRET: "e2e-test-only-secret-not-for-real-deployments-32bytes-plus" + IMDB_BOOTSTRAP_ADMIN_EMAIL: "admin@imdb.local" + IMDB_BOOTSTRAP_ADMIN_PASSWORD: "e2e-test-admin-password" +``` + +- [ ] **Step 2: Bring up the e2e stack locally and confirm the bootstrap admin can log in** + +Run: +```bash +docker compose -f docker-compose.e2e.yaml -p imdb-e2e up -d --build +# wait for imdb-service to report healthy (curl -sf http://localhost:8080/actuator/health), then: +curl -s -X POST http://localhost:8080/api/v1/auth/login -H "Content-Type: application/json" \ + -d '{"email":"admin@imdb.local","password":"e2e-test-admin-password"}' +``` +Expected: a JSON body with a real `accessToken`/`refreshToken`, not an error. + +- [ ] **Step 3: Tear down** + +Run: `docker compose -f docker-compose.e2e.yaml -p imdb-e2e down -v` + +- [ ] **Step 4: Commit** + +```bash +git add docker-compose.e2e.yaml +git commit -m "Add JWT/bootstrap-admin env vars to the e2e stack" +``` + +### Task 9.2: Postman/Newman collection additions + +**Files:** +- Modify: `postman/imdb-e2e.postman_collection.json` + +**Interfaces:** +- Produces: new collection items covering the full auth flow, one full CRUD lifecycle for each new + resource, and the three negative cases called out in `docs/crud-expansion-design.md` §9 (403 for a + non-admin admin-write attempt, 409 for a stale-version update, 404 for a private list a stranger + requests). Chained via Postman's collection-level variables (`{{accessToken}}` etc., set in each + request's Tests script from the previous response) - the existing collection's `variable` array already + has `baseUrl`; add `accessToken`, `adminAccessToken`, `createdTitleId` alongside it, all with an empty + starting `value`. + +- [ ] **Step 1: Add auth-flow items** (append to the collection's top-level `item` array, after the + existing nine items) + +```json +{ + "name": "Register a new user", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/auth/register", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"email\":\"e2e-user@example.com\",\"password\":\"password123\",\"displayName\":\"E2E User\"}" + } + }, + "event": [{ + "listen": "test", + "script": {"exec": [ + "pm.test('status is 201', () => pm.response.to.have.status(201));", + "const body = pm.response.json();", + "pm.collectionVariables.set('accessToken', body.accessToken);", + "pm.collectionVariables.set('refreshToken', body.refreshToken);" + ]} + }] +}, +{ + "name": "Admin logs in", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/auth/login", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": { + "mode": "raw", + "raw": "{\"email\":\"admin@imdb.local\",\"password\":\"e2e-test-admin-password\"}" + } + }, + "event": [{ + "listen": "test", + "script": {"exec": [ + "pm.test('status is 200', () => pm.response.to.have.status(200));", + "pm.collectionVariables.set('adminAccessToken', pm.response.json().accessToken);" + ]} + }] +}, +{ + "name": "Refresh the access token", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/auth/refresh", + "header": [{"key": "Content-Type", "value": "application/json"}], + "body": {"mode": "raw", "raw": "{\"refreshToken\":\"{{refreshToken}}\"}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": ["pm.test('status is 200', () => pm.response.to.have.status(200));"]} + }] +} +``` + +- [ ] **Step 2: Add admin CRUD + negative-case items** + +```json +{ + "name": "Non-admin cannot create a title", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/titles", + "header": [ + {"key": "Content-Type", "value": "application/json"}, + {"key": "Authorization", "value": "Bearer {{accessToken}}"} + ], + "body": {"mode": "raw", "raw": "{\"primaryTitle\":\"Nope\",\"originalTitle\":\"Nope\",\"titleType\":\"movie\",\"genres\":[]}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": ["pm.test('status is 403', () => pm.response.to.have.status(403));"]} + }] +}, +{ + "name": "Admin creates a title", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/titles", + "header": [ + {"key": "Content-Type", "value": "application/json"}, + {"key": "Authorization", "value": "Bearer {{adminAccessToken}}"} + ], + "body": {"mode": "raw", "raw": "{\"primaryTitle\":\"E2E Test Movie\",\"originalTitle\":\"E2E Test Movie\",\"titleType\":\"movie\",\"startYear\":2024,\"genres\":[\"Drama\"]}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": [ + "pm.test('status is 201', () => pm.response.to.have.status(201));", + "pm.collectionVariables.set('createdTitleId', pm.response.json().id);" + ]} + }] +}, +{ + "name": "Stale-version update returns 409", + "request": { + "method": "PUT", + "url": "{{baseUrl}}/api/v1/titles/{{createdTitleId}}", + "header": [ + {"key": "Content-Type", "value": "application/json"}, + {"key": "Authorization", "value": "Bearer {{adminAccessToken}}"} + ], + "body": {"mode": "raw", "raw": "{\"primaryTitle\":\"Renamed\",\"originalTitle\":\"Renamed\",\"titleType\":\"movie\",\"startYear\":2024,\"genres\":[],\"version\":99}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": ["pm.test('status is 409', () => pm.response.to.have.status(409));"]} + }] +} +``` + +- [ ] **Step 3: Add watchlist/review/list lifecycle items** + +```json +{ + "name": "Add the new title to the watchlist", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/watchlist/items", + "header": [ + {"key": "Content-Type", "value": "application/json"}, + {"key": "Authorization", "value": "Bearer {{accessToken}}"} + ], + "body": {"mode": "raw", "raw": "{\"titleId\":\"{{createdTitleId}}\"}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": ["pm.test('status is 201', () => pm.response.to.have.status(201));"]} + }] +}, +{ + "name": "Review the new title", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/titles/{{createdTitleId}}/reviews", + "header": [ + {"key": "Content-Type", "value": "application/json"}, + {"key": "Authorization", "value": "Bearer {{accessToken}}"} + ], + "body": {"mode": "raw", "raw": "{\"rating\":9,\"body\":\"E2E-tested and great\",\"version\":0}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": ["pm.test('status is 201', () => pm.response.to.have.status(201));"]} + }] +}, +{ + "name": "Create a private list", + "request": { + "method": "POST", + "url": "{{baseUrl}}/api/v1/lists", + "header": [ + {"key": "Content-Type", "value": "application/json"}, + {"key": "Authorization", "value": "Bearer {{accessToken}}"} + ], + "body": {"mode": "raw", "raw": "{\"name\":\"E2E Private List\",\"visibility\":\"PRIVATE\"}"} + }, + "event": [{ + "listen": "test", + "script": {"exec": [ + "pm.test('status is 201', () => pm.response.to.have.status(201));", + "pm.collectionVariables.set('createdListId', pm.response.json().id);" + ]} + }] +}, +{ + "name": "A stranger cannot view the private list", + "request": { + "method": "GET", + "url": "{{baseUrl}}/api/v1/lists/{{createdListId}}", + "header": [{"key": "Authorization", "value": "Bearer {{adminAccessToken}}"}] + }, + "event": [{ + "listen": "test", + "script": {"exec": ["pm.test('status is 404', () => pm.response.to.have.status(404));"]} + }] +} +``` + +- [ ] **Step 4: Add the three new empty-string collection variables** + +Add to the collection's top-level `variable` array (alongside the existing `baseUrl` entry): + +```json +{"key": "accessToken", "value": ""}, +{"key": "refreshToken", "value": ""}, +{"key": "adminAccessToken", "value": ""}, +{"key": "createdTitleId", "value": ""}, +{"key": "createdListId", "value": ""} +``` + +- [ ] **Step 5: Validate the JSON and run it against a live e2e stack** + +Run (PowerShell, avoiding the pyenv `python3` shim issue noted earlier this project): +```powershell +Get-Content postman/imdb-e2e.postman_collection.json -Raw | ConvertFrom-Json | Out-Null +``` +Expected: no error (valid JSON). Then, with the e2e stack from Task 9.1 still up: +```bash +npx --yes newman run postman/imdb-e2e.postman_collection.json --env-var baseUrl=http://localhost:8080 +``` +Expected: all assertions pass, including the new ones (403/409/404 cases and the full auth/watchlist/ +review/list lifecycle). + +- [ ] **Step 6: Tear down and commit** + +```bash +docker compose -f docker-compose.e2e.yaml -p imdb-e2e down -v +git add postman/imdb-e2e.postman_collection.json +git commit -m "Add auth, admin-CRUD, and user-content e2e contract tests to the Postman collection" +``` + +### Task 9.3: Final full-suite verification and documentation updates + +**Files:** +- Modify: `imdb/docs/low-level-design.md` +- Modify: `imdb/README.md` + +**Interfaces:** none - this task only verifies and documents; no new production code. + +- [ ] **Step 1: Run the complete local verification sequence** + +```bash +JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q test +JAVA_HOME="/c/Program Files/Java/jdk-21" ./mvnw -q failsafe:integration-test failsafe:verify +``` +Expected: PASS for every unit and integration test across all nine phases (including every existing test +from before this plan - none should have been weakened or deleted to make this pass). + +- [ ] **Step 2: Run the full `imdb-ci.yml` sequence locally** (mirrors the `e2e` CI job exactly) + +```bash +docker compose -f docker-compose.e2e.yaml -p imdb-e2e up -d --build +# poll /actuator/health, then poll the seed container's exit code (see imdb-ci.yml's own steps) +npx --yes newman run postman/imdb-e2e.postman_collection.json --env-var baseUrl=http://localhost:8080 +docker compose -f docker-compose.e2e.yaml -p imdb-e2e down -v +``` +Expected: PASS, matching what CI will do on push. + +- [ ] **Step 3: Update `docs/low-level-design.md`** + +Add a new `§12. CRUD Expansion` section (or renumber to insert it before the existing `§11. Open Items`, +whichever reads better once you're looking at the live document) summarizing: the two new layers, the +auth mechanism, the `version`/`deleted_at` convention now present on every writable table, the cache +eviction rules per region, and a pointer to `docs/crud-expansion-design.md` for full rationale - mirroring +how §7.1 was written for the earlier dashboard-fix work (a real, verified summary, not a restatement of +the design doc). + +- [ ] **Step 4: Update `README.md`** + +Extend the **API** section with the new endpoints (or a pointer to the design doc's §4/§5 tables rather +than duplicating them in full), add **Authentication** as a new top-level section describing the JWT +register/login/refresh flow and the bootstrap-admin mechanism, and add a note under **Known limitations** +if Step 1/2 surfaced anything not already called out in `docs/crud-expansion-design.md` §11. + +- [ ] **Step 5: Commit** + +```bash +git add docs/low-level-design.md README.md +git commit -m "Document the CRUD expansion in the LLD and README" +``` + +**Phase 9 checkpoint - and plan complete**: every endpoint in `docs/crud-expansion-design.md` is +implemented, tested at all three tiers (unit/integration/e2e), and documented. + From bc8ad20da7319051aa7dfa8acc420246ecb5faa1 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Mon, 13 Jul 2026 18:46:19 +0200 Subject: [PATCH 21/42] Add JWT auth, user accounts, and profile/admin user management to imdb. Registration, login, refresh, bootstrap admin, and full profile endpoints are live and tested. --- imdb/docker-compose.yaml | 3 + imdb/pom.xml | 38 +++++++ .../imdb/application/AuthUseCaseImpl.java | 62 ++++++++++ .../imdb/application/LoginRequest.java | 7 ++ .../imdb/application/RegisterRequest.java | 11 ++ .../imdb/application/RoleRequest.java | 7 ++ .../imdb/application/TokenPair.java | 4 + .../application/UpdateProfileRequest.java | 6 + .../imdb/application/UserUseCaseImpl.java | 77 +++++++++++++ .../application/contracts/AuthUseCase.java | 14 +++ .../application/contracts/UserUseCase.java | 24 ++++ .../domain/exception/ConflictException.java | 7 ++ .../domain/exception/ForbiddenException.java | 7 ++ .../imdb/domain/model/PublicUserProfile.java | 4 + .../imdb/domain/model/Role.java | 3 + .../imdb/domain/model/User.java | 5 + .../imdb/domain/model/UserProfile.java | 4 + .../domain/repository/UserRepository.java | 26 +++++ .../imdb/domain/repository/WriteResult.java | 8 ++ .../persistence/JdbcUserRepository.java | 106 ++++++++++++++++++ .../security/BootstrapAdminRunner.java | 47 ++++++++ .../infrastructure/security/CurrentUser.java | 27 +++++ .../security/JwtAuthenticationFilter.java | 51 +++++++++ .../infrastructure/security/JwtService.java | 76 +++++++++++++ .../ProblemDetailAccessDeniedHandler.java | 33 ++++++ ...ProblemDetailAuthenticationEntryPoint.java | 36 ++++++ .../security/SecurityConfig.java | 59 ++++++++++ .../presentation/ApiExceptionHandler.java | 30 +++++ .../imdb/presentation/AuthController.java | 44 ++++++++ .../imdb/presentation/UserController.java | 77 +++++++++++++ imdb/src/main/resources/application.yaml | 13 +++ .../db/migration/V5__users_table.sql | 13 +++ .../imdb/application/AuthUseCaseImplTest.java | 85 ++++++++++++++ .../imdb/application/UserUseCaseImplTest.java | 61 ++++++++++ .../JdbcUserRepositoryIntegrationTest.java | 69 ++++++++++++ .../BootstrapAdminRunnerIntegrationTest.java | 31 +++++ .../security/CurrentUserTest.java | 34 ++++++ .../security/JwtAuthenticationFilterTest.java | 72 ++++++++++++ .../security/JwtServiceTest.java | 57 ++++++++++ .../imdb/presentation/AuthControllerTest.java | 72 ++++++++++++ .../presentation/GenreControllerTest.java | 5 + .../presentation/PersonControllerTest.java | 1 + .../presentation/TitleControllerTest.java | 1 + .../imdb/presentation/UserControllerTest.java | 57 ++++++++++ .../imdb/presentation/WithSecurityConfig.java | 25 +++++ 45 files changed, 1499 insertions(+) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/LoginRequest.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/RegisterRequest.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/RoleRequest.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/TokenPair.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateProfileRequest.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/AuthUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/exception/ConflictException.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/exception/ForbiddenException.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/PublicUserProfile.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/Role.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/User.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/model/UserProfile.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/UserRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/domain/repository/WriteResult.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcUserRepository.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/BootstrapAdminRunner.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/CurrentUser.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilter.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/ProblemDetailAccessDeniedHandler.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/ProblemDetailAuthenticationEntryPoint.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java create mode 100644 imdb/src/main/resources/db/migration/V5__users_table.sql create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/persistence/JdbcUserRepositoryIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/BootstrapAdminRunnerIntegrationTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/CurrentUserTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/presentation/UserControllerTest.java create mode 100644 imdb/src/test/java/com/ludovictemgoua/imdb/presentation/WithSecurityConfig.java diff --git a/imdb/docker-compose.yaml b/imdb/docker-compose.yaml index bd38af6..ea99d4c 100644 --- a/imdb/docker-compose.yaml +++ b/imdb/docker-compose.yaml @@ -76,6 +76,9 @@ services: MANAGEMENT_TRACING_SAMPLING_PROBABILITY: "1.0" BACON_PERSON_NAME: "Kevin Bacon" SIX_DEGREES_MAX_DEPTH: "7" + JWT_SECRET: "local-dev-only-secret-change-in-real-deployments-32bytes+" + IMDB_BOOTSTRAP_ADMIN_EMAIL: "admin@imdb.local" + IMDB_BOOTSTRAP_ADMIN_PASSWORD: "change-me-please" depends_on: postgres: condition: service_healthy diff --git a/imdb/pom.xml b/imdb/pom.xml index c42292a..9138adf 100644 --- a/imdb/pom.xml +++ b/imdb/pom.xml @@ -54,6 +54,10 @@ org.springframework.boot spring-boot-starter-opentelemetry + + org.springframework.boot + spring-boot-starter-security + org.springframework.boot spring-boot-starter-validation @@ -77,6 +81,23 @@ postgresql runtime + + io.jsonwebtoken + jjwt-api + 0.12.6 + + + io.jsonwebtoken + jjwt-impl + 0.12.6 + runtime + + + io.jsonwebtoken + jjwt-jackson + 0.12.6 + runtime + org.springframework.boot spring-boot-starter-actuator-test @@ -102,6 +123,11 @@ spring-boot-starter-opentelemetry-test test + + org.springframework.boot + spring-boot-starter-security-test + test + org.springframework.boot spring-boot-starter-validation-test @@ -153,6 +179,15 @@ **/*IntegrationTest.java **/ImdbApplicationTests.java + + + test-only-secret-not-for-real-deployments-32bytes-plus + +Grafana dashboard list: HTTP Overview, Six Degrees Latency Breakdown, k6 Load Test Results, Cache Hit Ratio + +HTTP Overview dashboard mid-load-test: request rate, p95 latency, 5xx rate, and JVM heap all climbing together + +*Mid-load-test, not a static demo: request rate and p95 latency climbing together across every endpoint, JVM heap tracking along with it.* + +Six Degrees Latency Breakdown dashboard: p50/p95/p99 for six-degrees versus the other three endpoints + +*The one endpoint that isn't a bounded index lookup gets its own dedicated latency breakdown - p99 pinned at the graph query's timeout ceiling, visibly separated from the other three endpoints on the same axes. This is what makes the accepted ~25-30% hard-pair failure rate ([Known limitations](#known-limitations)) a measured, monitored trade-off instead of an invisible one.* + +Cache Hit Ratio dashboard: hit ratio by region climbing from a cold cache to 80-100% + +*Cache warming visible in real time - hit ratio climbing from 0% (cold) to 80-100% per region as repeat traffic lands, backed by the manually-rebuilt `cache.gets`/`cache.puts` counters (Boot 4.1 dropped the auto-binding this depended on - §7.1).* + +k6 Load Test Results dashboard showing a real failure-rate spike during a load test run + +*Left as originally captured, failure spike included on purpose: this dashboard's job is to catch regressions, and it did - this exact run is what first surfaced the connection-pool exhaustion and schema-drift bugs fixed and documented in [Load testing](#load-testing). A clean screenshot would prove less than this one does.* + +### Correlation in practice + +The payoff of wiring all three signals together: open a trace in Tempo and see the actual request broken into spans, not just "this endpoint took 220ms." + +A real distributed trace in Tempo: nested spans for the security filter chain and a Redis command, each with real timing + +*One real trace (`GET /api/v1/titles/{titleId}`), opened directly in Grafana's Tempo explorer: Spring Security's filter-chain overhead broken out from the actual data fetch, each span independently timed, all under one trace ID. A different request (a cache miss) additionally shows a `TitleController#get` span tagged `cache.result=miss`, HikariCP connection-acquire, the real SQL text, and row count as separate spans underneath it - full shape documented in [`docs/low-level-design.md`](docs/low-level-design.md) §7.2.* + +Raw PromQL query against cache_gets_total, broken down by region and hit/miss + +*The metric backing the Cache Hit Ratio dashboard above, queried directly - a hand-rolled `FunctionCounter` (`CacheConfig.cacheStatisticsMeterBinder`), not a framework default.* + +Loki log explorer showing structured JSON logs with requestId and other correlation fields + +*Structured JSON logs in Loki, one `RequestLoggingFilter` line per request lifecycle event - `requestId`, `traceId`, and `spanId` all queryable as first-class fields, not buried in an unstructured message string.* Full wiring details, including four real bugs found and fixed while verifying the dashboards against live data (missing percentile-histogram config, Boot 4.1's removed cache-metrics auto-binding, an invalid Prometheus flag, and wrong assumptions about k6's remote-write metric shapes): [`docs/low-level-design.md`](docs/low-level-design.md) §7/§7.1. @@ -296,7 +338,6 @@ imdb/ - Under k6 load, six-degrees requests initially failed 83% of the time against a missing index (`title_principals.nconst` had only a partial, actor-only index: every path-enrichment call fell back to a parallel sequential scan over the 100M-row table). Adding a full index (`V4__title_principals_nconst_index.sql`) brought that down substantially, but a persistent ~25-30% failure rate remains for genuinely hard pairs (large hub actors reached mid-expansion with no intersection yet). Raising the query timeout doesn't help; it just fails slower instead of failing fast, so this is tracked as an open follow-up rather than solved by a timeout knob (`application.yaml`, `six-degrees.query-timeout-seconds`). - `title_akas` (localized alternate titles) and `title_episode` (TV episode hierarchy) are loaded but not surfaced by any endpoint. - No rate limiting on any endpoint (including auth), and no email verification or password reset flow - both are infra/product concerns deliberately scoped out of the CRUD expansion, not oversights; see [`docs/crud-expansion-design.md`](docs/crud-expansion-design.md) §11 for the full deferred list. -- Swagger/OpenAPI UI is deferred: `springdoc-openapi`'s Initializr `versionRange` doesn't yet cover Spring Boot 4.1. Full list, including deferred design alternatives (Pruned Landmark Labeling, a dedicated graph database): [`docs/product-design.md`](docs/product-design.md) §11/§12. diff --git a/imdb/assets/6-degree-dashboard.png b/imdb/assets/6-degree-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..8531d76eb1b990f66e0905abeb007ae4fa392555 GIT binary patch literal 168123 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

wT#$Wu!i7CxLlXwNw_Y)w zQ4Hd@(Wynex(EVL5Svo@T*qxEZcN~>x8EJiU!Q+>sM;~4uh1f2w0gfTp)ee#84XC0 z4Rd*VPJ@T84HHdBiz$K-WyKUujIaEINBH!zsR@*n@A|DAdjhACi1lsBKp9&=LNw4s zJC7=T>rc(89jxQS=*dP~;gLYG?#}z+kU7j{jEsx?hskzq(ui64eN1uR`30H$T{N|c zgQ*Z7?`0o3$Agl$hpRte5AsJ{fjY0-=&1%}0C@iQAYV=fVFmQk6y&?N2R;;1JDAJ> z;S8R=`@5Tad$c?vT1NI2I_4N!d7Jf;Y2t?5a`6k7Nq&wTcUk5FTA>3p|Pr3gOebZ4rPYMDMM_P7HuvjBKsan*w zqUa7j9}~Z>-(5eQ)>2V0ec|f6Vm&wU6?iY6yD4=hloaXtC32Wx@iYI3%S{KjFBs%7 zCWuEn(3s;EAw>~x8G^RY5!mXw=22-f7Kg18^qtz2{0%JV-g@2cqNT3&)0)R!M_#VV zJP{pFPWw`k&cnmoSRuLrAYj+=^W^RIDe3IE^KqhVW47635#Fp@@1yjQmYMXepNYO8 zqP^5gGlrn|-@UAXowhVL9s;-+)348zC4=|#o(O=;PWFzCC@W zphgY{6JS2FTt|==gvQ@=tE426l92t4GKwF^$aK%t*SSi0*H%{-Y7{AE2s=d9X?A+> zhhLi|fo2yf|t>+KrOUchhg&6Bh#LMMRT*Jj) z9bFM2Z&{yN!S2_^*8NPWb4LtS|2(gh+W@(g7?NKO@%Lo0Ps-v6tNsVH8Ad?MhaMOj zwM7ZGZ-V|X6?Pq&($b2i;idBN!PfGHM5oOFp$upf1izGXm+qUAoFlLCB$?n?!Md9O z5R5rLO$@aJx7w<>WWjgch@mB`uL@~qnAf9cyuFx(5`t+dg4r+FW3!bZ;g5j0xyuR? zkZ7Ek3qD{E>G&z@$@u3AjyZYW>(NdK=h4ly$6$yq3aDi7xx|tGfwsmAk%P~1QgkSq z`?+&(dA{aM-KK`Xjw9o5{VgI2_?L+mmVY)q(!KyV9fq%^q?^!)<_H4v-L z&WC=$I&H!VUDrOK8EXM5({A%R6X3$Q?|H=4QzRn5`RXFl723-R*Rh>A%gpE1qJHNt zE`L#>>%`UKd8`yXdn23jCj0?4gbr}o9d^Wp#a~qBb9jZA?FvEFX~*aw&dJA!IMr79 zr}-zdO_(dXfbuV=wXkZj0wcDY_1^MZl4$#HpEx31G_T=l@vf~sqG=t^)R7r8hF=-$ zdz5A>QjN(r7pB}sS8w(g(2rf42iz{UJGZf^6KmX=queR@+2`u^I>z|XJX%U=EUlB) z{F^|A|Dci=Km)`>Y^YPQsMJ()GP0C{qN3*`*66=WG^v~AF8;#)X4=l%tZ9NJg5}Z0~TyGM1AsX1M>gY8?4?(VV;w;|Ai2}KDE{q z+$6wHcX4=Uy-|gf z2ZMX^akFP-w2H0XG~d6qP*=bchI0Ce*6KomzaD`8mPu^C3_8o^J6mDgFYE%pGMlaYfv)~HZD%%5E^PoNA9vRC}nFcG!uFH`CoVWuM%If8hengNp(PFiSR@Yau_;{PD5rW!T%&# z{|-m|<%@s?{DO01>%oFv86_3cloYZrp$+EC?S{}Y@wtPU!5w#rt<0T&x`7;3oA#8B z;F|v%ioYPcvtunHCPw)WqF+=@EIua(q(atoaQD*(C8+-^eZ%n84|w|2;<2;5&5X0ArPJt(MM2ITiY=;HAW$o~)H zghQ_`rjMT)h2j5i`GiSUVW0Egx&Qr-Vse2g*1t9Q*Ki63{)a^J_eKfFe|aJQU#d{! z=yp2vUkN>FY--WS55seJztGX4aA6<)nM5kFu-MnvCjg54WQ{6~jUvk@^_eLtVH)SV z8|IeOU^YV|I&<>^7sMK7!bmnhD0QIR`{T*H4U3mo_q@^YRLasfrE_ z#Uvvmo0*-9&(1b1^ydG=6Y_5(#6peR*%f?tcBX&vTTRy9SX5LL^^yq*4c)mfNIF|$ zOjbHLfi5WC>+0zyq~yrk+aDS;qr#umR0Vr`F6$j@9X;KY;-%>S@}79tw+?fVd#5M& z&N{LMZ?v?SwWhRC5~T)Le7~e?(w*RPP|@8Ror8u&N8 z>ozufmBeNK%ZwD;zBSwS1yaEKi@A2xrmo;yL$mr zQc_fCkP@9SZ*j-#@0&tBmIF$4no5g5Pj7>!b7NvSN24{sSDjlnBXqgSSrxUqCG%&0s(*Rw^dDS<42kGqrTL5&m1^h$7mB4Ag?nE55sV49bP zDE60+qb+1Y#W)57=#D)tA257vCi6h5;NHcsi5}%oePd#>JfH6z-*P(ur_*s~*Jw*6 z>>Buz;378{J21w4Iu?|y9NO={R<;}UBrxGcN;*@ZVsWwBBiTU|VXAiLk`JQrcjcv} znW%6TavT9T^=mt)r*k7l;svZ}pkY!|;Eg@GA>>`a-NS7qji`4Tig_mHw*OWq(eYxR za}Pj7SSM3_q&q2o)@H$n`I~LHH~ok7+qLIJReA24i4f zCVC#u!K9liK5RCppIbUOj27T%{4$2TREFrPL~WH@(GWumhassib^MY?2Q%t^d6kcP zOryO;-y>Z@64KJGH%Y5DwYp#zRn`pDB^55c%lpr|h)DnHeeB9OaMLmJ=T8F8s9NV_ zZ?f)DTQ5;*s>{t8tFNE0ldGfo=#ruBVtx8HWBB&(cK#S@VT*f*y#XH9dq0WWN`>t; zvca#zEYa!DUu5MFo#m<0;ULlkcuC8VVV;Cm%}}Rj4fM5gZ~j=sPq_ z@1I?S?auCQEO&9J5H411JLg?6@rdzgwGv^F>MgQm$b8?$nqs@4$=XRfj=%yU4)iYm z>Q}`MS_jB4Z0-4#V`#O^^~)-k@LBXVJW7IM^6R$_=$D2g=})(FuaNEOX#*lV)Sv!p zT~EM4NzoDbaDRxOkjVX%#3gG9aJ1z)#2ZT|ZpPss%4e9LxdNKZZEFLNOrYLF*DP~p!~7+b*t@kdXA zWT)h+{zC+!aJ=Jon_~a%+QWKMA(5Un%5P@y|C^0kfG%MBbZDMm3gtSaL#OZ25K#nu^Y!9Hu=18!$7}2&i9yY2=Fky>3AeVA!4Gqx(D#_;J;n>D5icNC)swy zsscHGYfVil*C6x*8twZd+8cp+X!rP*keWVlvZs@fi(aQEli!$APcmziOQzphAA!ZK znme@NF-7SzQ27D7Sx$beKAv~IvbVd9`Ka~$QJmz-tCSSEI5uoTioX;5ZrVLi`2v;K zJEZ3eMu9Z1mlu!;>AKEoTfbK^e5)O~+%R^>YUHSa7plprmfntbHa4*JxR~|sOR3J@ z*-4#f!xj&|^>XX0o2#)RZLh=Y@jE?FW51q^^>oi#ijkRzSZJ{JCVUs4#`53`LdDBc z(qfNZ>-o9mpHlU)en5~POe1QumJ*O9RQCdOP%6QD^K9wvhDVp~fbzzi{(+4@ZFXkn z>C^Y*)YO?>0{=n}p@MfbD}QbF{euJR**rls%h4Q84))&J`FZ};+5U-A@}Bm4pJHw9 z2;R6@i=%eHT_fl@0rlhYCLsCx=V^D4A!2kez4By9TRi$_#cqo(5|&x1vQlpRX!lQ^ z3+bX*L)WNIRdBK8fA%ivCwE_)rSIicJTH)r&aP{o`@9$Xv!S7(OmR{|DeiXSCKeXM zb9JT4fFW&Ne?NO`>;7>d%kg}evCipuiJ4cnn7oO#b*BThKdXweqDsf&Vn{44!KMWMmpbMQN5bafs7sM4iGt)@Cl!s#!Nj;;%0h$b);1dA|M4(&Sug2M4%3RI+wON^iQ_5lA=NT(cO^W6UHUurN*5eTGmn$AmbBNHN z`t=}S?RO+Nlp|o^VNtmyO~3?Q*C6fg>Y7PZxeK12V8!rkOp78K4b?fkTHyg&b&LJG z*!neBsz=qbt(6QAfUPM$nA44;Ejpc9$zey{QS9yJEq~6`0pVI&l0-RA%D#MEaEleq zT+$Thyz}wzM7iP*=8DO}A> zJUk{^oR89SI}m9(Lc{slDE)33r1!h|+KCKuhsE+%}kozrJ~R3^X6N&Fr|W65yP zqDE1qmGTzaW@RuPdA2F#@)W zG1TEmxqh9+b>ARrKGG+EtH5$55Ey$cUeGgAKRXLtWY#&^aD-W4=iyXv2r zo2xz;<>a_=euQ$i66Zb3){`{^y1MBq0XBNYTNtcF4i5AvcQJbb2LY!v?QUK0Vq?`j zr!Ry+$?9#Z5|@|ZJEYrhKA*XpIk#EQow6GF3P?cS_~dvaSiQrhHcnP^XFZmJZVZP` zD=jg=$a7|?BmrDa9aV!smGBCQ+knc`lc-95Yfqo7m`&WtJoh(fo!MdIrE1LNBNnSP ze{x}kcZrtXQ%rll=&1*-*1T36z>LkxwSCq1Z_w&a#izZl9MNvGPvo`Z+hL($!zpffqv@LwTRM+MeFcq-#Y_dgXcEIt%R$_cPLmm~o zpmu9pk-Y0wRaNF=sdzINa57YWAWg)dPx_pSLc5%2sm>2g#C!iqMTPx>%jKJ!WtXGp z%9$ugu!#HJlLvn{0{x~YwHy?!*ddjatJMGQA)`CG+!)Cp8yoBCr8xv}0B%11X${t1 zT_p(&$bT)rK>gKjfOVuWZArn%|DLrOQ|w!M+M5zpwCpfQ-=NGMyizmcGCrf$r$LOHu})XxaOncF)^ zfH_=R^=wsjb-*rgB2I~RE;rdQa58Qg<9N71d8Qpmje7Bby$0o%as;!>%1$r`-%aeZ zK8XH5?7d}JRBit@N~kCZh;$1GNHcV!B3%m7U4ux2bc}*X4k$Uak|N#R4FgDbcXtl) zF7#IJ=lQ?K`+nJbf7Dv8T(Vm zgV#L=Uyn!flYPu+d_xTP?62y2hNrWPzrcw4d(zfbUcY~2#s)briSe-(?v~xI>C(D# zj)nTqyvh}(Lh90dHBB7qGs|#(^;2SQP4RLDO?PHpE zISbs>PNREfFzmcz4T;X~r!?(g3XA4&5$Ro>As-l2|6y!CJ)gRnHUn-rYOgxzc0Zc! zs!N#VOSf1KYoB*njcAuUZKXcaar|c1Q}2vggw;HKCuul%Ia^V5E*nx+e@ZD0(z?orm`3%Kh0wVa}0ykc(0EDkU<3ckfp@_2@Y{y(3vPIloR< zFDxzXO`&b)ne9`KjEr!YHQ-H5GA{RKL=(QM&!5<=E9BQ51+m;Sx)~$6?>#q-Z%S*M0rZqv>odHChYr1_ov+#d>fS1yp8QI0?m zi=2kjv6TZq(>cD2;j?V_)(Z2q`CYLw1fP`rQiz z@kyue-qAH8`I03|zwf4)Vn@Y|E466%tS9%}G!u(Erx!uD_!xoSp;uG4I7g!vA*QxA z{3&aJ`TR^2zJo>qcD~XyPDdIvk3q4IJ$e{+`Fe!)Z3RpOTWcvjjIwNlhmXREq(2xt;y~cEq_``$i-h4;rw$ALcArk9&5Ug`RMX>_ z!;d2HhRJ5sqSB5C$l{*>qf~~rlt@o3C$LA0tpfON?ia^%REr*14kd1r)M(MtWsD$)wY@F4quKMW381ylL?va z0kiH#$;^V-g)1gH;c{oIzjRd)OI^lk)oyqCx$6u^@Q2w0vNJrk+EXe;9aE{&^>TOq z2wrfNjFkebOS#MWdY77%e6>q`%pFXU-HE2L`&1FF;lk|c#WGmDGz-e;KnHakPY=L%9>liCTz9Yb}?EGLw`l31i+x$|7L z-R=>*rZpYdk_GQEUR>o@IL|C>wt_nJ^BQ&6VTPx-Xo>sRY8-i*_ZPa=nR+ zPP_*qE3n<8bzpRQ&vPPyI*6buq5cPEv85JGEiIA$KwPFV`6Lb(pO)^32mte>x<1hR zs%5MQ#7g~zU&VaL&S5K1=IiG7J>6RUB6QJUtn1-~-y))hb(DVM&}~d7BpmA7Qq$2= z$a7LkZqwKZxs4gu)X65&IO!13M)}SMz3-!O`d4 z?Bl7KRJAE1c~6Ge12N`k{)F^IvUV{bK_9>RJkSdD{y1Z0AR*gcM-gPFXIOWpFEy}b zL*^P;Bt4(l3bbB67P4H8Jw*k8`M!Dk;sWu$tSn}5)r9~stHgkj7R9P#41|;3Oy?NQ z=EbY+&-nEM%vXE+Y@$FmJjUDiC@el+9td*l&-W4yt^52)giZMPE(9@7Q*|nd!h?)65hj|hYBuo$Fui~XDCjV; z2WW_R$oHv%ERC?MuJ}eE=+e(u1j21qTuM~FYHr%?*@yRs5dpQviXriBqUo2Jd1}L5 zHfskAm#1SGz~Uh6=vB_&BSO_+s?k%04d;syN?=hoACZq+34L~u7vzh*KXCtRy2e{Y zy+Z5}EvdicWM4?%?aUyj^~6cIy1LH3eBd;p`(zYYN7<0PKRwCa=9%ST`Qi=v; zHqSOR&V+9asV6~YE!bzcR)zR7Ogsaxamm-(hu54D52mupZIvS!L7)#!FZ!!|RK!bjUU7Y&_5+N6d<%FTcJbla>%iZb+ZAhTZ!RHGGH9k->qV!H0^4&-qD%;>CHQ?yX0B=q3Ipr^DWN+ zX&UO85X|OJmUAJg=dMB+Aw!BFvyCSL$dw|VQ9cNz-K`y>FkOII16$(d{<&kMdyU_V znS=9DcPBpFE7l(N%}H#R)A}R6#OdzP=4qJqX-Vj3n@CAYh+oL1GF}^s`pKd@1;h@| z7fa3a5ym5yO%Ar&Jrv0h^2O2GE6OlBx!G@DlFO}UUQ$3T$oh5Tp8-Blf%&mx43||$ z9kMqxwk)IOV#_=$JImQ>F0hPG@AQBVnAj-Y1o+ibHx&~T29lebn^8W8%%X44FizN_ zl$2V3p7XGIp^5EjCGW|~@canZN)L=sZ+TG?fotdx$DIg)v&!s?*sVve&7*Wf&p5&7 z$`g}WbWz7$rbn&g`?6U})#9X5MHr?lfs}jonLRd6!hRZpiRCJbj~VMSl&Z*&_E>jQvC>DJCivR)kqOVm z)@Gb9`4HVHB%H{ERpzF)6-`yY?ontNEYT4!cb$(n5LqUinUR-z&y-<$^ia8v>(y{) ztxre4BU2-kOwuO#fo7?dqW2keCudV0$dFbZZ_JEuM?Q3;{)F%i`YQR_Ix<(iMNN;5 zD@QkJO<|Bf50VQihZWQu18tm(t`+qa<3{5-zr+yDMffMTCgtbn*8?0*KtPMbaKszP z5`L_X7j`?^T51dd6Z0yA7>nd}uRP|)P8aQIESJ!+ras;pv3oncJGUPgZ3}cR_`)Ta zlCLW}pi)huvMLhr5BC@5Al4kl&o#@Qa@i4(Ce?zy5) z&G^q;a1nL_qp}O-h=zs+=%fZnWKIDowm?H5lj)MBc_ADa<^F1E_O`f8W))DupmJn; zpO`C1R~WI^3z=FDfz}ci=Dv*aEnRfk&Mz&cFEGchaDX-p4rZ(C0xlhs8jI;FuO8@- zvY*d(j;~PEGgqCML21-7jqyj8qYL-Y&`=e}q254_4i{Q~dsx1l$Kt8dZSx;v+&|jR zDwnrD+}{xWu0EDCIUWrxhtwajlGxEs?8#<1y~-tjIOd*g?SeO*rv_OyWK!s4Rs z+`v7Brk2l<31DVMrEgY6o2uclwq!W*6$OA2QNpCs1e(lyHiZiW_(k;~z;94s$2CQ3Wb6+UZiMSSXh)f?|Okw(OtK{#9pHp!c#9TEL9-4fp7jR?=RO^Zogo> z4B+d`0UQnkE-9&&U4gxnfKxZj;db?LTUU~!i&2LrWK?5xWOS6c@X~H$W23#hgHfeA z;>BO%3CFuXUE!%N#nI6biLUgE4tPfgIv`BjIytKo!$YUsQaCbnreLHQwG(mLWaQ*| z`T3`^n1XK%3_d`in8CqV3rh>(0EB{Bds3*AfAUXer7gazYcigMTRX3?uoa+r)pB7? zO_`b9l8}%{1Ieby0Ewx_=H}DL(#fJCuDBm+^z?$`FqPH4J-Ph_?JDPQ6T%Oy2Hkq} zMgjDSwzjsFbZj~C)<;Jdrrh56mypuu;saX9{|)CkTR$-U59ZSGU@w64_2yDCVfb$Z z)Bk_N_3)@f{$IzzCo|UcUp&6o04hd3fa#V`B{%rmyBiu(2jE7569fSFNn3k29Su!< zxNKCJGiX#jWrC3f=8*on=8r=Ud`{Fba<4WIiAIQgIzZWVR>A%F$8?U!*ilRFw6nUO#&7Yj?9 zFY$$hL5|~N48pUSMBhn4ip~EMEpE3P+BRJZWD2j!u^YV)qC(1tx*3f(g z;6__p-0dCks&5q~Ty)`T&lVG*qRCJHtnBMfyp|>=UX6o_dPB2WfL{lVM*NV#G~FO4 zyL|Y8dC%8b$cYu%4Gj(G9S=B4)8|&<<=Y6hn{`NCnj3FSw}DbE_GcqZGd1Pof4 zjmSNxkeHS%rOeOzLwfmpf8+`<(hEl_IL{&rzQ1aWhG)TR7gijB_Zx#vA_Z-n8|$-b z?G^)X#N9I1Ig|v9MG& z`!_Q9t2z9sbDk(~JH*s#z1xKVcfK!JZ!-R%NGuYA&SFJ%E4;ogIPL_4h#{T{p)^ z4m~+0ZgHT(18r~WRR<@*bLKv&09oou^{?S3=w)|&`tyQW7)-;;hi0$1ec1O-AwSc> z_t%f}jRiXfB+&n+Y1Lk#WgX%KGoQc*f~ z*Cj_IaK z?!y1DXT&6kLNL(T=n|8-G0VhzXF>={m7C2CmTBT55blpTv8EyBZG~y@SD6nR0OSEc zbf2gYeR08fzpJ2`OxSVYUs7JhFHuhii*mwRF6U(gu_6QXo0tSro=vZi(U83Ilxt4k zMf+R+@rLG2xQ7`^4FHPf>P{_@GgLjCIo}M7Byhf+ zjHcKaY5`Hq6R6RI_iUN&SkneQqWAd2J@{n2mub4K9Jvx+RmB#6c$+^#jjoLy8&i-* z>VQ+-j7-LGPGib-Sx+wUbPT_<-W!o$P;kwMd}|1kE9V!X>aXRXWCpO>?&j#A z>FGf>HZzF}uhG1@xuR3W>-uIIsbbs}fcF!p_#G?9@Q$B^!s#vWCU?F-_d)djF> z%e~UKC7(%JDFsUk`z`ptOm8w+yp%+-R2n&3#fwZt?anr7p^xPYAvEx4>?(0c&0D(U zOCtxH`cDSR*t$=O?b3$D%ckX>8>6RKEq4;u7@Nkh)MtNMCak#R56_~6x<9(yIrb5* zg8K;bK{Ytjf0oWZN`q_HCAnb0xXp+Rf^XAOo8he7G9BXZIHK!DU53Qh7bVWuamIZ= zN@cP42$nwsZ7nKBb6V5xPeGzGuqEcupYkQ^ktkHZeOi2WKl&60_Y5yaX959F-3i4c~0Sou{gvaaA<8H0C!G;O* z-pp18!S(v{fn8R0$*@nry3{zF4l00tbNc4?*hu$s;GO$+x4t%;SapRY$JwdV=}uup znh~k;Pu83y8@Dt^uEiP~^jQ0h@fS5?X|A4@@74|5(-2@18tbBa3-)$d-2ltZwV(zg z>l+{gzBbjab`px_U#Vf&KaersI6|LjGJ=W?dbeYfRB^~fK=ngQ5#aIZ&O@Ux+z9JY zN)Hanmx{0p^wKEa#XzUdTECUBwW6SE$jrdquqx<@+>hbLUEI=nyUmVz?bIond!Gi3 zk3sen!{^Nj3{UYKeDCOZ+`eI=q)IpQ zNiCTpvOMOKk@H2W?F;UA049Pic;T$qa0U+?RI57a%YGJrTW$qEKv{xpH_GDP8c(p< zc2GNZ)55Sv$UULSq4=yOJ_~c-ey4M}mXnAoC@x|AT}GiRKCC4^oRKU-4|zi5_XMxL z6y3F>*`GQ5lvq{b*G>sC(C5=7JT7?a^ibj31#HLlS#@l%@JK7>NOvga^3MI$=FgyP zWcoXz+;NVVC1e`a8v??mnw+zn#6cF@zMDRLN|s{8XWA)LNRHL6?+ka=F{$^dzfa9nbQ66X4Y|z*4|Fs)I4K@GPBh|H!tDKo za|Y$g#nOvUMzF(PyfdD6)cY1>89aynB%EOy$rwp5zR0h`fPSU&dxcf6kBwh=5C8oWG)Evd<+L-I4 zOc@+(#snmayT=7k3VwU^;X_;-Cnux+wCVQl?j%48ogfBTYHlorFX#jhCjcZUStP3# zyn$`G(6tM@g*r=j9~GlEuBXo=u)V8`>Ty~AKP!ulhX=$=w$DD_BHA)<1TN$pjGSq+ zg{3{(Z^$Q^8UAwDS}V_?p-@_s&iw!<8N)S0J=zPj9B9eie-PrWb?GQGGZOoC%w}$e z!$<)%EL1aT$`^ub;1TGBW)N~jpY`dKK*kn}*6)oHWo#hGV$uK(T7I!q(jG*FAewK% zGVEC6+u3OQOobH7=SqirF2Irh2nnc4_uuSFJda9)J3O{pUgqwE?e{%uspg5uFiJ0A zr4S;Oc-Z2&R3(&1WA=2+fB*^!B4&E8o9y=kgI+a=mmG0oAg4p_D?h1we_N%!)G)~@We=lyFVq(ouZb*IXWOMi?`Ep~6j#&MX#hiM4ZFQ?8=3J+D zbXf@{{7qq44LJ4*STOK1$cN6S$A=^K?tltdvH6{Q9BAf4ZLG;}Y##Q|PCy*a;2P%}&!&K+XCe}BnRt|4vfQ5vK=G!-Li zR}(Le{FHVe)dc5erCi#qh)k`NMz9IZtG zX7G@RZ)h7vsSUc#p>WQh7!Mw2zym?WJBJD;ETXx`)bHx!)>0~<90$vtpU|WQlS?25 z4w=t~xa8&|l+=Zdc(mADakw9owQ@2=?|SxvLOjz?M520PC2l>yS@4Ct4f>;r&V(issxl?hrPg!CY*^Cb**dWuuI0c3js$t1b=6%yTj=^iCZFSyxYoYLIWX3&G9Y>jiGxpROH(g{$r_N5x1-j&}A9CfgFp&0jcR za-Rp5jI-mF4!j9Ykgq4uvS2|*j5Y6F_|3mLATC%#%`zD)>{qW~!Fub1dsuf%*A0?C z%KmX_uQVz_2{`nmT-MkyFy7!tj*@JA&yaWYDRP(88ILW^`iyJN(5;R}cUV2eD-R+8 z;}`z2AzRhCPj0+yyF%tGPvV-IOCb2^3sk7i0A#fhnW{vADrTizu*DVf0PESz2PA_$ zhbMd}4>$rcI7JOR9uyjElU>L+9xcLjFKxN7EWF?jq$PX@SCw=wB$xN_9YZs}_P1`Y_TwF_1)+!_Rqcp z0!y)>>@U;EUYx5PrSjwS0X(wMxHf@`cv`h}JA%s4a?04XulgFU#j|(GP~ z*3An(X2`I%+s3bCn>3{Z-ha(~zqNFP9Y)J9*C(FGU+dp~dz}1=h)q5gUbfq>-c6?v zhiYedGR6$qD{7ac5cT0d6*Cf04Kz3u3<0^mU^^3G|KMP1aW9C-ipN(4*zPX3L3PZ< z%{qs+kNwL~!Tu(p4HMHxp^HQ^#@=iW;-=oYqwSY^HaA06l5)YgDwI;$wp@ zSI}11vs>fF1(1DrBn7xu<0Z3}7o~HQ?W@_3;?ViSZ?k;hO{2l9oW9$QY@zx+a!F2X zJWJZEnysaqWG84iyLFXm^MNFd2MpCa@Uhk(qo>cJmEyd6-_t!CY1&?l$|Uo|p>Md; zrEi>W(;xsfl&O7SQIIrxYJ~ovwU>+@B^GmTb-4AxAaf{k*p!JeF8$mUtS9Pa2gk4@ z4?nI&)!m?-#@^nL@A+)~sp`Ik#c5A{id?wS>>3=D_~Bodc}BB8!b;n}S_;v9B+ zl5m7ONLe#F*Ucf#a^#_-_2nrqX;ZkQ1mLaKzrgR#FM^3;rRn32e3>C(*g%|yq2Dz= zm@mF^@5mZXV}I0!DVb=~@RlE$Aw`=#^0ub@?5=`t$|Zl|s`X`TVhL;xt1#gSM2bsx!chRZy`k$m#6~n|6<+w5HN6qgf zR$bxr)7_{3ISEw5&pHdBm@&}aZ-v!Xzn#7B?tq8W)o_oLFQQeeygpi@6DH}J%O%(w3>7ccd4y5-A7LarX~n(V)Z5it*v&^hi)3%P0(@O1dj)<*AFP;E z?dJM4nIe-J$rf=#wHz069LfDR`hs19+sSnJy$P2kVn1njj&*J47r&WGy3H~si8J~G zCr6_<%hT;)A{mp56n86vV&U7T_Vc4NyAr*_dQXO6Hgn$E){381F6J>Mn^MM^FW)W^ z9qR%8Vw%o3!_$I#b%ZG&kIdrLvgveI6k>fWwUSq_ zyu4pgDw-YdlrP*%Y3-(bX*=`M@zLa1(O2=|CtE*Cf~|Sa!4=?5fxd71lLu?PUtWfg z1?RZO4%a|wnQFJ<6|$Ezy#((18Nbw`RKo5yS#&I1pUR;j7XbR5db>vTp2fwv9()A$ z(mBhQl{ZPv*yC-=)?zHLs{MTF@-rS<#Lo;BNr59`_*W5}j}<0%?-rRaiyLeFN<z^U$vYzCM&qMY|Ykt9;|w z2l5M6hQ8Z+tJuOMaXQCfLa1I!v9-1J8%&mDFb9-TY3D* zIP=5Za}K(q03);7R@gkn3m99|mLKc4VT|`cEcCoxpei0$ZPM1PLp%QZq%`gI^Z1>^ z{KcmBxzn6yvnMKoPMZSd!RA}z)+qK?hHl3(Xa++Nh>&~ zGBeBsj`x)tmBLb9U7bzyq$%HhqY+-Sl?Qc-(Um*3K-sha&I79*J+~bSBoLDTJ!m>m>DnQT)$!n#p7hgz!5E6&VD9(0rAU`TR2B z`{LqapsHqL!@|%g#GY=e2$ZP=#Eq?Av76)d6Jj-3c5+GdXj{XxP<|Zk76Xx9f0i(H zfp^UI&}fv+baqqs$5t8n8`=W#8G75Ckteb?7M#Jul-uH81G5>ZnEaE?!TWt1#cHd~ zPRnn2J&~2iD!;gb1u;zJ4a}N@*`NF!LMPZBkjP1L-whX(by+_p_|N>_k5AX%KHm-B z8{RLbcm30&U!UbZH>um}fBZjja^?SEBKYrDbOMMB&K{UL!6E4#Tv9hUjQMX*sHyF= zcJ?znXT1^7cKja`yWw{(T#8J^;_kQaj!)~?yNVg6+BNmp(mf`pzYGQCzU$EHxha0R zevFdJ=!lUuYJ00=p1ESL-AYluzKOYP2;vjK6c4K2(@@D=;u-|ry+y$-tx%&6^2 z$#Gv_cS4#6joDg4OD`r`UAwnH!sP^hFHU0Ieu}0`FP9xriuHan#ctfh zw~FzR#~iLtIXAw(nN+ac$>Z2MSh}gHxPE?$Od);V^1d9IUY^kNTS%)LXP)Geg{W@? zcXY>YJ>8&`9SMDvm%!bQw!~?=`Y_V{h*>|Fy zBO384aTIrhUd?+f!LQglODRn!L&da_SjjHg?A5H87~kREK)`;@T52jTVjP9QLnY6> zHPS09h@5%a^P%}RQk;VILagO#^H8Ntn!bAN3k4l1G&D7#dkxul9=BSiJlcwQM;CoR z&K8?doj3NNb7{Q7;XjvK#$16i!2hY7*A%7+n-?4Zr29DmE1|w9+p;E-dnoPIZDgB* z{7-Src2bYI$+O6+0ytQZ?Ap2+Wq$k%)o{H;GUl@4QFiv(G=(x_`_^9^Eab#QjUW!G z9pjyrbG9bGD;E(sJa?NhMRW8NzI#+cN3+Z4J5t|!@-7Zlpg*5SpYUmE<#~SPJFiLK zfFq3wT8@IcsqR+TtJVK%Z{No5I(rb+F+PiM3~F&Dpy$HEy))GvmL8j{Zd0X#?Oh#N z?((JLLfWGc39bpY-kLMEW^C&K}Lx<9otLhD%3NTz>1V>X(9-?X>5lgpP z%RE|__|FNqOZOM8JK7xQBeRB=UHtcV(i8P(i9`8Jy)awEe`YfOUm_z}r?a=QVW*SE z|GKW^usZfyzJgUHDo1`WWnGDTwc@o-1&>Ntj_hEnx$^a&|N0iVxlIr1rNJBRojhgy zgIXu*hwO0L+dhX3ppM`N9q_00aOzrLaYoELogb_^vDbh8`&-#ziOaYDxdQ$_k-`60 zA-x_6oFw|<-SRxPs8KKB^xm#-VlQoyn?XWE1U|Ot3GWi*2wxAb*I|#V*VNpcI&$_e z8BT4tTuED>rOGnSu{JBokLU53cj}zpHwk-hM+}k-#2}F-oVG7sIBvENPrJ7RWjC-- zm|iY>z)8cgH^TUO2~Duv1M5^de*kJT_j+5mug}C{)+qRVP{g%%XW%-$>u4#E2ao~Q z=$_Gv=4iABL`?U6eZ~$IizVU}FMc~nbokQ zL<0#R*Et^`Gniz*oC8!&+HRcSoV#D-=c+;hm^fjisNKQ?q{~Z(t`ft&0oY{3wXVt*HWiDUyrF_bW5ey@(?=zU3PX;?i z(ZGn+gMkSdK|(9Lc$FoQGXG(Te>R>KW$9y>%FLHnA%z?3gAz{sfeRJ!P|NO`Ik$3bH~P5YV%Pqr#knGsg^kbv=KpB-J+IP02gC_?c- z9GISt(gIL9;BBwjo#^-a*+$Gt%riK7?G5b%EA9034uE}W zon7(vF}sR6;>pNha6d>qc0OF>9W8Lcy^7vPMw+ZVGz2=gcT_uV+}bVLRbp%i*tdmw zl`B)(gaEVf98mvN_V($z>i+lDXNJ#{KpIw{f5`;K{V}2Q4(4FpEu|BIpR;Nr9=q*^ zCX5YTBZ|8o>JL^X+QPyrYxn%Fd2xC_)Xd-G(E_kTBF zXJutQ*cyxixGNmDM>Q-2t#Y=i&U$!VW-fiNOJ8erYQn<@@PK0Bzz6^)_Jy=`G1keZ zl>bAr1IGs}(Za>p=oV^x!%p7q2P->Fz??7wkqbng;IpsuiWV9Ijp`}SCxYx}={A?a z8>sWewkH{VM>PM4i_#FSKF-eOW}ox~BE{2IHC) z2VnMlR~wT~&UlMcExXnQs}9PK?qxh(;eP+#`Hj~TKXeq;&ot^!@i5epgjIj4)q7Ed zwBe8vym*GU;P>?|iq`=n`9m2Ls(UHV#%dssnMbJ}Jbcda0b#FWzbdj1-`KM6*$6%7 z=y?xaFlw*5N_0{$^(?kkn-Dzlbe$gY^+F*92FU{9hLNl29t|MxjMS80Hc!Nb2f8qj z+AFaxIb;+P?=3EuSxV7{%Z|dr>_GI3hPoXszkU@9 z%oWq8jwGSO@J@M`)^eEujdTrWf+Xr>f5j0+PtO`#Zq-bDQ+f=BjO9c`e}8{ig@Yl# z4SRi&cvk-bm61Y6b5%H$pMh|{B7F4Lr=gS!kLlgvpjiG2&cQOx?s=sp>c#Xw?`1Q& zzW=7RsTPd7E`iJ@wxGlCf;U4&w*?)omIpGznu;x;QBkG&vi<-nziq0z6556TqiSB8 zw*P)YWMX2^l!u!PvoSKjv=^b-hSJvE4c?EGPh-0#aC>cPyO~SfV2#OuP$W_V{_*>| zS5{VLC-19p>-O#OtJ=mva<(`A=A&a}g8kq7mTEL~tVNnGc&WqKC-@i)gz8qA z$4~w!EHx*ttp={w*Gz3+l(?-XKfUbXPT3H&(*DckW+$ET3ow(q2ek-^nr2m+SNY59 zmVvdmzkh0WiJg*``WYBHY+X3OoV- zr^Uc;ZSj!_CfWWnuv7rY37L%U(UJ*9T3lT%GDQk7uMg#dtiU9U*JO5WF6F+u&}K{e z41~hX1WIw|o9*9Gh!?n5S8-^rUgGZGSm3m6HBXoJ?bn#bg$4Rj60^#;VJgs?)CT-T zjVhh~?t=Z>2Tu47Rgt)f8_yKLIkv?&lal`X0m`q#GIu(3vJobK7L8QIt6ziD-OgVo zOut{U?s@ZAli!bh=%PtuYj?O*rp3d6a4`7`F?@}Qf6e`u@&c+^N;PK5f7{?&%1Xyy zn!gO{UtN{*f4)}Q$Zv$7&SB3Nkzl0F^2c~lV)*Cz`0BZI+$Nb@QGX{}MW*@sIsAdv z>dGiWp?q;@t-tR5HDzBIQ-1d*^;K-ifSvBAY%r$MF*$F}U-vSD>-Q*YpqQ7^3fj_s z0C~oM|Hj{cg#Q}4xw`hzh_I|uF|ieCgXZD_-V##v25V}V~5(CUMs0IR8F*RPHH|3xBtu%J6wn;qn~9t zV=uFoRTxh1W-1Z%I6F=@x9Bxe!xqv84vD^f5-XpnR(Q}ON?r=0`ZXC%AN1Y{Dm-4f znMIY3Y78CCPoGPzDU?MnViF-2(foSVT|o}*&I79rm<||~&4*PXZmuOI)&zsASX-;Z z@lQ1SD=nX}mObb@5;=1S;4idBdY*xgBki31^3f;Oi>+k6^vEV12=DRzs_hM?I``P0 zsoOIR4#TB%YhFLh@Wp=3UB3N3R$3iPfTcO_g9r1H9U?k^c{7w~V?N;;N}Keo9pcp{ zpVsRQ+p`bHewOfQX1F4u`Z#bmFZUP=o&GV`2}&CE0o@a>k2{a75m%C>Yb}G^d+qRJ zsw#2Htu2k$NcOd#Dz`VqGD&RCUovhTTFo4}oxN-=>y&-*yA2pW#v|#FA$hBLY&@~h ztnjdwzbG^%Vt3*E&tff}^8xqw_Uappi|htTmU3hshX{qLUPNt2Zg4vCY4uUMb6uF% zAl6WM=)57&hSPh=Ip)u@y*$p3X4B!Phk_yqE8*4)5}Uzjj0RSQ-*b?o8(89;s2!~K zT}Ao+A5O^EsVGRi6W&lJZR9qlHr|}FH!k#?0XZmw(g~Y#ZY-jDHi2K)+tOVO7y5-j zUl}gTX13hYdQyKc^^tPlVtSKfMwBFn+CLlY3u7_&2RszN;6NJ->%Px6Awt3AC*%1S z4?6@R&{iv9qNaDI30OF5F1!+liQII53!b}3Q}y}IWlQ;g$z zJob2bOM%5dAeidMDfIrPD&aBi_-W?%&*9;o4^h_bJS?pzP__EYKD9=BJWjQLNGMbV z7|4w+sO<{~@jkwpC%cGaTjsCAyayX{9->A)vcFdY@>lSMBNz6$w@R$ey?|YMhbvp7 zzv=7@F8WbEgciYeJKgs#=)}~Ol~rvH?G!_1G~)1hgJG?Bvxl3k12gS3I|O8>FQ`B+ zD^eJ^0G!b0r5P`=+hn=fT@*FgLCidnAoi}b)!A-MY&^A|;EV z#)8b@uQmE@MYZleS%JSL{tV@4 zjQ;RsmJa0kapzx^rTklDe^PoD-+G9Yd=``?!kJeUktPrPnLKx_yph38frU%0^r z-5-Ii^jlYzdkwxFi98d5lzB{-p-}PG4() zGR>pbPj*BTIp#Adovrs?j}=#s)pQ%?+icGuqAyoV-MKw@6h%+TR5J$++<-oo^NAQh zcS}<8&5Wp#kbkM1e+)4dX;7w1VdMm&2Qiv&E_ii(Cc80S8-=zF`B>qwj{LKBI{sbd z(H*b{;7p2~eg-%wL53&uEt9~{+r;nsSxJVy7gaAG#eZK%1i4mij(;mgGL%%5;6GHD zyavMYYEGAAhjO&Ks$A@m-i(#;69oETZC=%xV?FV~7o#g}Nd?>H*ugjYGEsv}-XV2V z$3be;!OJ@{6snVoqWy+dsr;{d^V{IQvDCx6MhiF!+d4Wpc=YnVe;?bJ@C3J%$<7+C zF+>IK1=~m97iOt4^@#FPyeHJ7kkr&9LE<+5w9^royFa`ZA$PIjft0g8752dib1BjEup=Nh_ zRN7GZ>>m3=V~6@{Cb_vRe%{R-l*vt~mX?t*?q9-eK0^6`{0vy2>k|&kq8f!qY@RT| z*dX|QAt52Mv+EU0oHO;IOvBv%jpQt)Us;*f4#xf~s+(<|0eE*F*2GUOChrUcTDBc1 z)*5ZaiNoUy{Scq-qv@YTQHH&H{6(#`wz>7{0-cglv?c}=e}3-ndy$etVRXC|e^7p^ z3icF^+GVS*|3V|ptX0$WEfLt6aX5es(q!$_C@4$9=a6> zl$3fzkJHoB=^fUa>}K@68dY?`DV?HSH%fyrRQ^JjZO10}u!`M^fT1?h5gD;r8x zkE+oT6~;E71?mXJYp3hRi@o+f|G2lWtM(KiY6MXQ2}(NQPH~wF9a$I=k&&uzsW2V^ zT&Z1JJkd3u0b|gNjwta)KhrZ{hINq6H z1koFKm{<~3?*$HCdn-G8Q4psSmoIS|TA`=*m)H9>@0TGW zCC-pg&o#c&+b%7GCXsrdCC@VEQ@|9oeI!QOI)CK*t(Kzsn3dG5u??kzk&poo`aFE? z0T!-5Wk@OL>cXh)@J?W>6v3;Qvl2eEEHNfuy9;gjkH0%=p@*t{{<3&0eLE^O^Vb1e z*ShWpEj>NP?c1ji$v;+Ege;V}0dEN|(&QvI#3xp5^ks z(HPpVD9Co$*@O-lt#V8+S4QE#AC01}UA+_drrG~QWnmG2l8tFBr0C;)^gZ;T$v+)l z;5gd!%DuN!%;CDj7Z=}UZ=GfT%RE>>*N2+<>UE>5TIY|Bqx{Qm?9`mEkazJMVKQaG zo<1c?x3hbrTT6R<# zR&8gKO|Q_d-)&mq(O3YcUp*2lNLruOGtN3T5^QsfYC^f9J%d#4sYXm z-sgSZ-=Dwz0mgRiy3X@BkNA9!`2KBAbBe7Jtwv}qMR<11#?c36$w?o|N?UBD-rr0$ zwbzzMC%baYesxRdQe>PI=>eZLMQxhLe6!M=R1!@Jw&UwP463GiY0mcs$CS)u4{I-F zW}8A3u9>`dVM8b8{)~ZDdTxwz)0+_`-`U}i^6Ph~Yeu!yXEPn-~ z9e-536CzvXx1Taypz`=VvO%%gK@2B^%dH$Os~G;V#Jn^rm5iV7MHbl2MH@UNx-Nfg zX^FkP!|uR7autn{xRsOX{9{W4-TZDh^a;Nj6(tugB9;0x+!p___OxVg&7{jVc%NE} zI3PF_6#2^jI4Ey-4^a?%@Fr_%)G9a!o+kcxEnag+H!FmOMa*@n{qWv^P}9IUnW4~t z{M{sBQLVh8^`H*bA0AMf`kiIx+a+967_Z+N?CZ=8PSF$GYTSk!k{ixzS2;z09|E}( z4Mp|*7L@Q36L8N>J7E=izrE3nm5V*t3*S|b>A65SI-&Rv5}-_R64(6pGET&e^AY820l#J~<0w)fq#M9i1LPFGEqQ`tV8 z`Qq^cKdw$Zord2o`t2JZIWDztCr1>r!&gY#z1a-PgSes)$Tp`*w`gD&@l^sE1)$3S6 zvrf$#H}>`V2S7=3;w1?faG_rREGP+=E*@O?Jv>fEx8KgbP`RZ=frXnrXkrL=JN@P(T*%uuRAwrB~XA6O+%x@?@R zTzbgs(k0MCpL*z#=wPww)uCp}z)=|^yDbhj`xBE&D$m(C98X-L&a66Ww^cMrKX!D^ zK(LYH@2{*=T~hW1Jzv|n%5SL->Z+fud<5bxU1qmgqcK}1je_}J`wp^(XpMgnfea2z2<*YKs?^wm+q9~8?=(sD(OVE zO$13ZmW0VJD#i0DdH=TvH=^{b5_M*JxKFGTk$C2bs2EK!+D;PWGP^?dY#`}f%97?i z=iwttC4|t0-r;yCSPt0i4F3rEp|jmSdtfUNtK zHg5&XHQZvw;-|WP!9WHkhbsG~D`~S*DJpD9cjt{=AJui^?TaOz+m|gMjHm8o)#`Pn zpi#&BmyMR(6#yV;YOd3i*#TWSee(R}DQWYA(|!W~=#&c=3YCc%pIl-=8cjA=figCK zu2fJ1@64*?%*~QEWjj2w&3M7;q=DTAud~Z};7>B0i^{VvoQlvm!sE?=O27Hb-le!7 z+L%mjV+C&Yp`?3fKCEkt1W156}RGVpX=dP645VG$p}rOsTw@`K3dGd=7x^e z+5;5o8LIaj_q*dc{tn9YeEXrY9GT`IcttVnsr})}&$zC#zQ&hInC`Rx3#zUg(RL zQM3V-6vEcs*>i4wR-Wdr25szrv2Uf^ul#B2-wtVriF@hZ5{Q(1YhmP1x1V zBP1fi_*Y=2EID(r8_OhiENO6e!_^PVy3*2wPXE+3bvz{Tgm&*$KMT}sPog9jC*5@S ztsAiKc}LApQjgCW*Z1{F>DGWwP~?>&>7U*o)%Cghs+rWJx8@NS+_}PDY{RjyB_xXU zf$vOjiZ#=6%uIK+4!KuFyuo-7tK0Vy%XqrjMn=Kd6rEnNtM@nT^6%Kk_{xiNe#@hN zoF#Qv|8Cn!4+@bmr=EB4%Gk+hkHYV$txKQj=Poct!b;PFvMpH)6e15qWJ2AHNFTvx z&yVdXaIB1Bv0>$03_FWt`%~|mYF*Vw2N9Eb)$(kLl5u=W`Tu)pDc`uUP4U-^dO?2q zy^MGzyq)uzQ)h3Y6MShh{v9pDew^<45$R=IwO=C-PVK-IYKRx-)~jleD96jETfiAS zj+pj6RU3<5dGs6+L;|5d;(g-y?$D`K?!Ueur9Rr+?XIYsKc%cF6y`qiF5D5Sq$m{P zUKbrcrI2z7=d)nPDm4-!?>8%{CO`CS)LAVJ>A=b{D5Y*Ik;uQEL1oF3EhWKZZ7Vbs zeP23GICe?Spn%UWjFUme`6|y)-9$2VL8o1-}R(c>s1s12_ zCc$|S>u!Vuz>b5^%SEM+W-{J7NU_ELH(e9Ds*I)DEM4N32i`Bpmy z&Ep#`-X@f{z&FK~CgJjO_`(Sx;U@-1zI%#^|Mi7C;SN|gNy(f$h@_+_pBL5DlJ%b2 zoY0!14)$?7Gm3)b%ubWG1-|vovBKIaRWicf`beE8SMQ%ORT0h2`>HAmYjQfXYRmm> zF}}Bv6FgU09$&2iI!(b+Xqi;3=)m3mJ+5R_o`u~}(xtr&EW;yU-6*gd3!e=)w?#>#80TA-gppK>dt zlg&hx*Xt{h2`1WEny|LrG@2zhd2&TGyzzOrH-mg-k=p$T0i2%G_@Xg;#Y^^t=9SJS zRH1E*c(w-yD;GmKp6{vi^YfIk;dCVAGk|1u8_c!+PQ{GKFuSUir4j)M%4SFdmU(Yx)27 zb)SgGHb>XzC9r9Inh#JOB%N$VN8~O?*J>qrWW85a$d%tPSTk26XS6e%ka5wCUNF?7 zAu=*Gl;pUdVdR6%LytE_=}$XIl`9ciTO!WoDS)gmli_;o8OlddH7QNVFLwK`%ItTO z@>mk?;i$_Y?6z0o7KUN$5g)MVS_H3{uQ`4ghW zt@?w{Et|mTS8%IMw9AKF!*ZUy$I^U7=Ei-dcroBlX>&x!lZvCT$BX2 zKl-TD!sc23Hu~0b7=_tm#08c&5bF_b5H7uNkmpv`ZZ~Q-V#YG(^yDVD#r&q{ zuJ-9f;IX$jvZ*clvkh9mZGUZRdzF+`AW}pig$v|D`$mB4({s)}||GxsS*|DfxEtSC410@a=l$kdmoY2p7pVo_V`A@Ecr6(ah>G z=zpmlp z){Bm@$k5Px&QEV}QLFjYkQAHy7J4-c%;Go2ZRF^XhA;}~RN7XPHF$y+;u8QfHk~Qu z78t#>+{G33CXMzdnGv$kdGoJZ({g>E7#8?VA9x<<8ahN5`CHUe!o=&_Z4d@1w3h2a z3v_p_d8mDNO_U@?z^v&zYZK4@el)hEmzV|e!Uabe(CGX6*naeOF9S8M;!7gZ40IC% zW*oTus?VOCzj?DcutTZwhjFWTubpJ$8W;E~OSoj7-b1U+eW;3Wk7OGLGm!S2@Vc04 zK!t4TL-__zX|65~@;6y4wQx1nSFDKBx(+-8Eijz=ZPYDB7y=safe}SzIUb6dC8mww zJrL;KtjrSwr*7<;7UXMWe)yrBQV%_mf3#;&>F)mUhg~T;jQ30<43YKTDdQ6IMv=xX zd7I3(y3_1IqbZ>g&YchYeoYhI+ z0(;?Gk~|j66@6zJM$q1nY>*bzBq8eWfvJ3zxJ@yQCne3d#+grjF9EN)dT|}NKnUb z9pZn}UjvM0jFgfwpBKz;`;mXc2F6dSBm$4wQiTTjKQzW1g>L5hxw}{ zJ8+l>q)gTap3>Cdhw2k^Rf3;ih6FFG9p(=lYR*gu5uun)3cp=Fo`)Ygu0iH%oLPEb zFGK7F4?bn3_YYOFcNmgz`P;eIt}NSM{_M0KcVOTcbJzShur>HZ&|bo z?{C=c0T=7xYMco8f$Ws+`b{h_zP5SjMY1yQ6)IJ{ad{&LW=ENE6ogJGD+9kFS9^Uh z_5%_`C%_{Be?!Ec>}#v)V?@NTXLH*6Ivm_QpWQILk@en~`Up?WA9*2M>bAD>fW8Ur z_>pfD&Q_+Y7Bhym84<%V4sXCPv&A9NfnEbqI;W}qoRs)ub>h}?XOe$Il+zsIIg5{$ zKZrD$^d7Fc%=ENn;?pdYnfRvYRnZaYbu`(|VtoxUTJBt{Pq8FKyvRqcEnjt+<#yn+ z=2C6o9?|*@wLW}z^ytxfm&N688Oj4?t=|rDE>b3Z@u$(5CnAB`f&3Mm9^P?ZD-Azh4^QxZS$t{xSX!+F7ff9xp{Z3%ZO*d}>JbL5Sw5Yuh@P0D5#8yob(3Uxp|F z+7spiH7}@LydJ!w*Sj(G)j1N;>#IXXfMpwc1nHPv)FMe=R8u(5`1INLE9q_;;%}?i z!n>qikS`Z&eoMiK4%qk7$IWlGLcXu%W|d>3OB}tc_y+>tCgX4&W)6y!lPjhVH?$VJ z%UpEmHs7XMN1ZarA!kW)lCO(7p`7eZ0;FrFZ@r2A>#M94PL3Fjk+{=u*DH-A`F_Uy z8Dstgw~8?3t-mRSPaJH? zB>#(5{9XNG&BWJ|grL!-1<4t{oiximCx~xj#&>$;$pE#=^)Kw+O)F~G0Ki+jb@bB{ z?&ow{*=4&Gp;dh65@K|B{PqX;8OJ=sA?en2jiWCcJ6;CBPtdrKaanh&k8r4uaF&&o zU;4~$&c0x11C2C7#_N!X37a#3*0RKWwB)9}Kn$=bQYVB@l9?<0}o&WXbEc#gf^AP`3@L5AOb_K0=0ilJG1)HjtY z$QD`{z{kI!kpZ55-2KS$fx^(R__l5xGltPO72TdN!_nX-=lCv2Ee*`)XI!9duois{Y!-VCU_E9tAqVEENgrytmw-Y|<`i_Kr}x6K=CrdV@3XJ7yl1|BSMJVu=5i zH_BNM?i;;$(}deZ$IanBIMHbam9QJPO8DaYPaR#;>12=)&LSg}#Sj^X{ z@pWNL!Vjq@T&qlIpPi$!-n`6Y+j;M)F;HKUQBSPOc00JhK|Ti-E>MR{bMZycX&Vhn zbd2tUqMSzqtf($y75Y7&t~do2ttTucs|#7zG1)UHeKHL(Gk&vc^L|o-5-pUs#E#7*`I#DSc-mZfc}|>XLHJhS8TWJdO6(%(E|wag0oU z0_SEcps3#Y?x#icJ>k^H=(;{Zt;`9@)Ds=APG>IrDdy2|t#D1xOov6sHs)8ef=2n# z)jkXcsDoh#|ARS?x-@lK=ofzcp|31zZWwPfH#pM+8D%U81673G4+>zcLY921O<^OwqHvs_&d#Q^ z3toM0HV=PKCsW(}8^uTOZPTRTHK<+}X)R;EC0GyZU|N4cbF}X=!j?I>IlXW; zpe?yeg_cc(KI8JgW``4X&mYMi@{Q~^A*nyotcm_vh&jkp^#z1exAUOby_k`&cw=St z{T3Z^-)sOrrin#$CQ+R_ ziZ^Lq3k5d2cfBufiTV(1m|4l8`K~?Y-mV5b2t>7%?{8vEE^g3vg>Hk~i@+aM*({f2 zZCREd@HUR<58RlYWqh!#K+!wV-MHh+KZPkr7OX9j3YR$K=d&Y6;Ex9Sg&(|`?!_%I zm{dndnLd_qfo(xIwInQuXADMCWQ4S0O9`K#nyM@Wrv>vJ`ZcKQkr2 z8fSVDnuWg>r%X#ZJZCDRUk(5D?bB4+e(vH;c3WQ?%UpK~S2jEbvGvNaLV2BoRL>*N zt(&4aC}KN{7$4b94EgNm@r@}}SwyUDx}-}I_BK5bqIaFLvp*Ds=n-tFNc*qT{_&k$ zZN-UGhNbF$%~u0Akh^XX9LJ^X}(Hh?@Z;vG5L_lOj4f89PpiWkxSIas0rD*QnsPz>uRoJLc-k6lK3#w z3p#$CXw;A9*iocQsJ4Guc5?Rs8$~ZDZay>Hd_cQb#SDCg(Dz3A|KL2HF*2&agBcL} z7Rp4Zh=~o<2JLU&A|yuZ)?U&6c_+ILvs$k=*pG1SpPGZ>V|Ocv3$A?U+1Gi*6nB*S zIl2qXh=D6Hb}+1mN1z@&HwG z`e8yN#HQ1vwUBjiNB#_qqV*`Nt3?G(hYi_ut=hrPG$|6~VaCbE1y78uDv`!u-x;IV zUme_9aKYoz5>&rU#&i-fVp7Xa6AZrk%aq9$!imK5`KCED4|M6y8-bax7{gCtj@*h{ zG0mZ{o(~6(CyVRJKH%V_jDE*$_m%Ng{G$O7!E!nm4P!uMbOW;`B900LZc8n9d%zoU zLtyAS8?+faXNM|x(TK====|NOw4X8rCU+;9on(*ZBHSkWZc$h1X(%8EESlX5C8wtc zJ(rgig!HG9BreKMzvdG-vjoFwliT?`_PFUbbR;Sr#SHZR6?Z=dgB59XVg1%tN4Q@{eBz4 zImZ``9Sq}$hMGJIqo`*Q2wq-2Os*X<`uV>fcs96fDz>0!0?lOm>XZ!Hqc zWfMwsXZp7*da+|^-^`ihbQL7bNEL)EqhiK))PDw7589JW)XzTAzk+REdGfiuhTt{A zw`yG>xM};HjOjt+=-1_An5lSC%tzV#HuZa%hHIOfZncBz)OTz7g}lW&z+oSsSw4in z4q>WXvX-WF6R&%8I?}y4$1;3y%HOO#D3{?wWm}nuw+;z19n)%$h9nXo)HeF-MN^); z5DIUdnWmVap|hq~PVuV}FB^8{_Wp)VMJqIo>J>4H7P8H_5d~h~l`MwhlcMR=v*2X~ z7FPD{Y>C>f?AN7du9P?&5AqneveNnH8-_{#P6{_Q4U{+7$j)~3LJ6)Y%1IB`k%PYY zaECpF#V7rJ+05mdMBTEAiqIm?X#NB%(M91DbDgikEW|{*|GL+B{E-v}Kn7H*I*O-C zC6j;KmWMX$!NGo8^psiMKj}(lZ-~r3NkR@4iqbg&Dp;mp`F*kCg2M+)ZV@&cw=hqd9vesMV z#5lZ3+wtz@<%2kvwSjG$LbnbklA}qQk8|C~z^^Cc=rdrVWz6yHy8UT$UW!~}OwKXO zq2;>%QEK}Q_8L>8r*X^{_aDIdwhLv3JYrw-KiU~s2U>$30p>BwAZHp9&jvFq%rzv+ zDKNB-gI@)(1p7fXGsn(<5)1!(5ahB~S@7w*yG(LT@^_tPS0~j(WsfuIv`h9#p&Wzj zHl8K#KaEk?d05`?!Otm2#vfh4P9;j5YfuI#$ zWA?fYyEH`^t_&i?UQifuQ>Sl^2W#RqJ=pRPYvh!Q53+GsRL1mrwX?ZHR&T47o=b~I zZ6CKTe^<@tzOffJMJwtInq14zw(T-m4o=t)Q5T3EjGW3|R(t?I4`TN#E5UEH`K|_Q za+(WmZsg9q3aIqGPameSwPr%Jdl=^Z2t7T$#u#L2zQYr-M<}IM?XSO*>Mw)|mBUie z-nD1<3qI_GH7WQms2}@_KSVX%hq25<@KO4{)W8?i(HB8}>kWrx8p)1l9ga}wb;>EJ zI}xE7Wf9%;i>pE?>IX(azOTzikSn+;jVd=LGQwDMrlADG+NpZMR)3c~R<0Flzva&6 z^fxp*QpFRqf|XsnYXUppR(XNl08Z?8-o3i`=EnLHz;gr;1SRTv=xk{}5v?GC7bBZe z(3KC);?;y)%4Lj&)TqLR9bdPwu#mRe;z!po3QmJ+ljvr3h@q$lLFh}qcymifPFdTF zUp!C4*>&L>ALcde^&kfv^{wms*UH?e*%eMqdF|EZG+3^;Om*$idWxo-?yiuT9F)DU z+bzh9T!~g~xgC{3)cI!U&x{%6#mg`jF*Tn3FqqJJpHO9uUEtQOo>{&2S8G()joJsL z6v=p}?%S2cO!7AGQpbv)e5<(;`>8~qsH`5=|8>-Se~Nh}$R&@4sV1jkwC^q0uFni0ZVZqQwTb7Xhjz7&($|c(%nDZy?plcLt1--Wy-8*m4Urjs;TUWw zTPygDj1|fnjE}Q_gn_0yH2o;<{L=#bhZteoo-M#XCtdric%gx&i&=N6i?gAI(mrS`Nl3y7ops*q_aFnxUKI%hv8Iq)^*U&oh@!s^8EJ z1V-=AMIEjnSKFd(TzfeT9p%fq4J2g5Ym|YSLQf6+UR!nG^jw;fdW^dhn>D`o?d8bP zNj26GCk}YFA!~~q=YdUszNJF^R~~1<>v4Sl)NB4%jW<&rrL3U>wA~Z*lg%8b_vHk9 z3}0^5X`IyNm4mLK?e>?aau(1DT-{?N)2z!kS`b{3oKw4&Jm>p;D{ZRZXr|}(i?}_9 zK)qUf>alTpMgL;L7nMwUck}xn6bU;#S^kB(P$d?`r}OHxYJ+I(-vinITraC1Wq z>&h7IwbXD=2hQy;m+xuAE+&MVX*+cTRjO($|MIJ^8CW@j=dPEv*Ba}Jmm9CV)&P%l zxoLVra&LWtPQl#A(6NB<(HQO$J6qg^9+;8cGpCDLkRkIWr7QiO`9ZJfxo{gl5p7Vk zx}dTyOr}ASu7uSIz1QCe3S8tCGbLd8f>|uh3Q`5ES?pGOfdb$QBGwpGCN~}q88LJi ztTprzcJ405MWmueTU6UkZ4%DuWmi|N|liGp90-nE+vRa(P(SYUygF-Ew=%B!_!YVf^Q1B2KQPjihHq%p^A zb++TrR$1J#sooG-6wKzge%WY{2&zuB2dY`Y@NWa~o`k}Ws(oC3^cy)_4yZu z`G$WpY*Hl$MOYbHtdYk^DT%CPjsO)mcWyvTsq%lzYWWZPF&)7kAgiI6!9`@Et9TcS zz)J~eE->-Sa;%_b)0g88^Q{}HKZ|(&XQt`DZD)|SnVb%AVt&6u*x^LH=l9D%lSsz= z@iO~SkpJr)X)~a}%770f-Bq6qdJ98aSms1pSLAc!tg9ITm5f~)?eIyfx_|GU7>S@Z z8vep%G$0F}RZUpvV|O#`*)j0=+bCbX%;)?4gQ=KK(8>UefWDFDy=fB~dhy8j;Te&Y zDzCrr{UpIm@{=3$z3S!WzIK8nuV26B1*LP}atEG=u`2Qsd?2?BXQQxN=jd-wzSw8J zAtn|&WtQQ|ZzzJ`#5d|Q_vuK^7!+%|t>UFkhmxpB+9J6pl3@@~HbZ~5JX|2MHTAKv zvBR*_s0XiW*JE$pTQDSIXHb9CtabJPlh08ej@7{WP>x+qbJp=7EM;?ydG7NISZnH8 za{GqMCbo(|ud*ax#*Zg|11%gI*0>ag!X-``3-=?p81*!3aV)E#1Qpg%&%b_z9T^YZuK-suyK)XwURNVds=zCz=n-*8?1BL_xy1%Re`LU-!nDg4Ta63cYtD@|M4aoak z<4zHgqca~1I-?7Ww1>;|PS2f<_z>ic&sG1O7^kBEGRWArg-8Ke#${sW;Y6cl>grgm zXN}mdIw#lFx1k(rIw^pF= zo!Lt$MF?l1PH)D(#{Oworr|zDn$MCCq4TV=m~aPG2GuLZVNseW9EF$(**RDVzhzGy zb~Ibhl7KUPvpg%|GI*m#xDne{r&@;BHOZ{SO(DK7K#fky(=u?UM>!I=Fs7iHNzApbw*Qv9v+%)-|dhXBMQXf zQsYZU9s0c;J5_YK_JVKjD-9zcg#B*85`y>b`uMhU)qBHq0%mso-uGl%(sp>~J1DH$ zqHOXzVs|$*78SVXJakfxU4%IzoH}1eUYY7?!pR6j+1TlUgs;h>vMOU$37@{t*k=H^ z3sfui-+m=Y^aCau?t88eseoaSt${Xa%E?maKo-qO5{Mq8pn!MRt0gyEr!=N`@hN3O z9)&;KII&wuntaTW^A|5RHOU{A;u1f)P9=N#92pB6?;Frc8qgzW{whxe(nkfxt=;)vC@_<_wm4pA*2b;~H7R|o{8S0dVg85526l604z=B%9h zQiJo@-RaH1`Xq4fZ9%j9N$M;lFH%1Z;J0|nW4z!2MoA7OAa-0-&2m$V4Cn2i4DXAf zg$)llMA5>ON_^o5FFj2<@NZOoK95%p>4imy+^s(uw48f?uAMd_BETEZ4JX^(PDdml z>Jd=`U?C9ZDI93Nbf*rk=<;wM`Euj7>hK~PXJy-6u%_Xm`QCVlma%bi0%1lb z+2Cn6jYCIFBIqJTEL0`IuAuHKD3D*6xIpsSx38|ZEkKYJ56@7Rn8WWg)fwd9=`K1C zf{ggt4l?d-Ps1KpT@T##eZ1jfKMN-(XtH*32aR-a+kB^wrTDbBMQ4yNREYTAQ^yro z*q@+_*Q_`psH9o6_s49U8D{wgS zxBH;c$*p40q+|mjAj_z%;k6Y}Ww)tfmxl@xt&?b)mz~jtK!E|vE4v>I=`b%QwviLC z8T$gFF2;4vWpyAMhv}4!x)_j~M)Ec|$I2$FQ-=N++p6bKl@kjX@rS*q4=%j8PY`3{ zqjzy}Stna>X>C3J7dv~{!NJjc_v`Nr36%|M`@^n($sR)Ixp&Brm=EO07N&8&Rs8$F zFsY{r6m@48ZEGe=$ya%KUgkM?k|vJ}eFB5!6M6)1RFH!`3dSy@hDo2SIis?Pel{W3CWqH@7AcjjJjYFn*u6>=kvuL)TIe$oqmo=f!eD{$7C z;GU)zFbxD1$EQipq(}D%J4hMNCM6Ks(u#b1q$HchXJ+JIoeVncZLs_KrsJ}GT(ylx z4fOB5QhT)4$vpREwu@opC=}09R?&c}rgNW;aXeqDadrZMQPo6XZ&xn|G}JjVQG9g` zyM6v$If(lqu)=o zM;AYbTQ9Y})blPtQyAA-aNh#`21{_&Glx>vG%x@IU7MOp5T&d8p?X215kYs&F!@#G zmmzIu&YTg7b$$P>=n@dvqb@FLQsNSCK+}Sk5^bGI(Q|SgF;_rf*Il71O3ih^JjANF z-jydkKQgb`CF~H{)AW&}+1>8CS95~17i?_Db$@l^rQ5TwrA3C<|N85^4Y!S7o%hcU z1`L>HRhZ9-m!x49Gx7)&g>H-Zq3gkIrWk-1cy)UmI7AVijSY2cR@RG zkBv#3^|8Gca^VRU-#Qx@(2=^M9#2h0TVIr+x4wd64o!$cg5HkgG^?1iKXje@o?Y;D z*1|0e=fOdnVv*&Lf4(B(dFppOx68(cbx-GV}K*&5nw zn9PmpNHXC_E>fCx38YJB_@;()jzbydrVdSeU3n;3=FW< zC88<-gJgHDv4Sa#iiU%)V754?>W_hFK9Xa5qrUJ;dUX3i-I%lHnpXt2LZ&UJBCFjY zttfD71CiX?E(Ia9MS#-OzxX+Qfe$ZI)R#^B5?)z}TO(ywFxgb5*jUca{jfgaaj=PC z&QQy(btA+i+aw$r=_hd2By22eAYSKcl`r^nSDee#sskw z@h|Q(^e1b73@x1Zko7t6^om~V7$UsqR}x4?G_Ox9^+1P!Dsfw%50Q(#{UU*;eX4js z?*7=eQr5__GR^!uV2TfZ#Hj%mUJL26)94MrUo6Ma;?$!(cwP1Ss6x)_PmSH zsvsIA$CYnE-lb#uBURrFXJmx**!bWHKD+Oj=e&^T#NF5WHivGTc76Da5}+46VeIh8 z9(1~Ee!q_~*s0$RjkkLVZLWIo@S$mR)4B{YwXA1sF)&(heelzS=iZPHcvQzUpS9Ch zuIS&k7_QTYPcpeJ9RW$T&HYwzx5+i=l8@1om_G!CeIZsD=-BlGhp8j1W4LYjb!z6^ zO@}l#`)(wGhNy&YTx-}EAyZtNY@6C~s}6Rk(BdQ{GUjD^6wQ+m9%%o-*%{l(EBjLmOG?u{rAQJH zmx@S?iO=%mXMz5KiMp1@NB|-bEsF5~pNkSQ?v02ii})b#>Uu3s)G1jiD5h#{&&b4c z>sZJWp3SO6LB(J?=!kE@3njFnhJ)|`G`i0`RsWR~wrxBt34#7%T5x4xdqJ^z=0+mze<8TxUi`2y8BGLncaO%|S(wm=?`)#q@-Q9c2?D)jQ$pRkE?e8WRSrQ8Z z#>eT-(h0q$)x+IE(z{dAQq_BerN?i{;(K(}%!X85BHTK|uOIsKLQr6^aR=OLbX0}@ z2j%v{TMPUj9nvj8%fZcM2l{k{IHRo?Rg$xeysuYGS@7wib3&L$$-Sh;!NJ9Qz6VI6WF8dfO@HRAA1c1jm#%V@S{IvcKe)%-ywr98w-zQ!x#==!`P0Pl^QQRZ1o4|++>{3gA0YISqL zw0#Y-p#Ssm`bgQ@h-dF-65@~JCr*YuzHL(otkzT7xwBtlihU*~4H7*{7ZbnFwrm;D z7x?(-C*Ge6O#WfB%+PE74%!jM?c1Kst)SHj@a*HU%V2!yD=8od?psUpN=ivy)*EfL zyG_r}i0NIth^4%ISl59s?(PQp>ZZdfv?orSV1U?Fealzjy3W2_jm5Z#65Lm)7WzN? zH5yFpF;#zU5pJvnGp{s1k3crBh-i<70JoQz(+zYy2t5V?-0`KOBhK(<%NwY8^1nOg z$_ItnMGj2{`M0pqG{CXz$RccC1^BL`E29XMLG>xu-Y&vYW`7$h=g1iEy)Jx`qJqNT zJ6LQ0$((A;hYL_7D(fojUcdo*kvrdL-iARW{L4PG+zpS~K@L{dRfQ1+w~;UYte)Rj;<-zGh-|z%Nl}=KaWjPci1ZIO zY)}b4cq=%+N8;zUV!^?C^~qNEF+L3?j`KHAl*t5RBJ|+3wIzmH=&NLiL`PZX5m65T zlO^^N1b*19e-E1A(NVL!jV72|Fb(umgJ`?59LZRc;G?UrRpS|8)#z_kLXqaFZ!wtS zi*p*?{*qkM7%(s#$%(Sm$~VZes>{L**Cj8+Zs7rd@ua-SdY=MS<>nL1zXHJ(wfC2J zLAB~{a9Uz;`+O*WDwL(qLH-bSu63E*P<(e3W<^GmQ{n_L0_sd{%S3?mthqru4~D#J zUbDe3Mr~9#lXYA#3P%>KeiA8(()BJhjU|JBH zrVTeM&$SP=0T2v0R6sak5)z%*4J5lI5$l-P4Vu$6YnCD2O|JyLzr>(X0Njz56{J(g zVA0JGQ8=dNq$@-J%3nm!--p1hQ_*tx7U^D-1>nQW0$6X>?F?)KJpIs$$M}=|jlb!e zXAJClf@k7f(9lENf_ORhrBSj$OIL7o!%;(wOp&O zICxKX$7N_&SJte#XQm(=OLVa=BTB)~v(WnQ`Ih55USu+CO z)AO4HapS0hwgpfqjHgi+BdUv9v(7c1n|^8?phZI_VBPV9Ww}4p;dUy3;JTD}1-y~r z0xN2D!phM@z+v;(8P*-0$=;Ke2{=mbdf`BGU>WnIw1$clj z`?M!8^7rmr*sVT$X{Y)wXVVhE8a;cF#vHj|D@4&A#hRa8J@$3G)^sCl=Im<*l!o&i z%l}^XigaeWq!w9|THb?XKK;>?F!HQs&MnCvJGS9r>WIBJq1}SY>Tmp zfwWOSS0&t7ETW_Qj~;&IAhRsFYAXA%$>>kKTf6&rWoZTUXD86Z|NU@SDDevhzxsaz z^#fD3Be{3)9xcy-9q5ww zr6r6tnt)*bz_Zb2;BhOrEYhkB+I8N%&;KtL@icj8OIjO@<$DGJd0 zSYYYVZ)PpU=r@+En(p433c$J&SNFZDXOIMl<}yIw(-S<&v-sb`(!B0GeM${Xxg2n|oR= zl4J!0)IKe!D3+@Lk|#=)CkuF+QfGYv!OmK|5?---vM^E9KT1O!HjzDLzuGy^aiqGE9+f=#eGxL%d(MpDbt6SLCvZD z)`BVr-s=MK>m09jU-He~FrEd=^Rdz|&$^yY0=I;?#_*OEtXnYQI}jW(35l8!(DE5y z`iu$E8P^yuUTM3%`cZzd#B!u8eu}l-PWxvHFgP0JKdLY?(^VqYgEx#p-w}|zLnmn7 z$|<-#)iv?T$S8%+V8?L8(NK@X{M)B@r7#Lm%i9WKV%~){9w0>|;6w_$@xmEJJGIA3 zpcn;EO?8?AR#d7AYS{jEcf?4VnsPcX4?ik2;dHYeaRqaOZ9z*Clfn=<+z^uhhu`m@ zyFzmOKjBX|OSUr|YT5ypmtUq1oE2k?&%(ExK#+lR`~nUK3{PSGUTmzgtHuQgoC{`cSG zwv%_2dX>N-CmR{nq21cK93v>&n|?d7W4~*n`?@1j;rz=;av0Z@A~)tKYZ=F!_F#rb z1_L>aMU|Py06Q;lWOT`8jOP?Lw;~BZVj@6rSE1t}UTiUt3OM!6ntY0!9ImGH^MCM; z=9yrD>|Aa)jDn8*o(e18)(xZGU4z<5v9Syn$(KqYW2H6}AYvnF|FC-<7DU$xCZA=-k*W~`kE0L>L|a>jaad+!dYt1Z4tc3ThVr}Km#|lbfgRUn zB%H$!@l*_28Z@fZjn^eQz%WR(Ou(!ivDv41E~Xu>!?~TiQ$HDx%-L7>5G(2vlrvI3p1E;aG){P+m(@gyPqi@ zJrb6(Uw`s9+so>GJlqIsypByFtmZUqNTzvbCv z7&Il6hTY(`Y^WX?*%n!;#wZ*d900iMYfTN&(dY10`*59=8T7y-4QOOgy9Mr?uJ($j z1kP{|i+E9kvw60L39xl?GW0pn1*Q35R;irlqAC$9!Py`}ULQLR;PFt$Yb`Ytzc=wh zMonhQhvJn*gs{_OJ1$PfVc`M!VhtWOsC|{2n>z>7O$JJ%M=Q48T6D)OOK#ULpfS$) ztr2$6kdp%B#%zhZhlDx!zw#qrooh9YeF(Xm8!tEkqEQff^Z*^!|5?k*(|^N#N|{?J zSZ^mUjlpF$ND+C-rZZjtRTE%NS-|iJ9a!T~-Rx(2v*DBzNU^P>g4ZC8fA=IpOEf z5uydlypj$A1$aIf2K2KqKEjl0;El9Y;8jq9#KYrc_y5Ry>!_;Q@NE!8=@6v5q`SMM zm5>JM?mBdLHzFY2A}!t0Al)F%p}RX~eKsnFddcOZTG&CB%<|~xTc6V`^#}k8%yCVXKrxicN?Xs({4=!b}I~rti zdR(CR6bzKl<*~!z(5cz;zA3|NIes|*X90aNO`efTtu;TP_Zc;5dkzGbEmL~!qHEeh zqq9iGz};Oj7dLOE<1U4E#??1!mj4#H*d3BzX8Ks#hIWNXKv)^&rwvStd3Pl^eYyE^ ziJY4oC$p3KS&0hm;$q8YlUsp`8dsqiwV{a#o~m;4W_L5<_fAeq`9>!?_savC%x(azi=qIa*g@*0avcu)J01)O^fYO<5v>E1}R;?am;Z+49RJ}e= zg8$nZA~CD~Ym(#92qfmi4J!-^0TAHt0?^y00sw=PL)ASIWc(i<1fu0I6#eHV{4@%F zd~F(E`p4yHvw!Em*vwBesJ`i!C-#5W=l?&3i&_rM{l=9mYiox8x%UDkGxJkYQd)AP zRH(mO%MMq+c69}GjsK-?c*3LGKw6BG)02oneNrr~0buhXw>}{3HvVg7qmF|>m&-u@ zif&`(*l-48quc`U`nJ*kawA4LMj#br1j{TG?ue73LTB<-&bOk&swf+uG{TQNCC}LWU0~i+qcF; zEHv!v;L!eD#9&^7;h!LdziLLEtFLk$u8zSo`1jL?NQ(WFPvB`l{d)Zq#`3?$V5a{S ze*5>oMLVm0xsd<&g@0ma{`tS?|G9vF7c0`M>uWH0Hymg$Of0O_)YJ&A|E>}hWuQ(O z6!+351ei5)0Q|qAjKXVF3j4pR+Sem}Ah(Gi;AGI-H%LOu8=k62**84gV_Y;+@ZWQx zqEaUSJ0E8F3r=U0CcfsUQKEJ-D$QtKn56umuM#NBs>Vu=ZXy4&M7~0j< zmF6io%I}wC!c$wXug4}N3)`QdM&*$kAi-xFOMa;+N>T#4**qv{>O@;KtE&2F{Yph3ty_I`I-VW+C?WQ=ncdOWvl+XSCwd=8j+Gy zLe(UBUJR?!!^5-h#}Erg`0siFf0MLToG=AiTK=7Z^^NW^Isb)Q04kD;`-9sN4H$j~ zl}WuoA#@B3KqL;lls{JBz;_rv0~EK41q3k28BHrRpnw=|EC(B@z|vPySBIU_CCbo{ zv<}R=L1Whcar2KUU9*0ZxIVRsC=3jx-IJSZtE*wa2~ZTKNx0p)Iw0me&EJ1khrgRj ziA_hal?9_B0szX#=clY3Z`uFJZt%NmNnr(v(_$FkWI=Xz^y44>^=1F3#aUrpV?AEV zj}p?$*UG=r3KXL0WmTI_Uzl4TEF=P|Kfs2gl!A?X;J+yLr9v2X%2Q?-^^AqMm~wI% zSb%drD!QgWxMw_K5Tl1T3{%T}yirO9o+UcYfwafY5pba04M4@+sjJJQv?ra;vZ#0v zSR>E39jiMD8%=WWz7NN<*fZI#$>~nO>I?2Qmie-u_(nmx#xCz8DKSSB^oq41KDR7f zu+92$RJK?=kIN=SoW?dYv_gT=n`}*%A)X~hJmHEe)0dt@!-e+82YtPXL8yuKsgp1R z{MMzVrNAD{4@8j=1ETwAYH0!5^gLnz?kZEl;KW2MKx0BxJ{ysu%?5xc7nkRNlz4Uf zVOT>`OS5;V^vwT{@hM_cQ&Xgj$x~RL@p1on%D0bJ-YP2j6@9*~-VoG1aX_Y_ow#Ym zufG4XKVtVa<=Xz@ojr%_9I7GWwX%kL-?^UA6@0Ll)L==Djo$#>l<%@wBj?NkVJ%^O z5LH?o5g6$>*ye62S#CeUT=&*}dmg(GY->O;bJ}V~7s6RulCKf9o`cnhiY6GG75$E) zukIn+0US8oGqy4F&Q0*b*Deoz+6kgVBPh1Yi=|Q(g9FLa9o5rcg~e_}O`6MtG1lqK zGn0U%kM>%3>PLG%!>goY7v4Cpt?pg~?)N|F!wCIvLF-C;eK(z z{3nG_tTZ~l=J?Fo_l1Qtln4Guz&L==ZB4-5UKXd33$RDfx3quxCsyf1UU7jE);fX7 zsVpltdt9tP7*ryM{+ENjkBu)IJecvQZmHmEUxsyl0-HQ#p*N@5H*wF38uC@4D;1#ap18m*z^x4Seo(Y&`Kc}CBZQ&he& z;x!<;CsH0nbQsJkJk(q=;#amHom?ADmX1emuDl7ylVGu5gC)fGpj^=4Y`g6>ufgww zv|d@Ua~>1eA`a&yAJZRs-i>tdrr9sAcs?FV)NU?m+V!YANUes!L?Xy;sq4j<(M&(z zz2y5K>f@`beW8-Q5|8WF$tX`k>^6Q*Ejdj@eC_JARV*}U2i!i8T;xXVocm~#F+AmG zWN@@;GmRqT%PK%<&ndpLdOnW zTvq}^a0LaT06$??_q4+UxQyJS+YGjuw>C>%8 z!3nKNAiPm3bLHe7OBu8LK&rs|kW_SC!ONBpI8*Y4c4Ww{MO z&&cLsfpVQ-da1T(&8{rjbUoeDY*4y0N89EyPh85p_r?s(#kHn^j@tzI4Iyb}6vV`$rvq!q}a>hnv ze%veDt>H5DCKNY8fxzIh=;f_KvHBJZvm z&-4svrN@>Va7rBA{N#1_%~k+l>*nU%0c|Fb2BgAb8W}=1eSiWmC;}L=0f1@9&CJZ4 z(f(29I{s;GE%hl%T4WJ~=}abSk6bD-BV)9Rooehyhop%rrKbpQ|GWyH=gF`p0a?#d ziHwgs=4aP*zV8WqHXgx$a*}Z{Qo(*-QBhUr#1`#@NXp5bj@ZiO7JcK#8K&j9OJqxukl=`b4~+M2Uv0gwk`WSpwbNMxjw-OuDg6LVUGF60t8n%{vqkc&W8ePr(5nMgM}>{s`T8_;ZI# z@G%dW{SmpgOD1K-p2_UDw3iF9?t6ztws&}9&!3g+O(`gtbL96}k(oicEIp7r*F?8F z9?A{yTh4>*1m-Vpup$m{By`333Mu`!c!VB5Zuk*!(yk@n7tqV*3i8L z#ZluT*LkH4Mks}F!SofL3+QjbUIMVVsH_sKS3{z-vF8gtetr zRXTB8D?Uoa@yX%<=k1{eH#q^nib(9y{QPIcmC+*qUK!a=db+5^911%(Z1~}dsQJ?w z`hX3JxFok7zwZ2rY0C*+?D&F+JZC5(`zZ3bZH;Kc4hm*hQ*bu2SkK0J&hWK{8SkgQ zGQ_Mmb$HYgEVfo$F%@Yd;rws`qCE-)?>PwxW+T7HQr5SK>e}JPmrP#lTP!0P-l|3 zkPtB>BxJX7J)$yTHxg5{>(xRCgkqN9?>*8ZDkm9_6kiY@d!{?Cr*NDlb~qjgL!`ks z5{&89b@?)^mh$CfEJOAD_rc&8<60)SALv0GREvl6H6?fHFP3BtdqYOwx!j{d4=zfV zTF|MU2O(ud8FfeD69+G_5*e<201=zRdd@+|)jN^C5$EgeeSgWaSLtY|F*oWQ17_56 z9&Adjtif&A2XhAVy#vULE;juN% zf;l~}b$4#GVx-{fD^RE50ei-H_qzD~^hQP9hK2SMn^Yw|-y+nb3yE z;+4beWReAJ0ex5l8?%Vr6|r{@ z2J}|HRB;(`Oc&l>XPLo7BWIB33l<^RMF*SqQHZg{X=^9zW<@o z8X4n}OofwLj|8Kvi8Dt`b39HCq2X#1tA&;vozdR1J3@5P_J_XLVcpXhO9H_qI*aX@ zs3j%=R0X==%m& zG0b-fS|WD6lyyE*-kLqw_!!p6XF6 z_8|Zh%)HH1Gmeo*dV6uW{vEO>1?{ILM_d#>1`iv9rdq${mk(QZHd3^?}$NZL#G zmG)%9h_meZ#v;NGl8_NSd-EB6H>o$BNOpL*Hep~jF&AjA>95H%jFy`0zAHc%wbzDz z$M>3zgG9BP$A00mBwop5ZD_4-$_Q=gvTF^Eg!BCfg}@uqF+=Ki2@6)(Z97i-rdR4mQ=+mTaLi57 z14Nh=`<==6PNq1KoH)57X?kMd$ys{;cOI}2XOKTpF`m`CtMK3>wAu)|TXzfuI9^OY zZ#Kn;tT*GHsBg4w?KnUtyL`TkC7pxddZ7Gv_7gPZe$UBhE?h)YGg-2?tjWbs^x)0v z@Qm)A=4Gui13i+Qe)=j{zku_l7>J`=o{Ke+oCnrxAgU$P*#=Y1(7oRam?1C5O-Fq} zyjrY#Z)5o6dLjAI$q+1$yEGLx*{+_%gn_v@Sg+A4>h;SrDfeN+MtWMPBa(6kEVhT& z`#E%Bn`y~$vdAydG@5J`@9-OAD(a7>HNTJz8h9*sGH+>4Jo+Bg85#RHzeMdS4WQkw z#@rDHGjVb?Ma>ql8qpG!(62P{R|GEYA5!|yrmXh8{`duR^JXBaBZ&Mc%3Adb2I4jK zwi-{y)9T))Pkl|h*>J!)(mZ$GZ43cuWEjqysAOe_xVX6?k4AflW)2h1pO|PafGS+_ zxW#x7t1;wkX)FZQbBVL5B=+vZ& zxDVvwV(m5BWp65?yTNdQ-}imrFWnvWReI9*J@!y})+j>fNaMR!6U-EmAu9heRjb$2 zjfAR~0Swb@Z7EvC4^3Z~P#+-;v{MKCWN@z7OeL1G43haADGY|$1GQW~o?i9$Iq|7D zufVPSTbC(H?C|Tx&&~aMU%$zHzLQoZyeDt^hLD$nZyEC{fDFL zBW}fCs5b0Nha=JqQ=jp9ekn&NWISf}Sd%2pB8gI@dj=S8*Qtd)qg!2D6O|lfii;xW zuF{EE9Y@q&0*eEgf8|5_&!;i8;nbV{M37E;Yi-Ri9D&!xYCuHESzFb*`e~;Wh*7*) z{TV&wXAv_}2Yi{|4AO`hxy`%J?ee?$0#~*yL>@fxlWn!5q=<1B^z?LG?1b$I@%c;_ z7y9G!t`b`(4VHACFc`8roO;e~aIF&z#+S@2c4UtGRN_%?<)%0t zr?0~DNt#|ZM#qMt#L9#4%Eghv3*b`4!Lf|YM=>?jU+TKV#qBPN?wCc{x$8+{F@)hiu)(rKoo9JYwAm;9E>|wLlp=Ls+ zbe`eW7bRNl6Ruu*Y;;reU*3-<1U3#IC$D(oId=Gv9e?EQM$`OZz_l$&3h;)2UGaPt zKl?s*k3tl86}!z88Wt87+N)uAu)uG*rryuU!~|f#u;`uo`E}BTw_9pAQhcxxuf7jL|%sv7Q$`S zUSIDt%t$YLuvJk$UV8C!Ud7($9_H0KGB2N3;kI9S*`a4lnA_=-E(bXq;?wIx=^f)g zNc-{dFBus|bM16?kAh>R-lcG4^!X39tY(Ue-NJ6)kdnD~j%FKi1|bu5Th$`3bsHCy z$%mO-+_=CV^s=J@pk6}{vQTnunR+0dJ@~jbQRysHf2P%h<+@rGXG#G6FjK8G4Dq== zm*e~lRwhBt;jVaZXu^QY?Td%g52TBO&@2}laTi+eMwM+%7A54w1r{P>^tD)8wcBen ziGI%W#=7%#DNxqnT}C9gZ|V#gT7K{m8_>#t6((>!S%8c1&?PsZY?hv0jw{pT&M|HL zS<7@Bn_d+XnI{%K`Ywqjel|Ynr9H{;0*G|{fj}PIz*lrU%VmkyjPNfb{R?DMA-Cz_79NBysfIL9fGZL{2J-yGHN)}8< z>3(SQ@s+U^XyLVB?2r~w-pZ?MQu9!y4o9+U3VTA=U!ky>@W zn`ng&5#F*8br?CEZM}Coob9XDD(f-l2dOW|<%M4x%pP9!s1zlXYBc}`7*0_HyyiBo zYRT$2fDS~jLhZ?Xy(RtFHMD=Y^)8@GzinwLW1u)JS^xcS4Fb)lq9WR|$c)abL`uNo zHKJ&pMKQ0dc%b@JDg#vp;|7!6Np^OE&QW_O_g-IQcE?CX1QD~3cxj^= zlO5vHOj&?>CtjI%Tg^bW0Ap0Xgc`K_hRkvx4%QJu@4)temcmv4K2|>c>gguTa-%^J zn9X0udl&$`Y&(Ln$2q|-`=lvkZ+ws_v$vS_N#iL2k?B%iK}7~En1Q7Yr^M6a8R2b5 z=V_of+!XpQ$va=Qee>;X5XxfdvE^0YF(L17@dCxclo5RxCcahogA-kIkHzI$q<4G4K6=f&{>9|sfF^C)kso(wH&0HMz(aD};&93!F5&>=oE6e{Z^3+Gpsf&hv-^nHEv^M?^0XCQ*rGanrkQ{ z?Kh5Q8^*%a%iYFY1T->)4KGI{GS~u-$=uLBH^mJLq>7_q9nGKWEa$uqy{f|PUNZw- z4JS34buw(orf6E?c2y3h)kZ1V5H+#Zmahi0?!yr^wQ+s`eHlLmrr7#BAg_zK?uoR( z?OOP1N=AhX4}#PB%P})La8G1zu$^b<53f7!i1F}OIG!Mb8TMdjZGO+kJh1__rttZ4 z>j*EqXB}ZnpLY192_6y7&gb)T8`w8$fDS&0LMv5k(9MgMQP%-&L@+m1=wew%9vYwJ zQokc~iBy5xk@*cO^_=aET3rjy!x zg~}f~FxxdB`YOD%foIr6{P;E~A=YlM-viMp%xMe);_*yMR9Go7cF@@1po!biI3G0p zJqyTvskw{`-4N}l@O`T3u;FnQSBYur$<>g>LAj~UIk$Tna1 zmLR-L*otTu!au!-&#U_Q`i&?g4ryKOYI@z}MZs$KIgieZo}yI5 z`aJr)Mwv0TzU%u@4lCr5PEvjw@}>O|Y2O*3 zMp(bW*QZ=mF~t`c`D#IDnyB@`5ndX(Y&Y`8e7a@N=ljV9_2s>qs7v_fpkE51!LFai z;7f>hH)Nr>hpS=b2hDE5Th;>twGdaV`6xLpH$sUwUdpa`6~pI}MzZvgNC7z#kEO5z zKTp6ml^lG8Sg2BxRcq--)y|~*Lp75<7*U-JDv6+xYN?{jIZR>6y=>vdtWP?_R+Bpo zW|sy|9Tw!-lq|38=6f7Yy}f$GP%VzTtL5~y!fyjO_-dVi)X_GVH)a_=J`fRv?3l^- z(AhOpekUg^k`V0?DGWzCN0MwgHLM`R2rre%=tj_KuU%--FH}%!Q2*oS17?+p&m~`Ks=TP`6&04%B2pY6yPX9uM*JU4w;K=j+X!jVdN}dz zPyEu)gWKGF1L=6!Cz4CP6cu(C)=2Pa#za>?mbNh>Z0J3-yIwgj;9`FJE$qTV%)3nx zIxk|S;ZvF!|A~PPV2{z`Z6xUDxPEKlyt&;Ju9yAD#cs0BR< zS63YKca!@x=0Fi&n3Z#ynh>3WwHE(R-~BXeC<1&pijaRS|1Izag?`IKZQ!rcNJ;f7 z0Fd<8t6iV@?`I7GcB{W@iV7G0KOTn^4KrN*uggWr=`bsQH`vo(Nwxn`J=ECp|35x} zYjT@z3?nHd6P6t_9y9a5$3JiW`S9;kp2_m0b)z7m14GeH&CV{%&OgULZ~po4uhT81 zj{mRwN>+o};_QoE((w`_)9suN6S!4J7dRi{NRST1D{IB5Y`G#_8u}dEL+A=Eo-?|B z@%K6!NEi={#};hm)3pqg-TqW zGdR6NvjIe#gKakbUR~`v-ojO8EJV ziLs66r{iv}NP~I2IixrIY|w`Fh{y5_N2{mDob!pH;jD{DZU8S) zqxNDKeOP;sE~p+(f)3M?ik)PMOMEeJ+`dDCJ>q>hQXa(~0^aMxRZJQ1gka*m_;7^c zC$3qe)YX8#6NWTnsYd)1TDo(CkIC;BHsM{dYF#+05p!||w!YTtX-2?}k4djC}J*L`&i=zp_-A)CDiMvBzhSHbZH^` z)5`ZWkP?-*XPwwwLtOF@*6GZua_Mz<4S2ojZ>v;-ANK`2^1>r7z+2l73`CP%>W9pn-RoTR$~d$};i5@>=gK$ZO*bcVUkVGm zdsvrx!iVL08qO`4PsdRpA;8_Toga(Jdgcz__2dus5E@J7DP(zX2u0xWqTaK@=x-Dd zrI%+qeiIWHTQ#-2Ef|S40ot=^x*CNdK%A$n>?=)&%q>XsW~6U?)`~*9M3~5v_-5A6gcR7 zl)-a8ukx1V1mBp9VuO_MdNU#qqpR+A897lPZ9S5i7*7IHHx#BjHo9WwO-BFP?to&( zV-tH+>q^Tz&0i~p=0Nv7kA|UHbkv06os7ivsT8-#)b*xTzz6G=SFc}pakvouof9^5+V}tW5cIFT~yCr9YvP$*$)-NdA6fsPa!x-1qx*0b|%m}-*Q(D9lnCo zQiI2rCt(-$w>I*2ThmnOiBLSoQZXz^bl$BRmEsBLJadeCWoPO;H=N8)HxL!VkZeme zA&CUK#>%u1fd*D;TWua-Y`bAac?FNku?<~1Z=G^zGMIcORI zx$Yj+U6GMIF9>Z2EV4N48Q;@?Y2A! zlWGqkCM%swL`s1{ej#ENpF6s;0)(!5g&(#*nc$M6D`;OLQ|YZx<$KOrdWOVW>fl>0 ziB^+bRKB3;zrSH_Svx^oHftq|v5A+%%)$2T(hbO3rc=4g#K`yZQORY43CfO#*ZAR> zXx{D|kE^OxXmJm;_--e%wW$Btz$~_@Z~sc*X|OZ=8uI@f|2hSG5u`Cs5E2v?T%|;n zZpJGNnCB`K#(bQ?sCR|Yt0m%{Yd2*RDU{EuDqd$?KXc=cb3g0My5rLeSBtERe`-+G zQ_FNINpVXbOlN`_ibHX2Qo)aXDvB5!$wi|QSRrhl#PGYt=fUu7s(Oui&~t>$3Jg?4-ckCN#D9V!@z!0k1I**) zwY3+`Nf00gj9Kk#j1hEtNwbGsNxT`&36Psc@(P+lo5;nmw(OgWhJ2u^jhob6AjoP; zx~|f8?Ys}1JTyIEX}|tZ>owoVoJ33z@pXw*SzN>1MrOB1Pv+9@&#y%R9Nb|Kb~D;m`f zdeIerW2zUmA2nD6T9Xl=?s(}(pKpGx{~Lp%y#z$4H4x1{$9zg70jI?4We#pe9YMWHcoS{4Ze=}gGV~=@rGBOlA+QX%SQ}3zF?&{c z4pLm}XC!2yh}0BHw zEtF>X-DN4fYiE@Ly@GV9){xRBrn64Aii;t;HD<SAMco6c-aF)_(|OJjMy zTwE+wL7_GlL~OB+=^8I5J+}3pl3QNQB;k*xQmoIDyqIy}ZUm=IJrnF4cSEe5lK_-; z&iULxCE80(^L>OW!bM+7;VX`mT@#af#fG)nWOW0Hyw#EPH&nC?iJaHDUO~h|KYlm& z2?-#P#tx@^&2qgTR%+50A7dDZlcCQ-M)MsL}29YtT~hWsBXUkFNJ zqdP1@o0%OSIqsBH$ZaS%XDq*pS>xgKa5$Lm|jC-b1I({lEwc&G%Cz1F0uC4`x<3{N)zq~pfI??gEyOdW1GgY9 z@iAE!vf5ShHj$aRN_EKh8ie+SE;2e~jIsS(lZ1b_0+BtykV4&{bkEs%h0HEJ_{o`g zL>_}Fc;*1ftmjeS9=WphzRT5hf4x@AT29n~FM54nG)W_}XSJa}<;#mltc(a$U-5Ud zjW2-Z=ET^(axh=|%z1pTxJ90%=S?tnDz-uU;z37+br;aF!_wn0E4n2(lTO1J5Wfv= zdYb|9kd}f1(|O*B)7<>)@y3TT-Sf{0bxuEIxC}bgA$&&U$KxD8IZ=>iH5Uv+d*kESG-ekH#1nOAb}C@t5Q} z^VWrN@M5-^_;F2r^b}pm@}HmDx^i7cpeRECc9w!rKjz+3rs^R&FJFD-3s?%+3N)e2w=&!Zdh?@V!rom z;@WovVuWZe28PHo8wV3yu3PtDpjOn;@u@7nL&~1S9oUKW&2dzDnko2kCh(*V#q{|! zhR{L1ShXK?q(bonO^mT|l+Y+BW>I-vh`*^^4-e4&^@NwHAN8j`?a9=g9;C!p+wnsX zS3BbZ_dh{ie+H4AosEi(9?+P-7(8t3)o?h`@KmjYOX^h?_bOQs+h*F6|1d!U>i|Oj%!(UXw|Zg` z<4lFs@1=tX@#X7Rp}x_anHmGyPj@x2_qQmW@zFp8Wa-zf+^gVMPY%&^YG<#sy-#1y zKYmxT>{}#16c;VX#8<>P=wFC(Zn$U@;vDch#v=1?XQJhPm4Uel?#RCJCM7=nYClua zIu#Kio67n2HRN{O=1?L#^;AIiM?Ejc5Mh6XK*JJ9?$qSpRM(m!y50(N8c(T`^r1lS z-~yx0JcW1;>af5m8pI3jGyx2w<;o6iS;yRAQ;{0AW<1mC{%JeIo=$pws3Ab`FRR37PXc1)D?IT z#GGXh{rMyXNIesChh6SOP1}5IdLWtv_$TpYekOD)gZm|`;Qdj+i;{SH78*2(@aP{{ z<5Jz4o$IBRz()DKOOH9}n+*c6xw)QFuYB5KNJ1lwz6I49#212C73UNB3-`VqsUgB4 zc9FUE2vQnal-ilfQ%WV}d<8vK-Fi~e; z*!^_S^qfSRiK#|zrArFl`E0)Bz?0}DD*DL#Ia=_m^s(%;lIuA2%5fbb7bP3K;)T_= z14;P2L1p1r#mzx!=P%{TD_N&TT~o{QC$^TF^j$62{N^Y!iLj%~9Sny1kPwLF{dOoW!|LUdT*acyb8!V5hw&ZT{Y84< zv)+_#@>!!o;W{1&)Ex*{#Uj50$P50Kumnu7>P2^(9_pr4##SrW zf4FatAt~Mg-46gz2V6wS1O??5*F?&u0a8p3|HtqfSJ(O`b*j_{>L=7IXLu@H%Z5HR zxf?OxSO89mdv>P{q#@Kq0exZCPyl00 zR&@0Z8H1edUjTmQqx*uaw&yW(K&R942!-n?K8?beGQI7svQ7}%kAY7WY$+iJAY%tadO3x(dGYD| zxykSo8kLpm;-Eb-w}>@{eJW}*Kzuc}?%>2)BwQXw*H)K`0VTT2z;1z=g=;=fD`$;C z+aX0pxp$(rED7Vq3%{)I0)arUvs0HsBOpLAA4PceYE+0V?)@659IE|Tza4X9QI+#FB@TAtVxalf#w#3~S~_dup+;9^p>7qSh}7|X&&%K}M29EeMa0I#^_|N`JC;t= zzGC2h^>{%L1jO}zlEtufVTF?igVHu|6Xy=T)oD{6f1KNu*DVqw^2}`74!Ge_>OB?$ z#0Fr0E+?~twZFs{nSKAr<6!dyhq(TzPkJez)D;EA3*YpI^FK?|mC*^;F9Z>4@H4=L zxAkke>DiSD&%}B0d^#hH7zPH|IzzLq%{w#(gy^miU9vbwXzY(PiMQsZ*Y(A+4qP1@ zmBoaSyHSr$Z#&`^{VVvvh#oWSNQpsR#P3SF#T8#KQt|kN@^b2K)p*;kFAln_jxY>R z4Rw&Y@*aIKg1eahTv6AAZG)crlQRAcBgNwDPscB94pM>mc`_|^`k64@LvOCRWCNS@9YrZ2HFi&{$yTdnQ5lQDI(>r|-NXcm2B z$WZW^w!Hb4j%jc4WAFl+3I^t$)JfkLAy=D>lp)PIQ3rA%b%9kw*$qZ zQgA6EJbENWtQ1{Sy3GtPf{6WfFup-#J^@3%PU3&fiei7wxLz4)E5{l0((Z3zXdcS; z*y9KnVBdLytIBT^c}qXODm)={kTgO?OTJ&Q0B@HS=QJ^c5JJw^b5Ld8+jMT7sVnSP zPAV2JSxq50O6TcpE?jYfbPZFA*2DiGVu|vn)kCigYtK2o-(0HeebW#~J$8TsWRzkI zNKDd}$}{WXyjBXua0m!U*tW)kh9v`^IB(eiNg2`eWsU70rDW_dk6BmoXim3Yw|DFJ zJsa<~+ry#G5t5EHD`4;D)b^$|_B`fqNn=Ne=08D<5YOq~4-N4UJMF+(1lhWW2ealX zD%KR@CI=B;uNvgOrK!cLtdfR{*O$2};X{NP-U=>O{;;Oyp%Eki3&8(!>4S{XKLHCC z?G(b)?^$lZ-FVhrrTo0dKhMm#fS{_@t>=WmmJ0#F(7Z;I%D;hscQuahanXviwNQj| z@cG8)3D}3+wHqs9ut2?83)eb}`$!cOpum~IxI3@*>Vak|Yc~c6R%MQ0K3ILiAVB|S z_zmLk@E6w&0Id=hedzaXOkp7T6zLmBX-|8gAQTXE_(m9Dsm}CFhoONiH6!e!Iod_3zOym5fO9oKeFUIAd@8UjZOZET^jx0(@eUHD0kHS3GL0 zIT$-)WX4YAW8Q;@IvHzhwRvSz_;5c{0CCD@|8L>$#0+?jNlklu_#xgy(&Ax_U;wriYEUb&tMfEAOhoiJAHzOKMO?ThEHiKRD4>b%SU{2Tln?9a*%j?`!69KgJLF zWZkYJCV-ME`$;!|Q5hjlmhQRn8shsYBVQoEZ$bz;I3Q|!c=1e?=!7R{c)>zob2^a% zIu`y#FB2XPt0DV(A_zc_`Glqcoq_1%fN#?Eb}%KKX_{s1`&cdw52gQ6JDeNcrjJQ} zr_Kbo0?r9qP;h81ij%-fJvwFCfNOc>>H>N5m>#0qdM)U2yBIywL?N*_Sg?ST79f;| zR)#f2G<9WYZo#moH6Zqza(`0M0YAS_e>3n?ig!}K82EwZPC=5WazaU67H=zCvXQ)Hu zk9Q}_Gob;NE-1{qJKm>X>v}U92;C{pjGQe=5^dLQE02f1T3C4aw%SUQHfv}8W6%G4 zyd2`u_O#w0kudZl#y#UFe_cbPxdg>)pK&^G+l>iI@L>LJ zYI>a%@08S5!-N|tPoqRdZ*e`7;nqyp$M3c(@0H$9$B1foQ}73sn(*OIBT)oH5n-~Y zfz3j4+qonlv=!7fZ_*_{e3L?`(C_}PpL%TajL>VB!BR6Ja>@Iw%=`H^Kx59Wd12Sz z>$r|fjegSXz5RcSdPOJV=-B}r2-8USHc^Q%DZ!|{{TUR5?lMmDF9g`NX@u<;Yqd%O z{d*SQ`HnnMec6hA#vpbUq|&b9ClUbtKtM+YXrkw&AQzs0(b}y^jMojZ;pt2N-`tg# z?=O~67=3awyIW5Jz^M=~NvKg7sLOjISu2Br)O9OpEAkZleaTp3s((Bh8)exUe@bTk zV?c5T`OCQE*{tDL`=Oy7TI$#w2c3UWVtM()OMfWwi;nJu*%JmYk~c&FgA_x5j9X4% ze%YPCktErj#sFZd2u-@o_ztW#rKh-qCGM(`^@!f0l1R6xilVkuMNmAO<5e)29 z0Gg30M3yjD2C|<&5j2CF+aGCiw-9H3J>ah)9J{3ZWa%Tx^kG0bq=qLZ$M%v08VSNj z_^B`2bxe$2kj!ZURt7@9J5yjc7pqc<2IHU!Ea1UwL0HT*DWBNn-jnG!h`4@#@uq?xg>ZFd z<_eeHa}*|rEm$gac++Yg2qDuisPK7cI$q~+PuyRbOh%BLz^$Yg2p-s?UBhXmzt#~H-ukZMEj9dsg=o%24`2cB ztLNjRduFVN^sTa%*aGbKMC$>;w;JYaVztY9WH{%eIP+Vhu?m`_vfc#sHv%>(*B@Kr z;DaaO&sd-Lr|=m5S|uik^liWQB3f#0XHK>rufq$+F9Yyp@kG@WNm%fElW z@{Ny%2G>_uxXxn7^U89A(`Cz-QkM-E(5^S!4#C)M^p2|4pP(qIs;-ps5NXc0$cN$7M1Gp~Yzfhp_DZ+bmBtK=Ey)yRxKS{uPgVQGT zr$UvKl{442-doO9V7&GE5b$shv)b1KBx1{pa~AXPc;TOW8`uR2Ld?*(l>92ymCSE2z7u8u1!MMOrxlQn`(>nZNj_GgyDw=MFn z{s#JslKC0|Pe@?6SNCCmV#Ar4Arl}v7C(v{8Uk_ngv`uBJ($xB|J|s%KtpB4{?ER* zzeG~$%v&AsBPh?>x0yV#Y}u)VI^3kxwK8HFO5#E{d*g1<4bo|t@79^eMStpHJ$dg}>#J#E}ulZ7yyr`*N zy7p6N*COV7NY1bgCWp_SnzAweN{$_XK!yOoiS6v%>u3Sao&uOe(Q#4eNq|A5#L{BC zJ@M880TZGfSLJs{$x9xg<>Y&b`|4GW`^g#F;oWZVW>QK3OUpGf5IQj5$@a>YyB*l+ zy5Dys-poTbaqhVg^C<_lYLq!_0iF0(kw&PwYQI8wfsJ6kBo^{(^;z*7sIMP7ukP~& zRc5aNCNZ;7J%*u?q=UQYx8O4cy`y-p394>uq9}Evx2LzagED45g2=9c*lp2`v9xtd zwpick7IJ*UpzmAU4oe3RtN9bz*JCOO-=X*P-kn77Q&1e+Z=q7Z#^&BQW6Iq|#jAo1 z9dAc9G^xi0u{xN-0y&^qw-X{D8v8v5WPq8K=t8l!w$?p3_<=<@1PE~lCTwsk-oEY5 zJNu~Gtu&K5iKgAJNRKTuG=}$iCi{)LddA7MU+i7EV~#JGG3%@@)4xiOZ$vjAeadhF zg|6}wM8sVyUIX>)M;Fc+RQJ?6;-`a91lDEHz9TC%LAiieSyS@jrumP)zp7HcKM|Y= zwBHTEc!4p7+HcKA^jfhr%x}I_dY}8Icq)@kXGANL+On>>vicd>m`imIk$c@Oi%r7 z+m`u(&)9{oysq01Y=#4T?5d6`uZ_}5>3hYd;zG%^;*1=P!t%@m*3TQoAre-1Oact- zn7*h}Zz~vAlnj-`iYAR+Cur-8e=y~9P4+b21Y1)8Fe~%6(a`hmTgfKNG@dum$4Pm6RT9!TJ& zniisYQ&EmQiHu2P$85u-)2lAV@ap=`U`ipY5JRoU>$r+}?wu~_-mrXWGgaaA8k2vI z%-!@(J-m;Vh$<8cuQ*Jy^m)|M%1dxvue8xjNm;M`GLOFeZdCCn#6EhaI35J>=q$1e z@*^7L7bfKK@h3Rs*CPNC!PWW&kT%DyYKjyf_yhmy!Jd%ZsJ3*zinuzNkC9VlVx9v# zcmOX^`kd)thCUtjX=fe&hm-4LV<9_Dvb~Wm65zyM$T3O|W;9?4Cpe;VdCJLp=axt| z4XFDL&tjC7Ja|Z1fH)y=pna&N?0H&@Y-PAtU37baZ*L-<L@D~g3nSn67x))EtmRpTt6df5vS5f#*FZ1gN1(dJ|eq@4M$kM)i z>}8SW!RzGaaR{03n-D5B2%#5vb=6lN0NB94r?g^z{wvyf>n-X{9No~O$&Mc~C9(^< zlb$lNs$$}7FTKYW?`q7T8Pwh)4D}?Z5So7?DIDiF|Ac~{6c)vJ=cbMeGTjV(XIuE5 zh2~EyA@X`8LJO$ZDF_`2wp<%C4x=L@Qm_pUd}U#|D{Rh+UWw^WN6`!j4Bfm|U1rRTZ7* zm^*zny)}?z1~u3%8sCan^;;hL0Eny9r95f$efNY;Hy5xVwm}wLXAh2Vwx~6hcG)(5 zbfvHVsCwuZJ<#`Ym>h#!<)NjZAj{QwetBF?nO{rqIGIbAP&ku`%j~c_MSyJvz(6dy>bH(b^#cS))57=e+x4wfiRPi znVFP``!*uRyag?}AC|MPhyNdN(RhD@i^hCWJrQmHlCizC5F{9nMQ-0&r4ZFIo&8~$ zi4A!pQtoTSV041pR`mdGUpp9OGl|%L6qa^5#gV@5`uN41%Z-EJ$rOIm**4Yf!HV2b zZ^{lUI~5e&7^IqPhG+ytxN5@9bGK^mmSQPj-_ebX91C2TKjqEUU2(B{6fR;gWN0z2 z$Dh>)j4KQP%-R>GFft5F-+c3g$F0@du@RY=6(4Qkfp`7Q0~3&q__h)w6k&ij*rg!i ziw1g3p`gtHKkQ2l2BJvE`aMcCq2Lxvg2ana-P5g6JWI^d9FeeijfG+485B%_PHHAv zrxa7pD%1`>J(~n0!y}E73-w(wG zM$UB%aGj^ZW>xYX7M z!3Q{ysIoB+pbb@Z>2d_QQ7L8LdPN>hOy7RWqYn)V3c**>R$m^GrkeZyM=V;9U2htq z&1PcAX10s;H4jd~`##V9!3{?$YInb>#d!RU;OQ#G<{8A$4wT_gL2B!c3yR2@75*vk z1{aD*^7YT7F%+MjS(BB3Ol9uW?4p77w%qHo3s*K`_lCjk$J-K~i7jDvYUIK`o z+^```s$KZ0nC}Yrcpr+Wpy~X|KDsb}5r{SLMER!T(HLthd}MS+Sar3&NKm&kC#~dK z4VYc~zY;TRJ;_0%!?q!U5&y%;{}oJ^Cf4|LssE9?OsjGLdO$&;iCki@-*H|f8c(b~ z$20C3=K)I0lm|m%Pjyc@-WaruO2%S!Lqb%S z&PctE%=9VVF!P-c1@!xzd=G|4oDeNhHyT_}egQNLN5xU?X>{pn9HlipP0~x9)VNKJ zXe8C%9m&gP-sb^*K_>Apkql)M5g^h)CXU?4z?gD6g>PA`!-&xpBt!^tu(@%9(bum< zoUOJM*gjavte8^Kh&Ygcbxf0YcnJUP^zFA`9{Dy#w-!eGbH;;ES|fFN`ul>Ccpij2 z%2{L&(!X`-eDMXH&>sqHAN;%pNti0DLj|_!TS~KcwCao}KGhTf2>;OvyF2Z^+fxZp zTU`Yf+uHWd(Ye5Ag{4#c?fT#3KZ_G1e(lN%n(JRgvMsInchoU4B1S}L-{%Fm8Kfgy zr;?zFTopBaFKM6-S?VzFBCj`xcC}&YJYji=hVr0g#;ob6CrGMu>(h)&e&KF^#eUoD z_N6Ie6zPlnw|=lRrJFBxZhvx&RN#I9k!OnAiu;&qGV2C7 zeYO7$Ab&T?X4S>7IyK8(wP$K|z%8-x_3sN^W!aMP=MK_B9g{B3LSOa_zBX@m$5H^m zmLMYuX#l!I1{Bm&1RUAJ!x3XsSFR-u{xOA`DwyC_&`Cr$8Gyh2p zUM1*YAWj2^qroWjWFa1l>_+7`JVX5yZNtW?!XFW74Ryker}~ekI>Nbl zoM0a=TILo|8v(d+DS5E0?JB`1SbjQmt-pN>6F0=GGqMXN>F#L%_|@g%;NqHIiZNEU zL+^*lOu0c`;yFk7bcF}PV2_SOyU`Vnk2nI@XAk*D$4*$RPdHE?`WQOYlE6nN>rucg zwdYk`=Qr6M-QT**{S0c=XlUW#jvh5PM6@b=aoI{_AZDarAxGwW>@ALXu5ESrD(tch zui6n1(D^gD@C(2De~`Q2#hOss9r_laP@&bGq!k5hi*=YxA^d)AQkReb1Xo^oo=UHS z`ey=-2cl6c@**8&`~}|~@42fsmUg_#0B3DMwj;q}uVX%7HR0bLJ2Bw`)2~yy?CTGu zJB(RsScxvwb|wXVI7;ld!6RDTkbbo3Iss&FX2OfopMS-A@Q!-@fnX=i8&%s;GtmqRa*=5o5 zs#ea6>3)WENI;n_-OM0DQqFa`mE$3n2Wf3U$$Vvj%|wCMgn?5KKh_cB?b`@Z)fdnd zEA1Erc>YT(uwwJO<$j1TPihVatX0*sL$6s8cQNQnxGCP)Gqs;sJJ#iq!hEL{R?QYi zkcrOSkqixYxTy>493(MQIK9tX*II9e1-Tq$2R2U-&c(OfPnujc2@z!zQ6qB z*0Xx=p;ml9NH^Q?I3AKo-v=l1o}Pa9<9h02nizrMrH9p00(RnyG$GW+p6DNWb9?!m zbm#;+2Kle=BP0CAl_RoYa_E@pz77W{6Ei&po-k9K*6=^0ymVPuyl&;rx}3Ohlp#0D ztQ>e%ETxAP3O<;NNP>vb_N>F1136X`u(tVPr(;77mGMDs zAgPvlRvkGz#B)NDT#^Mwd(3$6WOBB@=WYJom8zWRX4SZQ3ufRG_0+gKN+&k$IO@5b zf#%%zp6EJUY2+6de&kvC_#haB1ojlSugs>A3C>y9ZMvO%VR1%iai(oi14KlG7A`X( zi%==8JEz(fE)XcaH9*#aFyTJ7!bp)W`6Y>E)r3)hB?>%!#S*d$HYX~K@Zu%f8_g3m z2HANxyIjrZVV15Wb}GrM@?9<)wqS>@ehJ4#%9Eq6a37GLy_CYUL5RDGvO?kmCWDaH zi+$H~5uDm29xRoL!UpV%y?Q9Pv+8r|Rwz(*K;-1#AhV{w|4Z<@hH^kVgY) ziXLB92z|`Z`rIFkb=|KLrW#f*JKpxEHwA8*<$Y#|L2WB!28i3%O4bFECDY;B5j9H} zxjVQ{V3&xRH(Dq6>)K-z+_#)MN1GfxCY71VRfe^>f@tS8p~Gcz6bl9|$OaFMxmOa~ z<(K)-1l`9?HVKm>eL`K0?ou9}ly0&vsFCP=6Nq){JZl#yOAnn~)c03t(F|p5HyK_; z4@kL$pA#~BT1(v1Q5m>axANXAb22!iAs1P}=bmC>t@z#IM}tcs=HKTnNAY5^WrPp+ zyJ7#sH~hHHtCV()bYL77*{P2ZtZdms5BrZcUeaBRB(lQ=p1y{>d=A#9hD5uHmKSv(qMM6;0bLjMAt6ScteV1L{+gM|9WZ%eoHNxWX zJ=o{bLjfr~ppeGea_@!`(s~WaO~xNYTiS%z&}Jc;BVi~*tlzw*bv1t(4DSMJSA`H( z`z>Ht>U+v!(xLmSzWnrO1}8C>qWzo!g{C;%Y0HU%Kb5exuLafVOT#ort+r9*yRtwU_8HvAP$;7m|?ZTV6yK%fBYtA7!3qyE#hx^h=i;PK&Of-1E z%nH41e|@YUHar%bLq$Y(*~4w<8UBU6GKr8`nV=^SikjgL!&NF7whn!KFgZl%P zR1}=Hme8bvgH{^ey3bXMNH0)v?)UzSqx~P$?76bP)Byf1*;Qe~dxM_EDPI+i`e_{h z$~-_W9qZ~8EcebWA9Ap{2^sW`jT6O$MFSHRE74)%@|DXGC|4N?oHr z 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

`-yBI*~w57xWPcwlP-cb`!W`uv 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 z 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 literal 0 HcmV?d00001 diff --git a/imdb/assets/grafana-datasources.png b/imdb/assets/grafana-datasources.png new file mode 100644 index 0000000000000000000000000000000000000000..485e93702c4d2d50481bb3294f327c3fed56a49e GIT binary patch literal 65443 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%0D+WPtr-+a`d#>GX7e_UBr;+LyTdpm-3 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


Pd zBi5p;{6!00;Z2aHRG;4f0`Ru9piR5wwpjEzuE_mstdZ ztNkK!09PAtba@&GFjk>%u8pwR64y1ms-u8(y%Y1JJR=}q9(XsT_z}imAT->@4YC|| z3r{_Iz$)c)x;!JQPuAH*$5h-N*+8rgJP6R`(UzO)R6s9DCMs}G|nHEdvOy$|`o8kff@W>+knssSCSny@< z-o3T6dG%W$hVV1YrR8$k`qm!TG*>{*P#eHHr=_<0kYhG;(ohg82cwsFaAkPQ4TP%{ z))eM8(MUorMW}^`W@noq{-i56sfcg@H8J}KiLIYqzW9E9>3Zd(H<1w!y0J%&=JE!p zmkY{q1eGVY`|-=8DUA+Z$yMj*QcRvM2dNjsOcfg(@o4yt*^EZXZDw|I2l`yc*}D>P z<3;7phsjIJ*>N^wik;N*uTWoHLqN!+il&JarhWOm>>waKqA=gbV~`H52H(;;dpl zehON4DI>B<+xyVn0;?p|lYjKfm?60J5vT%tOO47Fo+sJaIxt^pfc;0lz^oUsLu~Ba zfULTgzdt=FPgkd@G$Ukw446&H2=vL0?-nqUE*vLh5YljEn<*JfIFuC_5z_E}YztKi z!&*2IFY@u-Goy|=uIN<1m>rKu1EINgir6uAfREohF8k5cHnR53LT9w~>t_Pa2YU+R zX=tv*wP_y2GW&@=H#;ZXe38Kb9e8QvU+q@_A+^#>AaUT$tdl40pS7UV8OdaHlUq!D zfxF2&6Sd;sVZaIS@+-LCX<@eVcIFFW{HihJmMvxy3ZIj46J}gGhRK)kVP>gT9vK&c z@*t$Cc0PDGXCnihos&a%jsv4rp7Cu6-f%)^DvOmPv02!;FBh3kLEz^F#8D?_(+Gh< zg6HoKqZKvshM?b^ou9A0M*#a_Gjra@QaqU3luj`scNcQyKx_HtI63i9Fi}EYD{9Eyt$#L5cHDK(V53ly;^?V$sV=5W_rul=;nv}y3ry|C0$8l@z;B=^ za}yD5NQR*3VOuMhf|PD8!7!3P!|&yH=3<`#VMi2nqjmO77z3LT#lY+-I2UI7_vOtP zAU$7OOFYJxQ2#C|3377nUtRc1!e_7*HKSQ!Ot0;R1fT&|CV>*`w6L^1`tqvw!kG3q z&Q9QOoShtE3oYL<;*!aWJbKhLu^{Vx=L9$W?xF#6z&Q;&imCV48}1+)X)XG>>QF}) zxl~Fq1z}gfHVqb5U5{7`cU;)rs!YJx& zssj~=m$#70T%oDD!z++~y%f@j%}Da?vUUIdYu#g8u#H^gIx<4#9lpVS-hFZ4kcJl^ zckb2fT46tpvZN^XNF-E27S zx>@sjSq-7MXq2cuPlw?ltq}w12Jt4UHmFx`%E;8ozXPQwgf@bn-}leU&N6I)nOQDa zgdq;to@sLAkt8~g0JiIyiwyZ|cl=1V(`gAzakRsb1{AH^^F2KV_yqVXiCf$?F|NB} zP@?r_n-Z9z>|@@rs2=<}GwK@=!S91rZmw>Z#m>=K!@M4R$~ji&O>ZAjfiGcp^@r%H zD$454%fez6sC2G7IjJQi<(wSGf{!c|28&Cs6{bu)CW$A8yQljngz#LT)49sJh+?qL zIFT5(Oi)@c;6b>b+#+qQCd-Gz^&7e-^Gq9dy(fb3{(~{``NyM^bU?w_X}i>2N_(+v z?hv12wYjymJiJVRAm8qO*jMn#C!Kd{TpSVqa4r)96dR)*!FP+hN2?a)fVI*+!<#BB znC?*3#e`ysOHRJU&nF>Ea-Y)-0FHIQ(U=rn_fEpi7+#ZQStC>>lQkSRCITzSN6D;4 zh&_U^Q+ctu1}=y?&+i*?EoMDL7$t>q-f?Uq`;^nS&kh>y+k6=>?!w7Y2aUppGO!L0 z&>-DitNXi0ZmTm@Va%;WNYL!dzz;G;FlICU``Un;QdJcOj#nZ035U3^U|PzgpwA)3 z44rrm0x&QagK2+leKS47TF@XH9)#jJA5HqeL&`9499m=tAvX2T+FiB8CHlKB_6TB; zooC*D1@k@FHRHB4zvHZf>bHE3h~$rF$6U~U=Z{ZHcXL&z8MTlKLbsHYN=P){#)N+f zq8wUg^LW>Q5}?g=Ks27($hHFI>f-nWKCmRXDNABA-y2J99vmDc3Y#D(t8|?O-6vcr zpCH!VDXVpD|GKa91A5p@=%HR>Ak;NLv%_QM6i|N;T0b5E!n3-*-WzHnX7x3`si`T3 zb?GpHC;$nelt5k;#-{J9zaw26Xm(_mIe3SSn0v6b;7@^CmAY>8^Tx7`GsE8=OwvVp z{V)al`N(6bdOx*azAF?277*wU=vrk|dH<3u#tsxa0+0m$k+Fu$W8E&678a>XMc+pj zg=F7I;q_t5#tg+UtGzqYq?djc&=O9SMHW$tc%bCIDHeUDk1Z%VT1I~5cKmizKtzP3 zU6mK|w_p%~zrBPu{KCRl@PkT|cl+gxOMM4<8Q9M&X#uJC!AHRAh=@whDPSvzP)`>r1#~D{J@{cob1V844k}*n$sCkQ8x$#oFb!58f5v|j{WG5;T~bFA`7@yc%*oCMv0U2!anCtd zKb)1b`&vPJwKHZ5sK6joRAU*P$imV9ASY754q)HaBBm z=e;>VeY%;IhR52Ll6&dg*u7Ig72wo=b|K`_)6*Ykse9z=KjCCI+7Nfu3Yg*{`8TvW@h`GZ0#>S7u?p)kU#^T?P z=1tO`o}LHlpTnX2T+RI3&oB)%T6z}pn--7Yf2|*ryvkcrJ6!wYJxRdv{aDxQ#uS1| zv8A}sLigkUrzRsmv&`6K9vl{SeXuL7u(U<|47=W!EG@hh_etBjtLq)zdDCs_v=vVDXhYm zpyDm2v!Ch^Uj#}f*ruZrUIS#yTF94n60UHZ$j==|t^-H~+rDV0<-|h{8x^L6lyi tqgD!@E=*ma{BNz}jRA@O$6)EgzAvVGXmAk!B_8~DTU6#|<_)c9{|oV?wtD~o literal 0 HcmV?d00001 diff --git a/imdb/assets/k6-dashboard.png b/imdb/assets/k6-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..fb315e62b2e7ff94212e4d06ef66b330462bfea9 GIT binary patch literal 89087 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 =nxci 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%0A`we0;m`wdi&6t7BpP19m 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

-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 z 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≧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 literal 0 HcmV?d00001 diff --git a/imdb/assets/prometheus-datasource-grafana-queries.png b/imdb/assets/prometheus-datasource-grafana-queries.png new file mode 100644 index 0000000000000000000000000000000000000000..0cbb600b6a577bea8d177a6a7c987efbf4b70104 GIT binary patch literal 241994 zcmcG#WmsIxwk`}IxQE~#9D-}(?h@Q3xVviz?k-to?eFN#vANCZewP*A8c(&8#mP;jMCP_WntaFCL)FARN< zFK8DPDN(4ZF`@&=kM|ZL3L;QYwQzSUtqSJkPW=P)hE|I7=})e_b9~6y+kJd82S-+Y-ObfT-+hlp zAP>e6{g02y;6Fp}|378q1exzk|7SIF@uVcOl>hN0d9bDPhk_6PDGVY3Y*+7Z> z$A8N6SiQU+);BjJJ3C>lQ)GdR!5DcsD3TNp4_>C`=JAP%1tU0{byOns|8!&0^!T`e z!+}KF-$0OV5O-j3u-_>Dl#V>O1ieuwL~$=T&4c}z_!toI`Z**7c4#!XytuqnHb-Le%yHu|h^RzIVGCPyy-wSnBcwdUs+_(j&L@4>Nc<$}PXV&!3L|VSPy+zyJHf2Z( zfwWzdm1TQ;LYzDZ>0;F**^DJAA)HT2z(`;Y7yqh?m=ZVVDgm~>{>%tUU14MXkg?Fe zyMi!T^M@WAF6eU{Q!qx%s1Zw^hD>gA%d{`dn|ClF%WZ3!G@k+fMP>)JVig;s#*lKnJT}n#o!-vg?SV0+I-z;ZU z$UGsf_=r1h?~6dxQz_=T2lp_-#l@v3v<}zi){cgqS_@AhdHdWPRk_5is;6h0poxp> zHl|so16xY1kR>0rD>Agr3-Az3RWH}1PdeHT$ZiyGQ78J?^r~&%y|ZB6%`DdIm){%j!~0O5?DcOQl*rnBS0m;7~&OSvi(eiBhUnCduVD%>Wite(D3c>i{N)p-``KlisOS9zWRm}9NLuc*Y5ZsiK*tc z_-t@wD9ou%zoXOGhN98yYqZZcSJs

e8V7X_?Rwo(Mxm?E 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 N`=R~=topOi{{x(51rz`P literal 0 HcmV?d00001 diff --git a/imdb/assets/redis-cache-hit-dashboard.png b/imdb/assets/redis-cache-hit-dashboard.png new file mode 100644 index 0000000000000000000000000000000000000000..148a8e3a2ec201c67acb000f04d44a32028ba6df GIT binary patch literal 125661 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�dBQVOPG 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 YxcIRqY1;NY5&V;rR*=fL@!-Y(0)V;^v;Y7A literal 0 HcmV?d00001 diff --git a/imdb/assets/swagger-ui.png b/imdb/assets/swagger-ui.png new file mode 100644 index 0000000000000000000000000000000000000000..cf06c1488742cea664aeb6e1f08155af1598de8c GIT binary patch literal 132558 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%0D-+P7eTOwX!=gMrB_A!D(kM@|u2X<1vMO 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

FzdfXSWA-$J8py*=OH!A!(8mSMh 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 literal 0 HcmV?d00001 diff --git a/imdb/assets/tempo-datasource-grafana-queries.png b/imdb/assets/tempo-datasource-grafana-queries.png new file mode 100644 index 0000000000000000000000000000000000000000..484e5feb97e75aa5a82fc291c579e498097a0d19 GIT binary patch literal 248645 zcmdqJbySGMRVJp1t=x&oe}PQIf{Sc!z<2fPgJ4Bk>gh0i_uM0dW%z1>Ry^ z=NAJ1^TPG3v=~C=1nCj{36kY!#m@)`HL;jbV`TVqbSD{YR|Eu{-oMw2LC0b<1cc`T zS&7eTUIwRYo?dF|kKLe)G3vDIby=FE&{tyUWa4HQ}$AJ&B7F(@o`PF{?*qa)`a4b^3$!_y(h_1t%opJ5}QhZf!$ z8s)$JIvl8Mv!Hx@vy~Iw3H?7CzmrS8)cem)Ugb)w3={oZV=kkY zkI&BOX>dganN5;h8guBYT;wQPd;)^KHv|On2?+&bZ*w(^MNv|an*TKziK5z?>DRAb zNl1Dl^Dh&AWM=NMN|aU;Lz{kU(}01BDlOFESJP0p2W;VDV00fD4n3ScMs3cI6#Lfz zr%PVG3?3RCro2((=a^1xgl{h##i$7L%&(7+m(MVKHTfWqr&|om2ub z>gHnYcXpDg9i=^f|27i;5_JY*S9vr_fuLzCv5I)h_1wE-?iZB^f&{!sTF#!;1oGnL z5pG{N`&D~=L+Ya&ms&Z8e&FsjK!yG!PomgrzcU$ccq&g!K%Z`}##10CFH|7-SNHHo z5~xS;?)Jp%h2B|=Q;3(t2hl%btYZ+-U|g@;tH@LmOol9V`{o^cy28>TN$luaD=bk= z>myrC=!@SYYX6!h_#@#=jWU||@4tukh|3ZQB?bn*uh*$?;h09|ikYZXrpNcq%|NWE zp5T3-8QSZ`)vqQE>mf55+M1d9QMuN1vn-8p|rMkkCbfspwX zM<_cBvfVO3E{*D+zJ=`QXvi@$$(WE~=6KP)*&|LY;KqlJE)Kf9l&D%%)zd4_RD(}Q za2EhUdpT`n*I;~gwMoBGJ8zne(wf87!cY>}?e%zvTLgG^+C~{jNae#Iu_c+vmhUyQ z@fG^rvCzW$JvOo+H}_?dT-ZpHp;P27Y+F(u4GT?!wrOP9)$$%18Jjd*0q*i*rqW|| z_<1}1z+fO(kqdM>8YkT@-``+gXx1uAZ55X;JfE56orvphMgyKSV3Z{#jKN&b*aJ%i zpHNYImpd{?)c0>lb?#pIWhR!m%duqADif&e_XUP%54m4aW*RXJJ3913v zuUilj67G)~1U9AMO2?2>)9fJ~OynTH|7G|d4{sXldkhWd$;*w3`}EvgvAqvE`SvHL zGDbi?sb~x-fF1S;PySCsR?qHs)U=c8tQ66erO#d7>|-6iluCkzyS?^jc!(|aCzaYV z0RbX54Xw6_de+t@exUiHkzEb#DdpbT>4je}6#_99%!svpe!Z6Go$A-=_l(ft*(1Im zRq5bZeVO2OoHt0cU#<{7LpE7`m}3i{5GT5-axDZ#I_Jr@k@jrUZXjyv@`gs5UPZ8K zSqf;}*xZMAULmkd)4uE<(PCOE8KwEppFi65PUv*;u~)Oo8>%`wcT-FsKZd4p9vE>D zdmm)+PM$;;rns-N*vZ!M_- zBcOdO{k^X%Zy3KoYGY^oc4@11X8GnMVtMLO)gO(#TrFH(muSDAHb%;w-n>yaYM^~5 zTdB&D{QQ1)7S}-A?wVT+3+_Tsq~>=rtx4hE{!Ex(Oa=S8-c7?z8|XS{am$9Qzh-Q*3mn z2H>H}4iTr1P!8aM-EuPfMRzYeyyp#kQBmp1?r0kxA4hrrku6jbv&wvSe`C3|;$|yv zp~Cf*XXmYmDz~lo1ISV<1(T23=|D8cxbV(+y?y_40D_a#V6+feu<+q60uK54&y2;- z%zf`lDK?L}O`Vo?d!It)tjZOOxoFo#tc_ef^iM0h5`M78mlGXfE-d`2<@w#fj(3it z8CL9Et5U;0E1^T&ESUPSD!7hWJ;&Xa@HdFnPD} z3tZRx%n%n3(u{96v!Z6cJ`6aKhdlh#mP}U^QHD-p^OgZ za-rONpA*tV{ohfUv=*JsI{TY;eBC05$%RhjOEth(j0!1iq!F z2Kj-9Q4epTyMpwzwPhu}iA@I$24cu`GrW1&Q{#5Tr^tL$Hk8!ph%scx7mURzwM!04 zjt;+&@TC*a7O_)WVWP5wL)3nUR`K|4mz@*vqIC^4bS2Qn=CfyNhHDd#kAd8dB z9o|e(n*4Kbg*Z2~{;b*iT{zNP*pYMcdH`-Dt8zD8)z5p~Y_s?sTszrs_axa{Abz|z z=~Au-y|^xSxkp&w2~)^)NMO+T&F$TAW4Z#I%iIXeWWy%xEhpvhbF5U!@yu^HZCI}UAB&G^N++)DUle`34 zKe7|%_BFlDRkD`m=&rP)xBM?-#{AvTWwTrCv;$rsWCEL$Lo9>x zi@dImG9sGzd-peZTo!19PM&Yy;?nYHJ>n7AN?Vi4re@Y286zT; zo569Wu0To&a&6u@X199b)VnqqKBR&VV&xx>+j+1urFA`H)?^={3C9n|iHl%G=OkpW z^@+eCf4V#(oZOW){uz*nc))l`#1}4DS)xt*N-#&aQtpFRLT`k)^zihx>F%junrL+i z3(Bgv>na9|fyli?G|g~VsH!xsiWT8#Xg|QnBbS7q?$((P-|w}BtNM-gjDM5*Kgw7u zgHK(bYHK;@8QZQ`2Q6om@}{jWK_FEN`poxbXzh8G#&%X6;UdIs+Rv*VHioJ(X@iQG zEL2|--l}- z3V*U&FfKftZef8ZQ$|E5!-6Aisl%6!!XGSRyHGyRzf9m8-ntQwKRh^PbLQlERjhbI zO2VIp{xsM%bR!NtiI1(?Tx;t3Lz-O{gNw8XRT^*_70uatq&(j}dyE(#G`gptptkh#Vk6deP@AqDNih}Fx1w3$Eki*Ast>2{9bxVZC+sLL>toz2Nr1*R%O^vRDQj;hAL zVk5qIe!t>zeou0HAZCN7*3f(<<%(JPa}$p#wJo$?bKb8IKeZ;4*)nMMgm2YR0FxFg zuic3&vdYbTkp!@tcf2noUbxnc5c{UH>jt;I)n0Iww{o+3P;EaZ^4IZb4qv%dPg4Cg z>zLEVsI8~ypQ6>qI{!5nC6saF^F!Dh|0_&7o8;lQ*)0!vol6~IPeo)cd!5omsW<4n zLf4Ls=j#&#hB%x2#*{m~SbiYeSw)Kz&NPKgp)|4WOT5rQcFvVpKPtQye|AcjtyfNM}&lsac5buCp>fo+?8R5u&6;b~|!#T#k1G++b7@?&C&h zZH6`6+-beml~@XBe@d+wrR#cZyRAM5V`svC`=rs`y8i0nu$OH$c^kCXc7L3Av7F-* zzk_<43*WNq{bU}z&B|}zO3!F$K-R2V#h?W39BI0LSB5nO_m&KkmLCpYYI$-jbPhDF zD!YJX7$(>wkaYHHp0qp$|D)in-+aeq#U_;y*Bj3I6!pi7i^FG*4~Kk3+1OZ-q=wtEGxYVe*Y8CY_D@;c~Yx?e70;y=~H`Ot;T)!wg zQMb2h=Bd{Yq|gBFHdW<#pKY`WJX19HO0EOn{&=EuxrqtQ2d{DVud0)(`B_5*nn)@& z7p@{uZ;Fx6RbCuLxBjV7~_*%p|94|KWI)w zQ8P6H#q0icH1xZ`?9>S62sfC2#gV*zE0F;4g><8;j%1D)Gl;WszyJwq|c{e^`Ls%AaJjGS*je zCu&Q0y)ib%gEl%~tE;=8MbB_f;Ny|^hoYybYH3aVYDhMyvb?XxGcz~;nKa*eVZSCo zSbJi|AJ<#x@-SA`Vlj~v6^S`ect|wJah!dgzJn-z?{>q|yp0F*Yhgq+(CS>n{l`AvFq1>sms5fNTSkoZO)4Icqp-N#}(VZ;nnhPC2wk4{wdVn&|+Uq!_ zu`Ig*ITFM-NBO11gv)dtmx;buM>q5^2g=|UPZ8ah#MNvvL_0l8P3dMFbbSB{SxS;r zQawGKL7}V4HzKzDPK_*p#ac}*&G>F+0MX~YMqY2JoOEv@H8QE{F5+^VeBzH59AuYdG2OonORg7~=G(rU^|$i4R_?H*b;a@#=?( z6x}{Q9?zECHYVil5E)YYNXW{-@YO<}$y9K3 z!#9XmRJ*@$wq=u8eg@dq;=1tbcwGr)=M1Bjf!UN!$#|xZULl<*(q5fFW1>?6;f z(}ip)O0>mHpEpzUt_hb|6Q4g8rK8h3BNz-(+gk!d%xRH5KK?ly#f}oeVNjLV@dRV@c@W`)(tF3?#yTsB9G*+oiu^k_gu7T=~3G$8=sv13bGWkmc zHqQcf!im?W87j|uO`pWPzaQf)pZl>`8EUXX>~%0KJ+KdoLu&pu?FYn4A%|tH4BMfX^5+t0F zx{htpVLK@JhX>y&A=KLA!p0u;{TPVqYX>bAuX6RRow3vl8zw*mtXI%TS2+i*?_l*>}Zj@>;aAhz4NQB0mOHd4mzg|aXH zQfl{rP>jYCfN)^30cX`uqyOSS5$Yvgg;ma}n8;t!z~pyA zPSR%w({vP@*(%2ss?VUe#Aq^e$XB)QNBN1-QdHNkPhAX+L$wG;G2aj^6+!7%dW5*G^pr4vHRsaBe{ET z0pb%{^sV*vnGYPUsSUqsaR{ZuDRDr5H#Dc4vzguE?4D4ZVHY;VK+})9+yUnO`rT+I zGyUSsdt_wf{(ANq1frw(qM=bZcFwWPubs-q{*mQ#T3Az)a!5_D4OR?A@UR&*ouGW$ zd=1LRu-?#oRc>D6OTXIJySO0Fmqu-lcU2#I z9Qxtk!l0%@#h|Nt*0mU0{GqRcWeHrQu0d3x(BAOtM{MQ%)q$*gL2TbADu>GbhYyd$ zE%s_8A$lI2eYi?i_vppsZY;;-=Pe(;V|KOov^jQ-O%i_|YkyWknakPW50dm${)63Z z%A>3p8#EW~xB819b-7eAoF2O)xTsRD`-Kx)aW?G!orsN@PhGTM+s;de2v3(uud7X0 z9Op&wTn6L)wqsoqKCf)vwA1+fVq8wnB%z`IOsAqu69shzLtyi=Dca0SJ~pH6aVQ8T zn7X3O?<{}+O0`bG9xZ`2@=w7w7ODqgrp3jPUwuysJLigCpBq}1+}CE3u%f2vWUX16 zn}UC#o=iqu?;gOT%Ji(P2e+%wGHz~IEG#Tq+S*%3NBzytvU;vJHwgD?o~mB5mKf8` zD4bqEw{75fYzUd36q~Kf8Z`uV;dZU?&vg-(BT+I#IiU)hrZq04m)Tvg~!upqSNE0}|>; z^T%jU*PZ%wLd_%qCZ&KhkLYuCkX@Iy(B&n*5Oj#SPnXQRH+CO{sH&8oi<{Qp>uETO zwpX6wvh}g;maJg-_EW2{-@~{DIHbt+Z11-)&yc!~#!5x7E`qwc`ss3Ak(LBypKC25xQ7n9ba8%#Q8|`D`auf)_Hs5vz4#L=Qa%Rjt z=)Lxzl-^tt*L5oKgCI8*50C#Brd=$`_T?l?*z?Iq6vT@;EEYqZmuA>q)G0=mke17(aIH2}AltF8S`-0i8-K_{F*R z9a<-T}z$hiO>Ky<&-Hj(+`1h1vTJDKf? z65ufU?`qd&!MU#e`Yly$E_Wgk?lr9p2AK^Qa*mw{s>1#ws#Nzm0Bn4tfVeNxt?+yW zy<9oi_a8N@1ia6lnIFC1cT$8Q$5=o(-dFqlZdJf3ho$DI+O!^H8r=i6qfRa~R%xuP zA1yTe8Y|be)G=h6z+a}U4ep(yISx!JRy1T!~h`f7#950mPTyDC>UnrbwuV0P*U1!P3GZvQaSjNCN=9p8y`wM3Z$7JD# z^LsIllS;rhH+?o((yI0?$njO(Pf;bz_og@UOrl?fu>&{I_VwAbzbqaXypxyNsL7mc z%tWPiS$m=~nym9vgH#)RSX>iLok`!LHkj-%g{U-NJl}6Nks5JnZnzS|klVbUdku%$ z4jm~aEM2cL`|~(LI9q;Der{d*FPfp5#@|ER0+f4#@RvV<15yq~c77R+%W`>Jk0%a2 z3k%umqLrHpI;AeJ5yZsB(%AiR`f2+8pu-TNl~fakMjdLNj6-1b5-hJS1j)nRIIqc-a}L11 z1u2&0 zoeP6znkPEW=RRq#FTj}xfw&N5H1d_#9J4M~@+38nFRE3~Detu`6OxxDxRg(1e^yb^ z5Go}s0#h2PyXT`Ey8f9QB}f{myVZMFR!|HL4b>R9;rwfZX+8oqZHyT>-x_*7dw06l z)Yjt{J>81BbB6TBaMMnez_@}gs1xT9Jn?gW=za-Dq^Ef`G2Xq={Km7wmu($~IY$|d zQl~8MrCy41Hp={tt2=K6_S^Y`?d_3MZOyHnv);HoR9PjFo|Y?XD=v+D$PE<-$B)Be zEsi>t%e5a>^b9tuzgX?{EyDwm{s;$=Vs4|u{d#Xd&M>1o5D*YRr_{B;ReH3(@@DfG zU8J=v%6S?)PurWuCIDDOS)?Ud-xY`8iI0eQQb=F=h5e4kSINS|zABnfQdP38r8!Jf z(0UL-)Ay+Q-&RU7oV47JB4Ymm2D{*pE)~Hk-tQt6@H<%3)(w&5=6Z*{GpJ~EI3=OR zbxJc48lm6jQSCf?VQ%BnAB&gq=V*B!L zwe*_w6N2WVl&iq^vJAYWMjxTdV}P&_mL9L{V9x$w^M{)F=F8F*D5g0>rSDqhXoxNX zoQ%2NOByko#=&}Y!6G22fAW}p`u7yp=(xeq!wiS2&qj>cE+MVl(7SnazuSK4@&|iv z+l9*gI#!Y0q-Pe>wMXu=*T7>n;tSB2v@Jb)dvejb?kMhsaPOaDx!dQ9FmgQL*W)DS z<^b>3pTz-Et`uQ6h-HdU|AVp^XnmUnH3Oy2&~W&BNPJ-%!kd3GF%>aZJv4Aa+j%Cq z%JLMQVM*VHWRBzwq%EM^wV=T1X8M1C*6wQbvih@%_Eq@ z%UjN^36rZ98S4J^5ed|i;*WzpJu3gr&-3%~eN|DZRCt@acv$y>oBf!!-fL>aTaHF))ZJE0b?phMm`n?CtIG3GllQKh+9X z(oF_MI-{qBR@f3TL?>~yiK`#|aCUb7UH_+e?3j&KoPYqCj$WuEIa54`vCcQFvQ=6q zS9oH1U2pMqZs)>WN7!L>>#?We2y88{TtBa^JT~!3x2h=lNf1Ilmo~YxvXgm??$EL4 z$JSIw7J3hijk4gElEIu7N1r%o`IB<6b|WswzZT$E_vfdKrk}=E1dMAvyl0q z>5!CrF?v8Q#Gq=>i0vcY(VNE+x!{lx*~yD_7`_&vH>z(j4S% zt`R$jA0WR1CYd5U))AXqjBjmv)e)EY)TZIN`q#$#9pqnc9XpbfpW2Se=avt&Y$r>y z^8*6Q#`WJk-eF2qsHhsK#7tYAdJwQ6Bn*d6TjjUsk~T<11G+x#Q7dAcQ78pCu#}Y0 zzab>N8^K7Kw#sd8PMw>319o*qKclG3%-2xnTlZJgop7AyheD8p+Mf9rl`%H21!YOU2}%(zP&lvg`Qs?78-VyIrZ4~f zQRnO3+g#rG+OAiG3AKQehWgVD&GXL{!bLu%Jjl&JVWH~UMyaA%`np!;ET! zNwO;EdaG~f{}8Yo5BaG_A*QDze=eAfNO<>v;eag|`%ws$MT7Q^PZ-pcPt*0nzowE# z!at?d7jv3KcG>W|{NKT8>D*pK-u+6>R29~Ss~;vND%CV@Gch!=I}Bp$>dH7CJ~*6{ z!(;#7%#fL>00gp%fP9ZZ=eA73f5+qDAz5{iUbvF`r0wH>a|1D#zfJf%ko1DZ1o{!-pV_tgX%NM6-?2ou~uwQvK~ z>*z)eOpr)acEEXd_!D!mCpqTKsagS`e3~2%Hl;z@_IN^ zniQJxazpNn7Jb5F{d%>i&oP{*g4?{|ugw+b|E_MP2m4oIS{@bG-)bFvYs~;!wT8ZB z>z!xz7*6PQ2)^7@!rW2U3v46O;~z!2^Puxl7+=^KzVsIx5fQx1gY+J<;pb5)M8$A% z2&@bpz7W2s_=kM)5bNvW|I{5^l6(8-v&W13xu|_#^}d!Xoa1GZX7PDkS97!k{qB{j z_FeQacR{R!+IyK73u}?6SSvO>mzKlHV=;4633Jn6l;?%L`Fz~=`Q+2!b9^OxyH#KC zUrYb>zUu2%XLn~)C>%Y}z1InwHZxg!Z1`I>)Uo7Nl~eQarCwtZk99CJwRAEGpLb|0 zFDu)3u$-Qr!fCh<-J-7oU5_kf<>m9*+ZFh&o8}hI92L3(f)p}1$lzi}_?B&`a!oKX zfvbdSp@@5>mYgB!$Iy2xDD=_T(Q*)8U6YDBV`Wv|n9^&z2xGS!hj5h0K0Vbp3tBI^ z|MAOSv7Qfw*hU-{A-|{59~^cgD?Fww%Xv0SHzv~@ z*qPp77p&{Rqpyg3B{HQ?$oXa4LNdqSV3U~mRB*bXIs()8#Xlw+lb&1VenUAi7%Gq*hP8=)VE!bcycRJ?j`K4I@KMa`0 z?aFes&!R@FYxdA&SPKq!Od2LUI;NOg{}X>QIy3!hs+>p zv|`3l^LU`{*8#n9*ckM*ZR($=GE=3Qwa<$Yx@6R23z5PuOJdSa{xW$F25GwyB6}{Pacsd3woB) z;K~MohH9tXB|ftLmeiIN9%GozO-;vB*;8Irdtdo5Fbdw07E^4_EG_ek6l8XP%{Ew9 z)6jrN8YFo7%FMKbJ1PwJ!YrQ`5YK`!l{*tChd2iI{G9H^wHU7T(H*H zaW$SXi>%+m`ml&6^QYtZ-pLP-(igfa-%RYwIVli5m5&Uu9IY@n>_XpW_0F7Fd~#!& zo@NJnjn4Zufit8;yCrAG()yZMf=c6bIQ3$r z6-1I%u?#E3`Vn~mgTNGyj}qE%09BygSVqwGC44hmLdsVi8yxJn$3$p7d1D>9P(C$^8=G>jxi2 z5O2TAeBq;}l!V~rRpkfRMG>iiLH77@mL#c&Y7l&h51UlyMm$ zO@qQ8%K?0`PY?8`XQ!a6JIeurx}_#Z-mvlO(z$fka$#*3rG~lgB`;c~OfjQRui!du zGYf++N;AK|VMP?Rx05Ex&ELGJbT*~?nUD|-=PI{DM-%g*DduW1T-t2V>o=0!PQ^qwhb9^8q?RS3Yw?HHmKsRe#$)WXNug z?6zeeOp{o$2V8!7l*Tn3Gv`cWXTW+o8qeRIt*B&XYX2KM-CsBFlt^o{ISWPfNG&)B z0il>LT*Xc8{v42Kt7M-=LQ^9ql4T%r8ZX-O6z8N*p%hm<@uT(^EHn-}tWHf?Tc z1&x%k);y+A$S8{{8-03@bBjYN;1{Uh=K0eFjAS~fH_#mvveax%Mw_tb*yCQ9?C@Nm z$9^U^G9vGNBs!Upl_d*TW=qGCnLO4rPOEGD^~-;FTXN-Kahz#O!0@=;N_)2XGmMZ< zi8QaeI#AA^hL~_>xxp6|E{LV2w|?#H3}P0cV`|CP`8url!_(x`PiBpG1j+!HAl$`W zXBOR9CCA)fbKS#OWL+1mTSI9W`%xa|GNHm{jf5t{@9y&D96T4v?_^4Bxm6dzQPh+I zNTQ<8Qlc@BSm4$RSGj3W70yE_PkaJt-<0EO;{telku1j<*8 zohtC~=*6hAWaY98G0o2+#EXF0u-a;}?t_zy2HZPh#3yY}QT8 z-(v2w?#HacWE93enI}u4tie2!v95xz1n;3|(hn!1+4~(E%6WH6Mj(pkKAAnNj`>aM z55VhuOEXh4o>cAI5p)TEl{m!vyV}JxUdzw+>2d}8$rMPR0JQ(lGq<;^yW% zXEe&x6gzd3qSRc}QCq#Ox91k+m4KC%Vy|N#(EuM>Qrv?`-6lIxjgcqEEUGcX(RkVO z5xePeS^d%A)&=!gFtp3S8hq8QK0^E#3gDrKcq)IrO{oPK?i_7NN_eS-ILJk#Aks#P z1$9i8sM2{~RXl?SGOC=8=VZ-2ijHRxG|dZQAQU=sBg6P=8pq8C%AQU;%$mB_50i|n z9|;$a#551Cpb;*W>jq=F75z*=tv}*|Bg0JGwL%3y#t)*P$u>qe=u{gNJm4oveEBXm z_6zq^NbL`8R;$#zOoFTI#{KaN*3O!11$3aFHqwH5_`|;Axck3 zr3tkE)ZXpbY#@`{UA}{;EXa79bMhx%FT86 z!L=xojL?t{Dl+v>wX%75JsRSEvIy5w#i4k=i+&efXk2qVG~H_ltdFr)wcwJuQ1tWn zYdK#bX@Lvkh(%dSK4)iDkVO)*{4Os~d7^OrI(V0n1(9@$k|EO=45{;}v!U-+<3qd5_MF&pSm#x}cMp?5Y#7c^;Y17oX< zQ-Q7wPyMFyx(t#Afx(rESC^ODFi~MKlkH-ZS&!6I_R!|f%Mlye6^9dfr;9}oz08_d zo2&C7D`CuAj*~3rE&yK!*9lb{l0Vhn%9p45ifi{|&EOi%W>+z$O7jEysTTIf!c}4d zJTa$F<2=4Qgs;V#t8CZoSYV-x%C?ss%ZWPSYyrcD_p95-o2ob0;s>newN2TlKtG1z z{rsMw%~WdI#nq$`7LwjyuQVByX%=Y~tj>LjdS|+r%yr5M&4;^OsW-B}qsu>xo}urb z2FQEuc4iP!ygY*NxDFgnR(r=fJtyJZbV*)|l@uw1w!3oRhpoayMZwfcN)zxSBWsp9 z0C@ck8;UxrOXIW+2-#eKx8!HS1x+UCjo&ySqO_86N#OY|uYhG&zk1oY7oU(Kb9}-C z=_Iy)jna1XWp5fsdfi{RGj~eCK-%Y-Jg=(a@ykUu0>%5_%lc~O7@+}i=OQ33{D5X# z`Nh%0CV^mhfwJh>Jqx-^w6RM)qgj?kZ=ruC3*z%(2^X3(w!z2-g-#!vp)H1sTn$df z=voB!hFX0W_@dnl^2Q`{L}s$8&%N(#47Wk3kK1}%ZQbik7=Dz@W)}Jc^*&4TOcgNq z39)XI^U|Wm6~6okPlO&9%fp0*0l{(w7Dp84RL=J@*N<`rUPr_(E~`yP{@8$L1Uq~C zM~q#oM4T$6B@ea>tSM=xAz;BoJNT0 zE5B`9iMQ&F+OaGU2uyR|6WSk32TWV;qPafM-dxKDhlml#AL$iwxM4Fi8&*yZ8reM_ zO_iR7@hw}Ufg7ROGheR;TEVlNTi17GB>6&1gWuGju}r7U{hNZB-yNs7CgY<=J`ayx zRPGM4!eKr-hxa`-w2tJlosS~16Y?fU@`hJuKa$!ZLqb5JA$4WHkrc*&gH_xOlOv*{ zm4fkrUH^5jU7Oc$pA&dR^v0VgIwun%!@su4G~Ww8dkF5lQ+nU3)l>|JVn+X~UXg>> z$z=2p-HFxJaJrm()VM7btf=Un3+1Os$OVLReSN(h0$T+>Pkn_woT_FDCH)Bsf!v>L zknj2V;G0U-t9Z7;GG4!ZtE8o6T4m^2>43jEW5opwIH9<_0ZHaf!_9cHH!YoQ2j=u$ z@Z0;)8aBg#FIbC}|CV?;(V^Q6DT+Zsij8=y7B<4aGT9U2J2X7LwPNegJw8sx%j;R$ zv5$g*feEkGV_m>8TPCr>KeIYoSjOQyqtvBVOJY9XJHN&p)XtY_}^Ba&w=^Rt> zWbPi*x9lzJZjT9um*EhK%_?PB#zhcS*=>9b;#QumP9zPR$QXeO&edwC52uFhtuG4Q z>#dhzkd6H#-t~idfbfv+sAi3YZK?MQsxjPW)di7m`HQZ8d1aBo!LpP(X zu!~U1DBOBl%U;puyJ7f^BzQVs+zlVDy>2n7LHyZW{Y7(VW3=u0k(Z(iL>=4tgj}|0 zw~zIyD@=jpRBpMa$>xG4Ho!HNBL%6Dd&Z@-S26WdGu19BB-<^(c=G7$rM!`b!Wy-v zl5$_dTJ$32fv_;~lY=z)%P%<*AwtV-P)vtUml#rBy>r7w2 zW!4i@GaGEov{PCXWk2hWzfv?yLZBre8qa|_*klSE!oI){=+sS$gX)YZ z;os{aR_2jjm}|&nf;iw>UTZu1eVEheo;E={`4=PUS$#Y1Bowgb|}4p7HuGiWvs&>!nN+$$_cHEPcC_wF#^ zz*QvcQ{?ux7KX0Cm-#RVok9bX@oQ{DE}GED}PuSQ06)V!=U**|-Xk(~UN$V3Kg5N}Y0sksD%TAF+1zWNt{4^4a;hc6F4 zc-~VQfiV|pFkWzyO^biJYVExN(7!8dB`iI8?qbvm@bF{{>FHj*XrBlh!z98&F#ued zXZxRDCF>j4yF1Dv zzj8U1AM3?N5T3hz{BZyXX^a{I3WBX2S72r0W31IM>*rYR1;yJxnzHI48)3;J zc2zKg3SKN?~I#^L! zY0GzA*2Y8i2l!D@P|-tnkh{kbi1qE-6QP~x`EK%lb8Yh8D8jp3IHfxOn<l`9@g z-@}oeH-x;YzRBy8N1P?llLx>Ty{~_10-)z)h|ujp7kF%zb$jc4*w(RqY+cDGM3{pk zU7Fmdy%jSp%MY@)2>-_p=N*vGQq(bGRaLtWggL)|RoBq|w)ec8dVz(4D4W84>!Bpx z*$I=7lF;Xh5w~pp>Bu68?A3T0aF?^EO)8@QTfsq-W>4zecZU=u4?S4iEYD7qD(No)Pa|v{PTU_1Lt(yhzkky&&dEeeF@vM2!fgh?w|^U(Z4k{@_gz* z`BJ^3kBS6m0lBA8;}!#6-68+hSpChi~pT545de4*#F2FqLnam zz;oaVdn26xVE^F!<{1jPilRsfO-drzGL8ef4+{Ui`uedoSaS8<_ii>acXv(yDx9GA zJ96;}f|cAAG_8t(Wlh9e<_@*3$7%%6>&BY}6(|NPX1fJ9QX?z@w9AzvBXSRyy`B%7 zA)X%@;fTPKhcnFg);!RCNg_Fvd#tugDCm{$kSqjyN!mwbli*Li&n(st%>L|`wMmFz zgv`+*g$K6wjZaXLqtf1$#&se+Y=g`an86Nzz~f*ZwBhjzST+d)ie?{NSp>L_bgnA7 zgdyVfo*TI}BRiOV8>+P z?hZhEHVFkZI8jdXn_{-^bEE|8?)iC7UMw^TE^%_DtZkOzmn|wocc^%DM&77^esk3H z8!x5MtY;p&Il+k^?RFh{-M^%X6V>%}0WX$vwB}^Aw?29BOvU~hJ)yx-dcTB+QKy{x z+}K2CI%^BPiPLR4Yt;1)u;p2xlpTAAoH<;CWs89$tnX_NyP=o_&6LH07d-ST z_Rv1q{k~jcE!WnCFYnqnK$EgT=&H2FR{!0obA3QJgqldDNSu?ZN?6dFRZJV|? zWmovBHv6@C#&_!lJXEG|!fE9wKWNa>(%8ZaTB04+M5SVt5K@}Pm6~*MTSQ8zU zC;xlu?D0E|!QEAL-0$V~$1D&MEKL=!jF92!PFeSLQJTWZ$k5?=FWVIrTTM3`z?C*X z;7gJcf%FBTx9l^}hNq@bkQE*w;HKBreF;gLWH3Ijn=P?Sv~PE+O;;|w_PV#}Et0OJ z%fV^-*o;P)x`%8dHdKKkF&)U}a>`$_ zfigANB()fU?1W&K9F=IVWSI7vT5{-({>H%!oR1=AiRf#gWK}G z#RIn^b;O06MOES>v3=owc{n%FeD5*5r!fnW0l-kiB zwoGUrIV|xYQJCy0KU6Qx)9{yNB}RB-311gtqNW=wremSch1$%js;iF*z1Vk*EnSqz zsOF10^6?`(Ol<%Cnn~4js6>S{m8oO5(Z{ZF$X$K4qaTHsKBjngvNJoQtRvqoDfI~ zTc#L%3&EbgI~@6w2(|u>&f@X~`r~+6wP2QV`IaKZB!4@s3pI(`9y-Dgh9aY%SCX!u z(9^tQMXb~K%aWiTMxairU?_XZpWVe#uWhv4rQF65ui6}m+iF6TU=6D{hKV+9v%g-E z13~)3#T{Sw5F4A%k+^|yn8EJG*!4r;(eK@)A&aq=n@tCA&3hgNy0k%11HkS#NYMH1 z+HQ6p3Oj$dUrDV+?{^YMr?;b{y}8K_bDlSKVn?*_Dz125`s-q1JXNah!xwO`#%1Tb z&o#S^A9rzE-{N^&WBPb(he^WO{Q~7Q$kfaCm`47slR6yXP(Q_dwl+`7p9gj@KIFC> zuLk3v*1F*;aF{1UovnQ+BTY$3YaZ&l;61u`jc=P}coe@r=-z?8>WgqlUH;mABh@-p zPLlJsv8(Jnmsnq4AJbYKTm%3L*o-zX?|d0*t+gyQpcf{B!onVDHL2OHJXjcs!u zXEn!`q`~DZYeNF<=ey+n7z0um^aKry1ZGmA7~J3LeEohq4eTQByvwQ#8>=f9o1U3D z8T7Ep7-QM@Hf!&6YP?%Qzy3Xj)IB(89zGQTpd8^WUr_ct*_>e9y}RuDb5@p{^IwKh0@~X%)VZ&W@5H=}DXK(2}s= zy*eIFvspcHai+?vNj7uHC-T?4tkG{-CmlX-n`@~6 zhUE%8dLSzyG1I~V;xv1YtAi4&d^fO=BI0wjN<6xyg3Nv3-JRy(Bz6`R(VAyq?P?|* zc-&@YXZ0*B@+1!(vADRp@}h%cPtQ+tD=K(&BAA#k;G<*W9Nt}H06KS@(kVMPb$$AT zs5))I!zCidiJznJR~4(ey?sSY55n(TnDB_jbfh9QrUb=1y)qWx63S2W1jAbXKca$A z139rz1JHx|#vYu1=G*}+)XlKTD@iCAx&pzU63L}$8>&4zDic6W*QJ_y&a4nbeF zO;k7pb0~h=TXpMjqtHcLPb7;bXsCj(FUr?%^$R|4DnnM_N@8OyinQKuMdGuC2B`O} zB9wO+3ktje6$qZuL;*fY*2|AHPHTiDF;`wN$2_-!GkBTIkq|4+%}7-5BhP zUl}eB3%(HvHR<2x|6O>-eth8L=4FCs8`<>B`x{2G=xTOCe?0qFayA|lZ;!MoAFi-e zxP9?r0!DB6cHvNyHlsDMmlY&FOX!VPEndv%@>T0M729=lLk16Rs`HgKr-NU;m|cPQ zH|3}|;3+A&*I3U<0)2|{P@;^X;aiaI0HSTXncqRwnzjfT8G1O}Rbl*gesUJfI6Tg( z_3@;Dba6v!7E2hBKhcoR9ahk>^7QMhy6avA#n^S8+{f)GUq0L;B~3Z{Vc>~}n(v`n(*BD>jk3l4hlUDvoh_KI>_7uHHC4i8tn#|_ zudn2A~o~ zr=v5HeW0}V+%?$vJYc$WrM%|?L-)V~yQekeaD*M#?3=)H#WS!zcZ-6uDs0vXvWY0u z1$sSCBw5bXK(g9d0@E#}b>oJ)k#cco?)B3y%=*_9!Y6I15f$Y(I5?8-!U2qh8f90( zBpoDaV_l<3rkHLFap9^rGpsx^4%e67<)7KK8BxY!>Hv;E>=B-Csi-X4ZUX;21fdx12~7Eor@IoxC8kaRv6d})dFVsD zP2WJ~{dn@RDKsmK=xXsEg7D}4^;I98?QhXJs(Ko=w9xU`3k+o3_AjpuzI^-Axio|i zQYb$KZdI@EYqL{$+9!fb40fY;?#j$x=+Ko~pn6cmYRW*_Os7jWWXJ1jq_$M!BRZQa zA5rUXOnwN>RnoP}X&YKdtdr$BOxcst%ZKDD{;EaR>$=;%c@_AFB3+(+c=$1z@dym( zF31;F@MhFwlPg0e*whQO_SB=a*XKl_?bqwgxV3#$V<1(|hD5B%Mp}&bzlzh|HGlh& zdhh!t_Oz2urTvs){vwydWpzpU%(R~{RqL2w6A`Rcopek+h1!R>HkO-|HK$1nvZRyL zOeSnL_iK2~C2l%m*C_#-p`H&ISCja066aV4b^t*@aSU9lo{T=p-lsEql!&PC8KQXN zT}-Ek1wj%>1`w24%7u0=SIc~*jjhf1ad>_uG+U}3W$Vf2`M?vde)ZMa?=rsoa~_YY z>Zci8cM-b>9GQfkDEB@2*~0YeGaL=*-vzQW7(Y9|^mYo4&M9R(E-f_**EV_J9WhwF zw5?WrHdcZuDcS!V`r4>+vj^sPT~f2D$-h&qD8V6t%_W0z=3QUQePj%uXQ5=XsLEsd zC0eYePAuNlVo~0H-lR4Z0zwyYQ0@a}~lip?rW)cUM{ zVVJic!&TKt`q52IOS@Xlrfps88>P{}i<^@*Wiax|qF#Sia`C2RYP!KHit+Xx7;u{6 z^=H#&6Ch31+sIJj3Q}0i1$vA>xAsomY@84uU3};%ww&(n*EX+2WD3@uUH*GmvnqGh zLwyB;jwv_KQ&CiZ52|JLLzWEH-Ib`=1>=Z|Uc+9dTHUd8K_im1@dU2ln_z{`khsTO zHUJRm@DGU82S6l10%(ZNv^X%UT-ua+$V$o1>3-Kgo0P)gu9M;D5#qeTu?QvEQk3A} z)V3pnwhpY|qSv^y)c; zqk=$AP+oCd(Ib^p>)vlxL)G3(&3)dZGPNRY)?EvPmMCxE3hK5HfEJm6mELj|6NHX2 zQO**@Gu}upGH>1l0Ex$wh1aape8gmtjL7!43sEe-2(U6mM$LJuyawH0oWDMaj;br+ z%10AgV;-7TNO0X4I=WjT93V6srDD0PDBOO6jy3kbc)yUzZ8N9h8=xC8?Xuwia#+H3 zS5jRKFdKmT)y78Ob7?ymJ(e`WICXM3Q#>)mz=({RyX-)17~WR?^>+5N>L7U@oNmht z>!Y_JRvt3Ei(VllPiXnVPQ$;@BPbAFm5eG}D(JM(Hq2eR#9i#r?#Z=B?&TN9%wLZF zpBC+kITa^q-=w_o>^#3+QZ^3aE#N7ALD*3F#BVP2x~3HWMbHl`@K~rRM8swu^#@|^ zf1KitPi)15@s&~FYt2zM{u*jmGTkxhNTe~8(BS0%uad+)GF5TP{qX_zUnx&!N)<(` z5u>m8M6Qq{Y_)nw&nNe=C%Z{&H5a`mU-jZP(?(aAi}AIEDOGpx;6cK!%&YSC_{+Z> zvPACdC*(ICUa2>mx0r1|EcHf1f5+y%PO$~7oQ{H%4WT=cgg5qQGouxde20Z0b^` z!?q(TD3};kY-ccIg*+kaEjsG%_>p@8UpCd;m-5Nk^Cfr3+}j_v^IJ$_AE3`C8e)+z zSd{*S)d&9Y;1zr~yFA^a4h3Y4SRwI}xiv59z+S1Wyj+>o#RC+R-lDSb?b-qbMQSQ= zq0k;08w^o1e7qc=7-<#S3u6i!eAWWIPZma-|e zaefmn0*E+fuUN;`L}(mqaa%01Zsra zRi5up(`hmn0{#8XbtMLZFb>Xsc}>k>?1JfcMM|KLu(K`eGNlJ507dqZq&cbLKL^_V zhKFsFlat+z_)dVyD;XKt2Z46Gvtxn_#jo~}>O3o8EUlhcYf(NQG)YoWQNJ~G*iHrR zQo0rvaHI;sC8f=dEtY*=q9sU#w3D;9gEJR07uR2{-45*rOMnOHyuroirO28)=yU(4 z(XGz@m$s(`1*u63vzeCCc|Uaz=?lfD$jBMfxPPG?%EUwkaQ2D|McVp|3AZ!Ul$54U z9iv@SNNg@h0KNCn`qlTZaHiy!O_&8480Q&^RtM{;FT{S#GRod2X` zaGE#*LE{e*wI9MRYWU!_q%A{p>vGBSohhxWx{G51W!}B-!qCJ7_;bzD{T~&Wph!Nj zD)jc!{9i({mv*pkmj9=g4|uqK{cn}qA3d31*t`E0)&0?%jbw@bA7R=#`Ts92muc^C z#Xx~F*E=)wLWGPAOd4ioWiZz_h(9p*7&7X8FZhsGn4Vo1|73YeZ1rv{?@6vEcr`X+ z)Vlbgx8kp~?aSf!%3a6WMSGr^nHf{hKQ4z3@|D?36t&5;$SjFe8OpvWVc>wNoa z1O{9k2v%9uH2^YPUS31UM)qR>{d02KpGz&Mh{Qm8z)|$Q`m6M7s2nU9a}xd7H`j%( z;o^lW&CGJ57iRid&*aA6V`s*#bQk+!U{hTx#g(@%U!&Ee_&7zpzOk zk+Z65cvDyv6_?D+cR^pj79lt~vB}5&V@-Q5h^v(c%({SX3*4)&g^i50b&X>fA?LRq z!*^_K*r2t^DO%ApQjup0PYuZ2GPlAUmd_w0{62v-ZjJ!{(7R7dW~BD_Mg?UiN1Pg1 zVd}WKo5;I|qF%*q+mc2FeY)cYA4IGD=PD)^QkcVU93bS|SrWrWPOjW@h}wy>c952suNfRrqt7M>9=J|LNu?0SVAc_AXblq%4V(O4-y@ zeWQN0 z?P>V-pYLxH^O$=2eu={B9Qj4^w<$&PD!$4VAUOT<@3#l$7`>M;GBN@MZBIWL;3#5W zK}+&f2Qa6iQSs&W%+zXG?lu~rgWrHurcB}plvx@ zdFnZxlaq*mWN;%Oc;%k# z4O5}yAtS4LF*p3*2E8+{hQ=;dPN1eH{?EOs?Dle|Jg*bXJ3Bw`Tv!lDm?v46Qu#A; zOH|G_bxhz85QrG;h=YQNU=a`$j9onbGvORzw3PCqAmU8X?*(p|+(s3R>}&Hzx}hNd z{PbaZWuFnqIQ+i3$s92qHf08XxU3^kF*#!TJHbAiimQyv0NLy;H8u4ofQ_td?w0iL zUap7y{rbZUZ~<*??cQwRG4Rwan*4pVUyekVd`|=KzbdiEhn4;mFVr2(t!w9BQ@xgd zuiKE*xkzhCE%nd)R`7}#l6J)0*O$LPsS+YaJVdy7rQkYPt#P|Sm@gPjTY~QqV&mQ4 z+4iTKo_p?D#U5A*;8K%W2K|DKukeSY3cvR6<-NDzU5hDIrY`X>D0z8yf$ zkWXznEgbq@FiJ&M-z|W|Js4YzJ=199$JnRO&!0hz&sQL6-5Pl|wzw#lKn$+>1rY=n z5`dlumRs?X;VCISGY)3J9gULA3LWIi0iTfttnSjw2+|OeCgs%B@{_AXD$2_Vd3k+X zy?r6FQ@Hwkp*%d!FJoe2$fK~zvf)kh<+3`-qadamoGKafCH|crj%@OI7CPWp%9F}y zf8P=We1CJND5|~fW5EE8196?e>DgI#e=o7!wCJ7ZJ-hvRIMCL7!{kY=+!|%~xcmlg zgO=7BNMFgLu*=r(s%mQFNSz#@%AB!%t5fiEzcN*EaxUPqyQ3@@3#llE@+VA%m@a%e zc9>L9ob@~gFFwIF5VeRkSiXxQ)szOXsIsy$J16HG%-6sVoF8mN94&Gv z|2UvcP*PsF1BKU1L_|V*f-mdQYZ&mjXM0%_=3uYe`tv8GAODix5)?8vO4sjlvFMnX zOl6BNn8*@97#pZW8v}x$Cq2w+MQ6hDMrRZ~Z0JA(Z#mo+FJ20gr{Oh5o91xh}lQ=bm5;`?ZVuIuks1w_$=kP;|*YjZl~ItgUp&8!A?$QEcifx*F4Kb()2hgYDYqvMyh z?HwHrWi`14-n^k8?_L9T1=h8_0gfplW&dnSAVl zXNp?v1T@3lsTe%Mu&w(5SCO=wGz7dxYs!ex-Q5YLJfzj5SU(;cgbf!}K`#?WjUC6H z^o}{%6*gmVkKgT@J{0OTjM~+Ly1aQs^=o1+H_VaLP*qIvZqDXZRP4x+73tB{JY@Z!3PXvX<0a4Zoqcq(p(f==zoWbu>B4@~(NYxt`b~Gt!uevke9&B(yC`L+xRY zSDfZ%5K~h0WgGCpSg9{Ay4GXEWEo>&$MerVcu0ux7#&bEDA{Cfsmi^|>k{1@!WQ`0 z`F=72NzFRmeP;(ZODvIf@=hzpKl|`DL1|*ishoh6Cc%I2MCIC;>?5B*Nqld(F1qDN zgohzQ9~-g5NXZzY(Im^-@nFG^(4>V>iG8TEE9rN} z<>aMv<;EvUkF<_SEvxvHF+D^nv6xXmK$OFs`LSA9)8d(SYI)2DxX*=^8IMh(qf`fJdCnpyQ+9r@eQ5 zJa+cjqhn_NcI|*JFRR+x;AElNVuuST-*s>}#j|J6o8(p!W`Y&1hVqGmKROk9%6 zbCK-Zb<5fd)?fYzHKAb35Sxv6(_|S( zqB`ZM-uc2|n-O9#IiYY&H{Ev=GS}mXDY}~ep3)hAW%S5M#~pjVQ>(p^Fmz(h7H#i1 z;@c}fT#-Qv^z3vJ=S?Ze9hElU5R2*5SHA5c$VMKY1k7>3959VFkHQ;2TM7|uyH=YXWJX(^A+C;XQ{xyg1 z{i~U2BQ8}NyQ`?Mlt9+xq2z4}TX~S3tB&a|4u0!#Id3%nqL6)R>xjFxHwj}-|sPNbzjL1PHr=@mK`~A49`1jn&a0oS&y*5yEL|z(6m%?O*B4! zu)MM*FOGnF@dYdPv&%2vQfMg|6W60rK51wAN3~RVbtywoI-5) z1BF+?!PoWvgt27al-@(0IR*@MZyc^HM#ZdB=sM7fO5;HicJj~BQ4|;e8ZvQVT^ zo0w=53SlZg?+7$VsSe3PhgVd@j{;-scu!{{9-Zn}sAAu^F5g%Ej`oPT36C9dy0TF`~FZivx{BOm)=%b@>45opM2L(MHuJyVGMgpSY zTrawqURs*Fw_44^N8%{_K0K>VrlcgknioqZ>RiiN?9E{Q#fxzD!N!)9T3(=Y7b=?} zSZ8?ZwL{{>r*5-X663_A39nl;Le=w*pnw`_@ z`|VRyT^fa3Fx+0^ksU=&eHdT`!PuTyiuA4{%><@X1IQj%Gb(%uy?l6l2+Qi4bza+{ zgff7!JCkx*KGdFq4N5BHdWvRF{Q7NB9pgX0KCc{&h`EDQ%Nz7FV7~tlgK_~e0{h&2 zD5^qgM(@M(K}1>gaLu@E@ItLV!!V8d=}U9lZU1%cluB6HMEDKzI=`qSPGWMU;rCA% zJbSFULUWPMlnL@%?4**6_$XGon0!7Xpc?DQhvy`~nYH#>BL>+u2h4dV5tb)&M*#0lX^!rxfS?0Ev)mMp3OkfU00(yS`26 ze6Ywb=t>NpuAg0VFnl_EPlaJoQ6Eqy7VPaY%+>Y=>EF4pOX#$Qz(`YAO$`%N`g7{) z!q3kgvh&iiKp=UxH8i=YQ#Y*GC328eQ4zVnUj!Yak~Q+)S(-E^hH+8G#RzyqTK{6J ztE;o$=;xT8R;41_!2l8Agwaf9F_oHA89W;sI&+SHHiRp&-9;p32WNC-M1()7JG9?C zbM@_aMH2`Z^tS5FkNw$%{E8_&-Ko1qhj*7symPW%bW@!SEc5kF&lU`;WFRQaE^X=QX*Tbm&FlX9w%&6nsChyPZ?Q9m)^txwm zW2rYZH2m=Xje~KBpvEn(U4J4k2I8aW*BGLJNX`B%B|#MQbP^&r2Q3vlPADbQVO71A zatljr&GHenNT<3(9LF=~e2p}TA{#|Z^4T-9=uoXzCkgA-hMA}`j`COZ-$Se$++-!pF@6?atD7)rffvn zV(_R#6Wth&HT){c$%t5DvX%;EsAKPb?CkhnC0?%7q6N}*e6N^g_iIuDALUE?(H`;> z}<(1(l1j2B}%7q zuJ|cESSBiEQd z4*7s6nFP~EGe7R(Xtabfr_~#QYlgwJ=l2g@>xos*5!_@s^lH)ZHvNp*N5<^ zk(gQy;C2W8;Cz4bTG^{S(g}OAV)sYZI>+s6)R!Ft`kJz^9?jQZl)%S_d2}4HN1t>I z?`s^ux!8JY05VE{4Fe!C%O!SOFBl)MjR$Lsu1l($D>% zbT(X^8XeVhcf9thS?%EkSHaRV%V1DYEvv3J=$n*+c>cm4cm)gqP^r%Y{|^89g&S}T zh0$Hhy#TIJfVAQ-kFKd-Y0!9ya3J$IOkbj7UkR+6o=SiOoHhI(J32cPAxFx=CYU8& z*^$oe+6@>+Sm5B|*4uA#D~4#%1HpWSR}MAy?(UZoVmMr6K4${F`Z?DY_a>DR8G*cF zH&dkRAI=f-sJ-iR_{)n)#>g2(ZSEHki{IxR&*MpoUjY=9XG6vhA5yiqGIij z7F-x;ioWu+6s^0qV`4ITz4aElRjn3bZE`)MF1vX19<`;+ zx}DDR?2NMpr(`E}Da{UCH>Emu1AFYmp(?Mcs3Bid7Xz=R-cakUDR~Zg^@%~P@tC%d z#E;IJjE~|eTp1`?cJG5V?x;5fe+c9Z0?Xv6J#4}6foN1M{P1@D#zUb{>m0urtOkka zcYTbAmN>enptQWzot8^NOZHcN&v8~a8Hki6dN-9e*D@|Tf7N{5Z%R8In5{0-xJBg} zR9eA}glOO%OsW3WSra|)XO_$r7kDT?2Bk)lW9kLN$oU>FG~=5FeJq641;-&nP=~GP z^>xaw8{e92vyvA5cRZ_B;?0n&Jkud{)=B6_@Lgz^k9EoIzJu%-;uHll9mbP|&B2%a z)gSX~LGMW<@byQGFEs-Y*(EYSs5Kw8x@*6Ws9x1foLn4omGt#qM9&~n;ZPL*q`h=r zPStv&TLzjI9GG?P@_A95S}tTDrLUe|AU=e|SCZb?m`r8TztM~7FruVbW7PsM|5nxZoHIo%`u}8U$2q?zcR=!E9z~P!kS3VN5kGxb{vpH z-E>Av`opNg?w-@ZIUWuX)h)Tu8)a-@;DwZ&wiW;4&`f#5aOtl;If=!D3n!cF9r$th zFbwQnKc&uyS#gAIdJKL8r8C5As+vho@tA53ko6ic-yNuV$hZf-zXlsuOO%ym6}#D! z#0RaKJqj7}N;Y{t;{>w0jCOK4lGiR4-xZx=ct8PD*velxi$9B@ROJ3HG*h_{*a^I& z#pa6$5>qfABO{essW?FapJkGUwQOs1^45_U%`_{-I&}@m37GwaB?#5EDGVr%>pg#e zA>a{4T+;0Q=FqIrb*rV%_4>ZrkSlEcv=3D)(3~i~N*8Y=Af@QHxx)o7eXVK2vUB9b z5#8FxWAo1jN%R1jME?6Ov)P}OqUThGj}1;2>bK*DtTprIzO?L$ZzGGLs$ictphh-U zYcC(P@m}Ke2*CUfNfW2ORlR8EcNARS*G*?GZBPpJL$ea1KnQTg+V>X`BE)Ry4ATN8 zYT1)}{@+imrn``mLgi4|{WOlWdo$UoM(rK9?Pcr_Blq_F{cxjmOTgo^$L^`mRyawf zu)aCe+K`WZFRc+0(AIYIQ^e)jeAU}cHk`mYo9<^Ncx!|82>9hUq8AZJ4nH&Ar5N1q zswXQ=937C);>IQ3OP!5vmEI<#xRt=C{fPD`O%s0ajOEs;$%y!omG$M-rvRD(c%|_d zeg$T?GI}fhkQkRVTYXj&z5-S_3L-b*)hiMX5*+yGIO4&(mmW-eN?9XbvIp}+N5`i= zOS%_g2vDR$#_Ud8s=J}?RK=yAc9l&w&(@!7n4>FwT2viVAFr_B2L~!<<})^p@5~DC zIv(WRmS!L?e3Mq`xhiaKe==K7P(8V?Rov#hj1k@Y>31UQ%X;W+%C(X_E1@G@8;t=Pi9PpLJRh+&7 zlpa)TLKTy%tE>GOLaqIoRPEZ~ru44a8B}4pL8pSeIuON%aAO>0m{XQ0Pbxc^O+41t z9CF0WHg_)!q;OQ0WM*f7j#=^=NpKDKzNIt>P~MrnIbDXNNrmtBRg3JC)( z)a56Cv!=&4`HzuaIDO+8)h?w;Kkeu%OA`1^e{%8`;D3IFBUI-?7}$K{zeWOKv@atq zl2@HqLneG6Y8+-g&7xPF8>>;w&la3P%buQfx*8yk%+@^s>4ArTrjL7VF0>65TteemrA|UL*u4 zE_E67sty0-5-A3lE^&tfKLc$rAx~jkF;wWQ%kxmcy;Kx4x%uG zgNW&+MN^~Hi4a2#)(rX9T22d9^sm@jRM6+21?X@D$#T)~uN~>{q+FFVFJj{m#XAhV zy-U=hqb*0;KS6|VD|Wt$vGWw5^v8lp=E36Y%6#T&u92eUm}&~Ma-hEOW;F88Tov7Q zl+W8M0c$#Glo;?EtrB)~!(1x)ow%{&1x)zr8Gob<5SZ%nk@NjJVJT#ny`7P^Mm-M( z3$y^6aqDmg`{qhXsBCE@QeHQm{ZFd0ub#M@w1Q|0y?1)F6JuQCdvCHftws{R2J;QF zc*R;Y*_BVMqRB2KG_C0xBfw@dJE41g9KZVjdiyt|uFPGL-1F_o8HI%yQO{^TLt?g3 zgb)z@ZyFjK=~;o}hCbdL1+=$L*9DL2>qF~47KoVPp)h(&=eO-kVltgeSV8{}fJb3;6UwA$Wz+8QR z0CBv8kyA zU}qgu^BB+affg*qCCz8F#)4348rK&;N`D(q*f(obCm%Vdh~&wbY!xV3a=$V}mp9*& zalB~s7BFV$$O~_u8-UqbHE=dZvjI8_F_`cx|~`kdvF}O)Owr^rNw9C|-DXrGm3*>d>?8h|$?&MF=lK)gINpAr|j_qR*-; zT69|-+E#-)DKUeE9ngFVF`WN~7syDnsX7YxGg3K^PUm|^lD`haD2jISvNihJ z+3cCU3ve!p*>K1iox6?d;tq|bf)dx%yVaW51cWs^w=;-DaafVBDhwbUA!%b$w&NY*@tmUS087)_q_7d+xX}Y$^Q@7>I6jsu%Z= z;vX{|+_~38n5@rV1|Z2~w>Uv#tN3({ym6SKKoQ|^&^rsu*1S;!^u)*)0O2+^He$X- zm$C1)bL2dON&~5z3WtgjrP`0q&dz$1{T#`>QN0gPRvy^aAWKY~m%My;?Ep%sjDX9A z{`CumiJ<1ENRD!))12|?DfRn6iop9=RTvSMUq72h$iK!^-1#Z{1^R0q8s2F9djvc_XFvz! zU^L!M!cmQ}UTaD=heME~vcVSaud>%!m>l}dL~Hlt(+<(|nat>JkQ z=VWb~89-yG(QFnNysxckcA&w!6CEYDAw3`7hY`j8DMFyFtY@LK0I<9(qe}^Drc$>1 zvcjQQKaUBaY$@k|792UtK_Ih*`3E(t&eb8~Xf(-)e9LWdrV1SGza1mpdgi@Ws(W4* z(c!KX(f9zzs!4wo7*Dun+cVeNJhoAN+p@DW6k&qR-&O|uO$=usoSw|Swp91m&)ucu z%9y%e@Os@(UCEpLvBHy5v!H(}vWs|g@JpMJL7sIBSAmYuadsjtwQoP=Z z?IuhO>0Xjfsl=fl{Hvl5n8 zb5IGjKIAPv414#^9Ky`(BC!^3MC{Y24`RI9_s%*f)Es;V2e>g}3!(QNPLen~9Xmq- z_M-J1b~+6Ay^!mV-f$YV)+&b1GLQ;3M$H)hf~FN?+PG%i|01O$}uAGeE3B+fEJMCFf@9r_T)%Nti#>dAfB@dJXFux z3sBLEMKs*p+?c%QpFg`{!MRvHPf%pFT6}Mf4R?GY1?rR`!oLdeTU3l8=?!jT014-P z;}*kMn34|+VspQLFXJx&j^1EFf8SS#X=D^~Cpu*y2B46vf**u(v;S7YYdj(=EaA)+ zV2?lTJ8Uu((q=k!%{50CP444V)wyxW#!hrp%tcM6K-f^74jHq|?(U85+c_|WFLkhL zd+t-OZ-*xFmY$pyfZfyaWk6Bq8LiOXW~h?4cJP*8?x4S^@d7KtUdrQ2(ynq~HC9S9 zD+(JM!u2(RhTep2T}Sn(ahztU#EUXrGb2BL58X8!*T} zp1|zh-VcB5$Im5WHDAUir}3<0ye~zG?e z(`u2)M998M(9$Yum^~pHCzo6{vf7K&P}wz=6SJ%P``=*6DJkFQS!isOF!-%PGZ~+= zS5)i?-{uc>%_T`CvDq)DpPK32Ci1yJYHK&|&$R?v%?`P!|G_Rux<=kT6|^8S2Wum|MF4mSUg!icqkY)T!YT)Yxk#cK#kiKSHE7 z8a)zuR>`u^@P(CR$fQDx@~T^!u> zURfbCH3}o69E?P)qP&n(xKsMXZ|qzg8S*SR@>7P)w(HY!K$SMFw}hl?Wb|vgTk=KcAbt zcZA2p!~~tJ!68w}xn|XZ1&Y1@&}4BJCwE{y^J-FybZ=1q< zKL0fAP&I1RrPpO<@qSRXCuDZ^rtA^;htwO8 z!#;cTH+>!RDn#86aA}k3*yFp-d_w=zhJK{I+T*-ctMFOWs~9o=B;}lbv^M?C_i<>| z;#uH`i2ufD1o0;iA!(yt(h^ z_nt~nBcHQ|L^ns83<>&A|1^9VF-@1xQy_(d6Z;R#7t>H7J@s@)BZ@o^vDZ3;4P040 zqF{s32>AzP8woOBJT3(1CXk~BDo0fm{Y8y3sT>12Q+fv$@+J<7-ep3E$HvYQ9NZ1? z#`hE1={De-0|*1oMzwd8>&RedfQ`XI z5gfTGc+i$6HpSCAS}07(^v|^VcLE5)m|ii|4Qg+x@Z7|@y)F4}gB6;hxHQeMhRJEj z-g0+?0!%?6bwNH>fi|skP>XB2!YRuhE%f{=`kKgz4lTzc zNH8N5CZ&~! z2uX`Tagt(Te`Kv85OT@MN$bfGa&V{tj!Y0+RUW!3`rFfa9e)~~Qpf`yh^}SxM~JC6 zd}k1vl&FA(+_u3+vL(@Cjrh$E3!cfO3+zdj?jM$(Z~WE*D?Em1S*^5}2uj`j5_~+~ zTy{0DXCdr3^<-4mIpxAoq%}W2?k~8gDyrPHp3oV^M`TDGebMKCO+{HV?V%+xZaQ9+ z*byJnU@hr1COIFkznW|Dl@!Z|A#qilxl>jDNK5Yd>-=ZE1oY8M_)M*~khpK(p5Jp1 zarb%*@-SU3GPS4N+7IekU{&qkztrwoDm(d-G0kTGym)3vhHDLCIKVN_BpzSA5GPXR zNUtk`T|mFTluJOJ-|`bwh+lF2>6E(uU7vNZ7D|JojeqH6V&k~M{)}C`tHEJm)q-b9 z%2LnfeW&v;sfmr}aXJ1Ztmf6kH3i>+KWpQ>=Br>z?f#)o;Shie)w{W6>qwE@3bP6c z)!y5Yeny_?1fWgWi7GQZQZ+?WHAcC*4LLzFJ%qcu}?tS{-Q;; zUCiJ`{zXOw7#Kg9V40wbRk=emJr*q z{MfJgu0e0;$cLq#^BO-5qIm(6wTNpFf*%TV;Ri(`RUn6}aG=EPYj`UaCKR%-vjUMC zwOym5udtmqj*$3td>EOSK>b`Ot~hEv7CCbgteYR=iivo6WBdEz0ZkX9^#7iN4%~_Y zl_6_iM$?j;5^Fu%H`A3!GP0M zuQeCo=ZAzDMkN#Cb)ZwsBUa+aeq^9jwGP9{2XO9-w@FX}{YD*r~~9 zcfk~OIp9z(o#{`IU`Xb)64Es^n16%x=3vg(8j->>cy_S9&xGA!m)wMQQ&x7<>FZbW zyg~;@$4zr}^MrVLq5Csyg?!7h8fA+1Hc2$J031&}y&0FF!a^=Iv{+(N%r`Tamx$m! zqHkgns7w{6!DDGv4NjBm`SOPF@Y6o_jA`}d^z`?h!AXi>e`F=Yr>SvwM=1>q)^y|p z4ufWGY5oC(ktgywo5!lH7v6w_4*dOvE@b2|*d~AU4@r49C~s~#AH3Th&tM8fJTjTP zOp@W7u9k37_pjC4D#6`fY7tS>EI*d(w^V7xPb=OKOnAn!&^183-D@BFXct3ku(j;r z#;}ALcWusXN{UpT5a#1c=z}jBuH-AW+ViUL69%hyO)Qg?Fnt!>-N}slAcllQEsxY1 zKhqAnu9R=jy(^UxFGCXVdR{!*Irc(SCt`R~jPQqZUhgG0toj8f3n!kW-e7Qi+u+2XxJ&)a`bd9ia*>T=;6qj**5^?Zsi5mUrg z594R`x#i63XRxqw`6{J&D>QTIBj1BUnpATeRclKE)+Zyf0)JafAsX3jj4r^2zU(}l z)gH{|9JT)a7W(sByLT+{msWdGZu>HW+49!U<4mG1pTE`8eN;1@C&gG;y!yQxx3Is^ zlGJqTQl9537;m943*9Od^;$ods7_O07A3kV3Q6V8bl#cGCeFrSOKqG@&v$7N5fN%?%2Y(9`Q&P# z79)SXO4~g&)YaD)7#&S)6!D!%agwr;yK%&HHzKZ-jE*jBzESh^^mJWsQ=oK8K~?ed zq;hc6WNLCU_FFXN#=*^jcn1ViTFn3X^08QGAW>6OW2uCW(_5f{qy7rNXRBnmm!<)* zSY*&=!^IXZMhpuL&SZ@_g!R=ILp0!3)VI+46Yj-xC$D%~NcT&tY5ocebkeYwdET>j zHEFDqRL?}hSWO}KXOVZ+?&9k5f}{q!3dLL+zr8L!45N1wg^`TiFBnglCO&OS9Qied zalGHt9wj_H2;0cX+rQo-q@RM<733wCT(AByCgko#8M2a*o}OIAW-M{7bs7#A;bAC{ z2Dr6M*d1Eq>6-mSFpw9X^eSoqAHITvtB-JiqNaiGQv7#;uY;OMU8bab{wkQ9@^g~c z)zZxt8pvFTxc0F!o6Q#yFBX}RgB!J7UT!WRtNk{3*N}Pui}eA9XK-xn206R>LvhbL z_buho5T_cTUM{h4!Sgu9@5hRSK0bgdlm%O@A`O}yTm^gffzZ)kvyd)hS+Tl<~fu_0OYfXhMHy2Q0Ww4n6#Fd8KyyZG&F z#eUcDZ1n7*qfT#i^i{I!0*2zXes`&;^IdOV1jghbEC zNQsH4P7=S?{;p#r5-f5Tds788^)J#T*ogB=EFS}g3M1#Ab&Hce)I|P&WPN2+TuZkt z5P}2<1VV5K!4llvf(D1+9)i2OH16*1?oQ*u-Q8UpcbB(w&Uf#9@4g@1W3YR$cXe0Q zswH!-sSdS3s!f@(3^PvFCuZ}{?Xurj%9U7}mVLFh_4D(aFVru#_%9!?p<)q3;}^8B zzdacF6^ODl*L^{cUZKuT*qX_2Hw&rTC{oWXKZ(oBlvQWWTAibI^JPW{v{Th>&gQkk zzvx6=9iWA`iwgJs3=!r3On5WsWS-NLBL=(TDunLP5MI`V*b0Z5t9YIr%OZ9h42nT$ zatzCatSs_{j^UvN4r#gy$YBj6tIx_<3946(dpF`cTlm{7(DdPG$$ckTcZ{@i!BS7@_S1KYm zhtjsF1fuVIY%11xq)|GJ_ESY|9$MYW1}{%fPQ+}2bxe55Zbl2dYQx;3=k|C;Jp<`+ z;ru3xb!8r|O?*~*R`4Zes7ls^Nt}1XitH*tK`5?t-;hfDqzmNzi}n8aQb5o@iCh|B za(kzVEjXs8w9A`D`$w+ICoyL-(RjbHzD3Luc7o?*wxytW_!vaCQjAAJbSNWOZ@c|_ z;gboH{iTj10he!J?~7B@!&ITL>lZb)Ka?*B*7}BLrCR3jjHQYQHyleG=q1#pyu48{ ziQFylG=jM6kX27|n#I+$=Ql=-zG8x33PJW*1wUi`X8NvdC8lXcrD?Z!;+}bOnJ*S9 zl2#V{GaOT8KdmT+du73LLBs|M_iyVlphvu|2W5zBvNv7%&2z{}a-94$F8?uee0(5% z1kby>#xz{OnWaOF?68qbGV7d7mU2s@HIPdeB>fea+zZX zS8{iFMpf>$WocN|hiW^@(b<{*%?0hT;n;v)trvmu$~?}B7pl|l@yN33!^SB0#jXon zP58tZtuipc!AtE{Q!A9M#t4xq`bXGyYVECKt-5ejR*6rI?i_P*_jk*$(p3iG1}IF>GgIA&^Yv7<#17m~O9$L#un_eY)RQ!QJ%BuX?|{>HaYBPkTEyLJHyT zj^bdoYuD;%dSb|4+(ruH9`3lt?Gmm=c(^p6HZ(9DVb8B+L94o;+K~1q)|Mt0HE3~N z`Vo+s3xxkWElip|CBQaj@OeTOYzX~UK2CEHBE8I^@7;;F=)6g=;AYhS zOp~gp*JJ+sI2Z+g4w{CX2~O&fO zq4v;cCc6E?!FIk}*0%Wo|B5arkGVXNG+X8&d?BK5($r8%-G zw_kXvje{N9YdSM+lXzRwY2=qq8T6@&sv7h4{+8L{$#H+=(_c-btn3r}0_3{}<{x0` zN~xb)-r-$xli(UuK40fOz4yc*=;a&8-1TCQ5<5!z>hWZQF+rxzKB2SC?BWZL{;Pn3 z>;x9{WJ%VZ!Fr@K6?KU{CDd1rvQUe&666^wB?&rwWIS$K&_j21famk53720;Bn8LU zd}-zJQ47c%;T?L(NT{~4ymqUfbpzNOKIFCDOwIkq^I--SobPGwgO81j7wzfGe0a_) zM@X0;+#q3L>%ncpYGAE+M2(zVmxx-3e=)o*({-&KsC@G%>vDZ8`39A%UwpeW-QJ9q z@H9Gie8-;pUM{K*fv~q$Cv4)_BO{K>)&%4|WQaZ03m23B<4+-;$YhU1U&nDk7$Pmo z%ZE3R$zfE~Ym{hOBEv_^USI6-;#b|;b?nD0sr|`$jFkx)_R}jifeY00>(}?OtVg&5 z;~ppz$FIR7Y%UDdAymdo%2jnvunC*sKEnH$!Y+TAnBc*obgVpnxMz26;-)m}X9v>- z7P?kAMsp4Jx1zioAtOb1jsy~p4GQ5sT$4?Tf~A{tmk_#w4&K<4)je zUC5+|Z?J_`vXEhJHqRQXrRzV{ql~nGwa|8g!I}Y&pnt?izMggmzn982rPS^-le8fT zS$wDbGf;|m=th|@_iBngw(2!edhU}&q)Sw+E$Hk*`(&69BGnmQ0~QgAY`5ekdVL@M z0VDB2_G>sLPf|h7-R}`;#*h^2aJ?hnHfH;uS!3)SyO>n-n%q!Bxst#j+e=@Y z{11_ZWGA^qKsLvz@*gi9R{6T3Ly^?fD#*lvPut4TR5Fq>Nw7VhpveAaNGf%}n!HdR zdp*?B2hP`tD8=n)9*io=pJxL7UfogjD7{2{9*(@ewfcB z(Ji@m)H4EcP>kVkF=4^^vv#J!G*qRc0(KY5cyzYuE3GX-mZeY>Rg8=x1eDS6zF4k^xfafe4p7|C{iS%)yM7jk$Z*U zaKj-B3Z*bjOa{Lp4EA=He{!rHUD!Nx<@nDY-NJ1n~0=r!%r~Uf8J%Zm-FTNNJqL?e`DSadkg+89v;J0I~;-k z#41A?Qh{`g0p^bcIr**R#Om+GOw^|jw?sdqv5c&Y z0Kp76%GRf|Q=m~*a|qBKlT%UY4@<@SWvs&vGKjXNiR2|U3F3kT06wRXeen&fvYgxp zVLw>~qdVn5E=4Oo$J_^p!u~JMiPfJ8S_x|pCUcealVu=+KRV>voNWk0+TCKDEzQXn z%1C_RV`qa@9~}+&UXdlT`5SJa46oamPtC!^E5)`LsdfbmrufK8M|TYs)fAXNoeU~2QnmX)?T=m~a_Ss!yNQ;1ZVD^z9`?SnTHeRaH2)s3Kg(Bz^7KD3PtFuu8bhV> z0E*aOXDd_&Z}zD#j=7T){J8&h&6Yx6z_U#olQKO%ygo{e?c3oa#s&h zyXH7-5US!ZA#0}FS>K<@9==p9Ali+=oS4{dszJ9Y7Z(2OwPsR2%L37Op~c_S0+)+~h*c1ma-w!7 z@(SNOsH5>u5&4ulck(9g8zWeC@Ceqn-Y!y3diS_WwAx*Rdrh0+C=S;lru!56iJ_=d zWxvK2xZTu|`w}d!knG8~=3Q9hXA76TF!3d)C)s~v8;MReeMntt?PQ-J=0|5p34U$& zN>mub?9L)YqJ*A)e0Wko~q)&awW%2dBlX(%jw^Dr;u{`a#%IQe$gc~Iu*c7cSbG|TOu zIE{;$mC!!m-;zzfj;n9&Pvq8SrAlr!>54R}b7UZ|60acV#Cdm}SIvEJ?bjRZMEBoH z2X;sf`K_?D`9ttbicF*`%HCT~Rv(kyXcb-#oIKU~<=D~-l0n}>bb^Im)JpCx z{m>1zrf|2Nwc}h(YAKOt>!^>lMm(8i?Rdqd*x`hEIc$>Ky0S+ec;D(hmYD&Qf1rrcdp2cVRPUQW4(_;ICC{tLCAfKiN>q?Lp)%@*6DXA{o>ol4V^e)0fBrmfeymDcUOM-T`rQ1*>cd=8s|4RRPOV7 zQL(WmDpcge1OyK3pY}wi%kSV}H?!doy1OQly;D;visT=$(S1@tPpL9|8j{mJZrq)& zxcTr?vt93~@TDRG8kinR#7Og$9q>^cGD0cl$RcOU$C;_o%zHWNmBFOp=U^-))`m8m zJzsY&7D2)!U$hADdL#>(aU|0O8$QTM`Z)ntZKp!dNBn|`I|iI z#s(4-jJi*!o3D>XC<6;H>`Cb;CS3RulqOa6)Gw`SOmJh#1MB`SH?L=(Dn?urBTy4w z!ezkaZ|dUzLQU6c+_J5pQh&hT;fvE5$q=ap}rU@0EMY;4={9ihxye<=pu3)69BWs_XIO zI}eV?aMy_Y7FOEOn%AXa{Ro{F)*PC}Sk0#v=wE#2%HQ!OLp)a1Qq`mj{06RO)unrK z98CqV#w76h9AcfuvWA_0!w@V>ri&U+xrA%m7dW^7szrQMRksKh@(C^FmR<852DopPtt5U8ps2qGKmS%8O#O=KHbRyZj89rCc|K= zN3lF)2D)twclMFtb;_WSDzM(dpHRN`e5X#wo*WIs-+4M#wQj$)wIbZ|cw*af+l6Q} z8^G#C$#_fm`+-U3vh%Q_hFQrFKR}s7u$lMnmJzWYzyI$0%6a?sQLMcRJF&+sshK)J z(*ljoz23e_q0>)_6}7#_W#_<~E&R5N@ezO%|1oB)@iaA5Y2CDKW93zMz=N)!8mZih^$gc5{$Px-l(N>PlqS!9E^z(;nW~-%)s1 zs$c|#J~bi7KUqGxb$%U;S*mr(!DrTN)THAafNIOp7w36~knC&<#%(Up)2yhLjg{?G ztN{lU!|qBE&v*k2t&L~Yc>25#W?TuLt1Q0Kgb5tZ7qAIDaEv=u47K(&Q!RzW)&9~e zN^!nEsitxtAcEPfh2nf40Y|r3zK#O?sc#>gtlU4-^5s)sV)zkSC$g|`Z?_WR!*UD! z`WLaj_y(+t5oiM5HyN9GjX4MtxT{H6uMgc$f+~HBVW8;Jce;a{miJc!zoLIjt*Rfs zj$nZx#=JWcZLbzQ8PbS8G41DJ6vGs+cr5juN{R_eTLo8Mo+Z6=Y`9m!U>P zfuLWcB!nOz$F)~FnR-}S-2A}mYa`)ACU#b$5x&QORmKi|BW2;KmocVn_peeZDBA;7 zIS>vzG|f;DCJ5B@{ks>78kUS;wh+OOidkrKv6vA2ro?d0Ogx`tY>RRepNC1?eR_Y~ zf|4csgD>}58^|FD%w~o};-`o*mtzBO&Y{;~+n=1%@heUwGsY9>Bkbxe_@v`aVRf6} zf2Y~`N|8-@;1o`iAM)Z5`G3&9ozKH78RhB-nRR1XS%Q?P$5=prjbAuM(pwWzS#V1#;~7DO>uMh0RcbgYxW zgG0d{$n-FmO|jRC{khO`44ZV5g`C0}Pm7`{SE6~2dN|Y_wZVQcYU`wY|3Q_^=IUc% zE!YWL#Ixx65&gul$soaNv4Y7x9$@@WcXMtt?1l@kTyARqP=N~Wx6op=& z7^rC9BqY=v?b*)Pd-%V4oD-bN7`>%Xt})TvnVVa3Aowy>$3^E><@;@C)lPlEo$<}w zXvNu1CnPVYSMuqqPm7V~;q1k5?R+PDgWVvBdyeR|+C+vG+DCh1h>q7#i%k^0zUNbaI3LX=p{M5c!s*W-!N1;B=A=sm7`U% z1Evsqr1c_@<3mKFOiG$LXA^vKK>hYz5D65xIR)9USqkNGWNYGO!zqP4t~_lkA&;(R z7W^y9yu^6ewU+Cp$NrstxA}9Z@Y*pM9*yS93mnE`GiF7)$Z}K&xZX_YVAq;j1%<%C zqqjExo6z$!hf)Hs#68fHhW+6%przp)pFaI<21@sJ|4#!C@RaPT4k3{=3jEYO!4K*3 zHU{by3SJqmo3o4x38ffl7Y1u-SbV3niiUU*_a?sHL{>r-=tvm@0bE>5QCdrlVN?nz zH)A$81WjCayhBe~9g4&DB@>MV3Bex`h*wCr{F*Jxy3*Xua~?f6RJ|F{84kJ-tPdK= zg_JPVHej^6SfX%1nisjE%1vf)Ltx;rv7vT@1ZSyHEXh~>Wajc{5ghE^^LU8a(GR_1 zyspsFros!vqCkbXYg@_1BUA&P(flX7gR(>Q)lymBl(2uez7ii%%;nD)@SYY=$E@WX z&fE^Aw$_BR+)uWnp+qh7b9z;FDzewd}e~?b*_hVstDS<52xf7`_kH_zc^(mV3O}M+nv09)koabX;Kl4c7=Ke zg0+x-9ZJ>kUPN40v-txz>RFI=ka3uN(z(hWQ zKp?kP6wozxhE))l9WeIPwh#aKBLr&@!W7P^++5Pq(oz6Bb3kspiU2HrC6*3*M`R%V z{>J!Z4=G?xXORm;Nu^NUqqiGzEcD|I1<=&m-+3)L^qEo2%3Zffilq<&tIW{%N4CZM zyW`njn_j==SQAmTDU7?Gjp?Aq3;32v$ zM!8;p5sP!5W1SrkZ|R?THzzf@`C;Av!R3p!G8GXd#{sdsi#8+|OpS}0@m>2=D4SPX zUvhAoKrMp*z!VH&kZ*?F)B*X_&Xd-}^eY;&pC~+V4s+4%%)73i3dCuqQ19D0NdkycJU@lvaBurZy%oV<oMl#uUpaWg7rO?CC}t3vB5h+-QmkVdLvI8c7E zJf?&Q!VDk%8yfrrMN*w9F>K&h?a;W^Ts^AJ(t(8996H^Mzg&1dRO8X4~MbRXy zDP1e=R(#)ZWkpl)qfs3L{_UW4fb(8nD))+c>&@V8BQy=yeP`S;exs3-RNQS|vi?IO z*}*463aqOKw=J~s1N|avek@RE&cw`fO3h78ZEd%RzMzN*8A$FY;@>IQ+1sl?hDIX- ziQzO+3^&HxJJ=A@RZODl)<~w(`^D>&vD?&c&Y)XH{H;-*TTewNM9Xn9f`6*Dr1-8I z7Et6(9un)O%r4~W#l3b{3{A5hsJCGi+mtWW9ecKeKJzr)<~v`~|Lu;@bj^1*GPv_p z>A;e(Nhc?hlO-rbTBcUNdv~6rw|4UbpJr8R5#wH#F1hJoplQT(qj_uAy}$m_?uCUi z^oS%ttPm_-rm*6U@MmTw4D@{YcCpr^uY85;9+FU3`gB6YD)Kz&hcp2+9lDUc)$$Ff zbMbtTB@yAhMs;cGu3>A+hKLiI?Oq82rS|OqK_TVk<&lDgR`f>kvRJRi)RNYl9J~bK zZ*2Az%w~Yvy|Q%8>mRM~bQwwz$^D@5`x$|549i;KY#e9xZRtWQF}H!-gsxPya(e}HY00Cjhpmrjm{ zYXYIE{H&)&a{zR&D6zf7iqqAumD*PrusGGCLqF2lJXxa+Qd^*?zMbE>Si?GLRKLyg z*h3?6LJQ)zP<^4vJTHB&x2h)jK)bvvRO87znVeId9Mw`vI1; zuz26t$U#b~VesnJni|3@y4PRMY)ROAL!f^8$~$ca@LGMR#>K|M`Q9gFOytC0oN)VR zrKN1yUBgx>;&m&N{m=9yk%Ot@{zXOI29%X*TzsNxpxP2hq@&_O!o%BwvB+L5RAANn zmjC(FEfURh%G+#lsn6d}g=%OqW!`=>k=Du50auIbcf~}!`b5Ojb`4CZs)lV*gr84P zNSs|>8~%DF1^_@c1ieQfNU@87=%dNId7xovLC@xB}h z0)=LxP+q$WK`r-dmULHJ4o3&|lamX}nG`J^*Qxr=_QSsp(g8DoWI7%|<5-V%Y$f+AKkn!qnQZ+cv%q&kF4G9y$rE2|*OFK$v@y&wP2VhUYn+@Ea3 zcqYvbn0;z}># z;z);SB~FzDsD?`ghpfAv=55O|_=ZT|HULPAJx!5pn=BJRasMfcW8>t`e@xS5V zSoQTd~4#av`lg%-ukkGJ~lxZ!m=Kcq zX;EwTOX6T)Di`}v#Qan+K0coNd0NBasV;1!T{P~S>wOQ~KK?@5TEmkPx`dcmzK6SV zlii7ypnD9?|EQ>*D>q7Ees26PcBS<9w^ap>Cr^w;wiGRlt^31DA1ky_*{#&#NB4D$7j z&&msn6u(zIvr5OsmgfJ3uo~`9S>EOa3+pV;`O=Me`gux)q?cBuGc-V8d^bNbI`2#6 zrQS>3FBp_Cb?^fm`gktT2o|}A{E%@#wUP^?#!fo>YK+ z2r2b=Pz%zYxX-)d$O%dF<4|6nw{fChTk~7{VTlBjd<+qwy?DX6hYn6Q#7qw?eKd#E zp!8Axr9xDu^fa+VV;}w4l>}dEb(qC)omHx_@eY-o`dea4OKqSv^5gBP(xNW#QIz@+ISx)!#^GL}W1rCJm3HS48FZC?s9`p;{27D!j9Uj_aA?7R?1 zoZ01~KrikZQqSY8!M3DJX@?OZKsMx0nCar*D|> zP!tSO1tF4fI0!5g)L)wo3^ZmThj0pIRO|uxJ4Qyv%5IplvQMsDuFeV@It6uI=t#gt zup1enyGNP2>W&w^b?3+3*TXzUR8TwA(=*Iq4~2AM_VP0FYN!z*0*4_-6C(NxyEKd% zu06hzTHbsxf?aUbo+AgV%;gF&$ zEgE_!epd}Koh7aaK(z4E+2TYUe}G2nQ{qk*gWa`{?^@W{;{o;RLcI521s92Aj9oFZ zL+d@Zt##S@*E6(L;C$3?2#w+E)B z^QaUc9wFeHIUMMgP6U^CNJqMO(*#H~$p6$o-YQ$LMRq?8u-!k;m&4Mh@l>isvGKkV zbUWW|F1_0)+XXcxhov~84_UfB9cXp+XVtd0JRN*dN~2!IQcP-lyc*jZ=V~Z;Rf%~~ z8G1zHH#57J)5X%Ivtp<}a+34}vkR_>paAEZg7k94@betLmIuUobukL2-pkj1`;&WN zthjwr#_re#@Ecz)KVha0D@_2KF_j z(>Ou`F1y~tb;GuQIx$yHn zEZ!Ja-)Pl=%8t51t~nDC&^z?IA$e%Zu&;FtBy%z<>=OlD%(jpcH-$tx{5o5G+KiX7 zt;-!$y^qmB#h1tB@MaIe`MJ4_be@OJBL$Cxp{kbB}ibI@gJKLz}k@uuj0FPLvioaD~Q}XXlj)Jry0yd&-w0wcL}k~RcMotktJZxx_Tt18sbvi0Zg2gh&mV2P@oP3;Pm{N<~r4mkK6Qfw= zQRl^66q~Mj5sU&DK484?ZsYAYEV}4oR0SnE-P;=sy-lf_fR?Z+W&^8>+e!Q2lXzgm zz?5W9sHnd_r2)g}d?b1bI8>dJ*hKLWlr5P7I!eVBX*XgsRzo-NKR{>pG>d&5Np{jj z@@?dV#>tHrTUR)_iD(Ybc%LC?nF?1Um>`RPy~kczZxS?;ve0VBOJvC{^v;6$nA!i^ ztH$snUA(kvk={I(@EV!Vk%sKTvfJ_c;%oq5AY+9AH4tXpsf~EJ?_MZSxu}YNN_iDz zZ>DINny+dO;~x!#-)0mw$ZoJ=4Gg|zt|yoO{+GB`rw+7>Uy-uHtWZA7=&4BHhI(17 zYu(;!cQCK03@^3+d{7L~h{SAGfEGD0fck3O271Eg77%H7&apw2mDTG>(E=NHj+z=- ze*XReZhe2hJMWHN9}~EU>c^Oygttvv`FguHuW`XHRIDZ3b++OE4Q^{{KqSO5a6pZR zcjTP4@fO5PgK^feruPS_^-Y+3gW@**KvF*25X!?nCLOtM=c51QOs0ZXzZW?Ijsv*Ab(qx}#^OESs8Iss>5l@tu|Gxbt2V~;9J<3}P<0AzxK3riJ3 zIg@A0282z4?QUYK3PG@}=|7;P5H$N(VC?k3@AV$|*0!}{3Ye<%Fmn6O5(dz)<9hW_ zXnQ_qaB-Y09Nt*bib~|vPeG<-LwHYMUrRS!uRRDF%WaPMX+B#26*muEYX>K;qMki&s^LAa)Pv=Y>7>LoYmcyV;Jy*^2E&p-f< zry~=j%btgf*;#)J5hZ2;vL|bR%Zz?LiaSS^{q>L9EHC56RXwd8D(KL=c z$4{XM({!4(dKT?^9)vGj}lh)r)r{7a!{YnoW{*k)G@TyG*U3pff94oAd@q&EH zH$ylxu)|$7Z#NwjA2sIQy}tgDwVgQtGl3-O`9-pG8qw_00jF7hWuM;Soo1_o6-1d( zvl7OQ{OlA99zD|CJ45-k|64MX(KLNBhv3Zys`IAL#a_Sbk-*CeSLD&u;oZsH78+w} z0KEUEQPI}^Uc~t*tr4p^;^mj+e(u)rQxB;xR{aPra7|f*Jl%aVbiW&p>9w2;kx^=7 z&Mpryk7O>gjtdcyEnpt`oKjIyyXN1nO^hw5Xy4Gt8LtLvaGdza-s{N-lC9 zi19SW@ZF|$ltr9#M|Vu@*g6{qyhqUQRi_*8VDX9Jt5{Dc`5uZr9{{C{`LJp0Jha8@ z1p+akHHeS8S8!x75u;U`Z)^tlsayqAi&VW^gs?}v^3J{st$HuxJ{o%VkyScvjPim0 z)MtQsis<)Dw9G<0p1`Zv6!!Ahl$8*}^K&s>?a|eNzO|?C%RLyRznbXyYz|yL^N@#S zm6^gVttR$VU)txOhJl>WTV1bp&zq5ewu44uEl%#```ru4-7(DsRqDh*u#hQ2fRIa|?dVwWs=~7BW?f%e3%S@W zMNy{4D5iYVz4`6`myxBWp*d}bO;{vDL)G;tF^)KAo;BBBA?$jBQVqgtRD*a%YDuPI z{8-)`TPUW6N&ah$S*y4EQeLkkz+A)5Bnow)e_6hZBY)SknDtwt{BUi(Hy)E5!6A4Hv#0CYH0rya}5MDJ^OJe13C zwqxJb6{^4>(7o7A@;z%v;XVrQh8(^h>Pk^*a z>=eS%X2bm|=*W3U(v-Day`G-j^y5-$%*T8=Vj!4CjGQHC{k+}P_aXBJ_-}QWoXIP= z@q=`LX-gBR$SwYET(Y_l%MO>^7|*kUtW zXqYb2<;nfoQkX{)((gn;FP@I9xX}XkMW_qL$9LN`uQnIc4EmV#Q2SY9GPMhsHu*MmLMVKO{L?`9Da&Lv_8oS5pGxV zGAgr(wEIn=j;fhExtvt!u-o#Xc#-cPs=d&$!M`+F{lCEqefgNZqw%=~dZ7HSu(TFK z=;YV2AWs8cs~y-X$Y8ZNJN)D@5^YAykNiy$TSay_|IHjRAa;iB8qumj)?1xKWNvB+ zFIZDCzj4@I{#bs{=wNTZRYYO9wRboc&&OKjzL!Btrb!I&=lnZ}?E?3OgdU}VTEk_> zq~nj~G(7srRiIa$2@e63n~^b3acI>l@dB?+5a0zH}UWJ$QP__fpUqVOpx(n3uckdFD76@lH9g5)MRGnN;&b&o$YD#B=Z8^{`8~eEdC^M|I zFDtA9IS`@edM_3}H_`9kH8ttLn9sd_Q>6=nzRs93UPYzy%0Gyj*iP(;ntJ-HIeY(m ziE#oOAg}t&V*Y-vJ{tZ{o)8MXMgHzRVJa8L9mw z&X`ZjsPT~am;!o9)jT)xR;O&gYnsf{q;I5XH?*HNsJGA>P<}+WHebd82}=PU8jwWv zMZ5ixPUtSpy5OS!ou%ejU@qN#{{X(K9W)rA_(O6!*V`KgI7U!pxUaF1u%1&esS++n zg7sU@XWN~B?D^3QYpUR^2w&ysoxg%B5Qt{DH>M!}Yy1H|6Qe2hP7yOrA`|;z) z%(=a9A(Yz(2jM?!wK>dBm{BpdK0uaGOiD`WQ(T_!?!XI)pZu~~Qr?wn=MJ$JxIEDJxZv*Itj$;L1kEW|62HyM`n`_@T z^enG}TzOC&=LrRKlx03@1jXku<9RWcFu*Wke z1JSomCfwGGM?sf3Y|84SzWtXfq?lT0G5f z2QwQFnwz4MlCqGM2iE}e)9%SQg(~83pk@#(V0(~wxEXbP#F6$Bx4)^s%Keeuoh%-s z`K7P^4g7q~DZBs2*|*_GoPUa@nmL?K7_9@?s;tLUgW=B#(pME1mA-#5L_OZF*qYD? zU+Ifqd)Zd7@qkZ)ziTU)($AWhcKvm$9jm+y=-}9E z8yLX(-M=lgWaOzRYz4Hh{O<1?B=x@RsVV#e+$^5_cU?OuV`uJz&YYk1J~{oj%W{Qc_cQPIhj3t$^gTtTWIAmWiU}qcbZJ%4R>siId4k z&e(kV^a)Ud14QS(QZuLWF%2|+`ay(V*PZsC5}zu2v(xg;O1Vf_3OW{64luhw;%GNZ zN3kssxHkX*$il((Bj!%+#6 zNt*Y`mRdsagm-uqb~axWv3lzMpsy0BHui7yf?b3R{h#Q?2z%1^?oK5*c=)ktcYohE zt&D(`kuzs@XlR6titDgmlna=OzoyBm;4k*N+ounRo3+=Vvd7YuJ}D09%2Pzg#`@;v z?Eo=1qMYV%W1}42Ljft+7wkydp(u{7As~jXkzM`|C$WyF19Li)c;H)5wO07Q=fGy$ zFLU#-<`fDBtn4^p#ox*6#f!3(|8+{R(6X_?Yi za41&-$U03iQm1;j!;M#rL8+Qx_h>e?VIo(M*2o z9i<9{swh4w0$i&0(!;r`GQ$#Nq<5NMWOx|Ac33_#khiv(yEmRY%z>WQyT`s^` zoP3&qMR5()c{<}|R`|3`+c0Z)xKj17Si&##Di(UGeO{{%oN8>E&GA8DgK%}BoB!#4 zG;RG?gDnnau3Voo|HNhU5;$tWu)A@-;$Z(qWl`Ani?VxE$*SMe`@kl zJoEsb0gcIui&q;4M{k-sK&4b9Yg}ujm~Za~Zaj-OH^N-?e^qY|c7MFFdJ$mWqZ6vJ ze6{dUdE_xyYaronsk32{BU#?(Dx^y1=u>I8gAQ5s2opYa@9`?R@x8$p#M8fS?y31^ zzEn@jkAo!;_^6;}@=kh`Rz*eSYsi1xfo$o@%E~_j3x2iJAN3~)YX0B;C11M)rrAYB z4a@WMD7*Bh{a=cHE_@Z#w|7b$SkYv!bHfdpC0HN#;+v1$lHwx5vr~8YfRc%lvlg2q ziO1k;QPw)Z<(>$};}01a2D#9GS0cPhzjItH${D{=>)u*PWv@FVor5wOA{l#*nFzC) zw<#p#@xRUYvZv+>Cxcc?27=enZ>UU_hKAmX#;KeczJ!DE_T~|Ws|?{<#YP^}N>?xH zZ!XXo&x{wMz1LW+#ZhaI`U*uHNKYQU2(0yQvm67^O3Twfa|&xWq59EYdDwAwalN%U zUN=sKAJ&=ej=C~B_CM*Dqs7xw*y$6Pc7Fdp9QlYZFvH^|sX4Iz zgF{11GE+O_C6(7UxCIcd#n{=ucGmZBaJ=0X@7!Umg7<4^Aci)7d1)Z4Hbmo~;N5JH z@0I-yw-;km`AwVxBEYR2ren{q?EfA|=#+N_0rf^O#yMRg=^hFk;E*5G#WH%t>%W06 zBFNttg-kG>(Uzw6;YdCrG*N{SDKsq3ln$Xe)wVl-M{p@h()ctWt&HYPcPI3uH- z5tiTWi44fR{HrjoYk2x63~yoZ_kXNL;S8YpSE#)f){=@}uEnx^*(_hC-XK&krK6)m zO!9YAgr`xcR^;6WV&N=JE}(_D1pLFOf&vcxjS@-YEdiJ1w--=^}G) zbB1#0E~>3RDwR;IZsi5}S0g#UT)7^|YvIW)v;?v05k1CjIfvmq4bu5JJ|A<9)2^qx2&@r(r#NKJNlZfaq_XZb_{9Na(^n!T1$ z%_pG@KGB~x5EMtOga>vmoHZ=|pFh7~(WX+=s$NFVKNm}-AncANMWm#-ij{h}vl;MR z(k(Wes^nXYunYf$b7D;sYWNj%U5I{j@kp+FL6F&logZ=dJ<^`iFg%sChcnPZw}7cO zngdo)bX3o6?sKWUw9U31+k|Ct;UHtvR@6AH!eejDSFaYXWpj@UFR zk93b|HqGdvQA|D=w$xxy`6dHc^R^9e=uYCcbA_&)ox!e719tynEr1h2uxxhyWW$e_ zE&}*e-?}am0J_{pTc9BE&HvF?R2SiXBwMR^ibutgET{>oa_ctwvb?!)cMwDUwEada zsXe-eIX_^)&Xd9Pb@XU2Lr3i6{w(2o>1x7mYgkb6sFc-Yn&D}F^npkY_CiNm=*lVm z<1wmA%eoxzqLnAo9FN4{CMcutsDW>Ni|wVOmROj? zK?uPTEI@D#7Cg8^aCi6M?k+(B!QI{6-8HzoySux;MNZDS_xAnu>+#0u?hO9ed+n7a zpH|J9HEY&8L|?%{uX_*1B(|mFS8a;!8cAx|Z7`R=B10NKY9vN0XWy?I&8;r%GedP- z(^Nom)Pk#zsmC_2DRC72BIIXYV-q`vu*_oyo69l%*v?3_zq+tkXGce&SW&~(?TrBA zQ%&XLMrM3}0mJrexmQ+BHm%ztAyA4HP_EQ^tP|GN)wjGo<<`5x2;-TgmgYNn^26eY z-Ps=2yPw79iz99v9j#QCrH5X)wY)P1sB7Pj&ZDu0ZF8)26(gMm_FMS84gFTGa0c8K zzfR^%QK;I5!Sv+V2GAQ(n^6~v&bx$ijp&D4?0}Co`UMQ9c~BrSnc*2b%(ZBh#d6Rn z&)!v02`l9{GX9z%`xyuctJ6z`J=d3t+47~uCsnDQ&PPp9lgF!{UN?sf$BWJK$)S2>p96cvBnDtb0fo6=k55e{11ITbWlt$tzi$Ij z<4hrRdd19casR+TX<)su`fVr4vRf#08S}nWRWmfByS}G_-5s-F_X1P}6k7v{LR*Eq zWmC^&NE|L%vSo|&=^1z7nmRT))Rmw4WQU&}u-@0kGSc1tWMG$Z$E-|c=_g1XCf@BV z6mxOs8V$Y!zHA<{i7k(XOQymRY)4vAEUGk6f>7#Ttl2DCj`YzH7ri~vN^i?U& zN#~sFqI_q9VT93JW(s!N9GXEpbo3x9low0ZxS!{7=IWYtGc!EQ;LoNJTX3}MklI#v zEkEQ0_{A&m9;vu)J{BIsHm!OJy`(W>E?3(<>qlJT8j*Q{0x%Dlz^43KAu9q=0i?G2#a^S>Xf7Rm==)Qig@O3=TikiRy$)cyCkt`fZJA0INQOsGFts<6_G!wo{}eqdYwk z*{C+V4aA&{<66&S2?aR{eFRB2<0ra(aRr>oQL}NiPq%?Lt@Au*oiX+rlu%~-f=~Av zj?)eu6X+T4PLU^}+#{s#{l1}EPz2I)rsBp1>7}{C)^b7^h;%pN!zb_{JQs zgu$tDoh;h7Z6)e#(djB(?d>1fTwDNSUm;@iZ>tFr085ZJcOnxLd8e-q)EZ;*i)1MO zFkb|-)f&*#L|`#k6q*X6)NhD=ATVlBF2g+Pg1 zup?XExslR}f?FS|uWRz!5}lcJ(9zI8z4<+Ig&8C@keV75VsU4f_wR4d2S)maTbf(kNT8`?TbfgK)l^M}i=0!hXuikO zwh|1-`)83~kk8RPwy?fqn|P}jiq4L@#wVZ+(SIqgV2ZqA0j<^l7*b{dI>1OyhD=A& z{uA?iE{E`i38vCxCY`K)Ey2yrj8grK6bg$u+0q+&-E5)=JIdq%R)Yj42Qp!8dCGRX z1094ysFnQvLnOeow+nv-8wv^mEBr4L(J>65*y#rF;2-A`+wKC?F3HPJqu^D`&2co$ zFvXnlaZ71zmMOaO2$b_*2g@@%k?nQYktD}5`^3!+%~eLu3XkbeP=gq?xJ<+&<+^NJ zt=Zds!j4A})4|mszU(YnDBu11GJ3SG9RSO%g}wGmIz-dsTE~DcQxJ*Yy70{o=i0_m zU!5-_m3pA4i5IMMgrvE4kH75?9N3QBLk0c%VjcYbph%L?u{mjm&-KZ6#uozLg5>u3tK{4QDfhFP-m=<32=60WFIKE+>$!i=~@~N zp%#HNU&Dz`cdt%A$j7+XrfgBev{CL!GMY;>>Kb#Y4(9-cEyN!EHT@M)zz{|%LT4-$ zCc;?&s?0<7gi#4sf5Fs&M<&JHH&_}fFvq=%E7zC1LO^^-zo)z3M=r|lx>9mhi&h@B z(Ovfe{Nqrr>%a|ptDYNy5ECimf*JOEX+<^h*8Y@ccN)jlFMvKfD6>0$LLe$N$m-En zM;jYbLlOnN|1TEb!^ z=bzyZbdB^tFY?a}30ec^g!xe}3l@GYXv&uKcIIqF#-)_>#ru9~Dh>IVCG=bft=nz6 z$0n7NFF)vGncdcEWMuRVn>(N~)_3v~64+4Imn+K3@QV1ElL;CTFfj-2-j4yk7{X#2 zeoKp+>B<>Nk0h47xkCPfR=}@)Yc^Tr0x;(<`a+7X;#}Poh%5+KMA8Ovh-2eHV&?se&J_6WZ(SQ@XD&`urrbQ!I#N zk>9jn6VqghQ zN)Qrr)Hnu&js!evvFnX!2sLC;Vhju~AdG1IY2C^A!A$qa=Fo-5=oIs5&+(I_P6`0 zP2%AXp99YW01NN$C*xBm1{QbYFpX5jH6cWNz9CWyim#<3vOWM(E+8xE>Rd?qJ1A*}%@E9d*){~ch(Q$+$V%0L0&rV(m9i$nkp57Z7P>mUM(o?BYk5#@0c z93CB=3^3#ayLee`EeUWyO-ssV%AxY#-$C&&0FG=U7=ww3iVDD-GP>^` zAgzuEN%iW2=BK&j|L_H>WKf{-kEH-W9US~)=wg8%AUq0q?1uDLWmR>p5$r$t`2o4j z)%of{5y8F1kyn5>R}xBE@l_wKBm|ov8Xv^|Xg(k2@4n0<`fp=H=;gP;Ti5zqRPCRB z=UdWASdAck_d8toZ%vu}idOyW`|Bs^T%o_!yZ`xRlC%OMHZO8e**(4HN;0}10w85k zP!#J!$ge1-Zdv<2ExwZ8RtO6KriC570`xt+caQ?hdo{Jcg8ZCc10)yBq*3JQ7 z?ZCYNwxXt{dr3|XqRko>z_@Cqj${M0TLJJiIqv;VT|z=YX{o#LoLAYOtNz_=ehsf+ zm(3vMia*?Vs!UR2SJ8u143LwcLsmvKL@BhAG z%&N7eWmZcerqexpg@tZpY~rhM@T&^5oy4E^CptX|LS1AV!(Fgb93XIYoGvr6>dxjkbSxb zynnJn1)DaBr5h&hPyHp4yc3AF6;k7gngGO9W+3!x8F_;)(3fyov-@aLj zEiUSw+7D#N`Uu;$I7=?k0-m7ArWz zntp)Fu;KO5$`HIsYp(c#y|-_zf;q9VH|BRpyDqvNw1ZfxZ(|Fk<-5(L%$8FrqbWLu znMH23j*Qu63o&m$ZvX%|ZUq2}J_yvjKK1V&x0AUJHa$E%0?>PH`O=i7H+rLgWz!8x zy}|(@AwaBARNiL*Fb8C_8~CmBIy%ITkALNFO(<0zgZRQdw)VqD02O zTz>oU?r4|(7+T=wK&(vu%>#87I;LgLMV&jX*`ekA-xx6MW3)vp$+DhGqqEw3oURRc z_*}vFkP)G&gvy%RA3;VdW;*D5{YjRnleYOWXRQHvIOAp|A+5P0@XEa_;YKZe!^v6B z{a2OMp@`XVl)-a*$CgHA%=UMKFFO4lFmhD{IBNfn2-EXwo?V}}4=)4a`v;qwo0dd0 zo^IdoZSDt2&(E!+#iKH3cB1d*mX;#Pp<@R+agdjneI~2#9#&#{Q@A&iZv9py(0Rep zlO+4wb3P|$y+2c9@R~-g z(!uU0YGuiPeBTfMfF!E#Szc~^1g;fp6Ea)nYRDErdh}FQS>2T`ZKHClY`t5g?VbSp zZ9VO}P9KM$dvk-U>O~Hswv1%kmV#yW!@LgilgmxEMXWtNe32xeHz^aOUcg;=e2X}8 z&AWpSI7Yq>Z4*_^X)QrGI3e4oq$Oy)Ol%O<(Y3YIfXrQg8A5f+tB-hoaiQn~;uqSQ z1+#=yVtx!b@IbITy+Y{Ebl-n1rH+N2)GI{YQfTY)PZW_y0B~_6vDqXmG(;~xP}A0A zSK^~w!Cj=d`v!wZw0P4)Wv+OSd2bShm%PjAiJEaV^F|q^y{*q4+((7!%dHRFk!;P4 zp=}LJM`wD0cx#U~G6{ugyT^EI8`t*e9zy&5npUn}(4RG(M7OOHhKh+lgJpyvfyR?H z;_|o(hbdK3Gg;!Isc@5pA-yN6e$ZGeZ(-m6#?eUo6+T8=xSOowTIWWYF9HW(zwjtE z=Z>YWY|dec?i=v1sHonb?{}chrke=uTa71(f7IJ-Z)|UCAQl3s_uR;1;Puf-cU5|> zP(R2>PUJ3%X$6k_FAcYqs=(d#R8=7LzYgcEa<27uudqy!*Dj+yD=&FG?-$!mv2F+0 zU#we%f)ap3I_Y&LD;OieGOGZcA7q~I8T6JacM;^gFDP`wTEuy-8&o1k zW_8hT^i+Vjy`;)$&6n%}8Ql;Hm%%IjgPYHc2DmsA@{3e-fQlGG#wuhR zJ>tLS=D-aMP`g7D`2_SKeBp8B6iPvX1bsyQs^!q$F&iMILoFv1o5$Oz;yo=NRdC2B@ZIJqZ>>J*o$TA97n(S z9FB)4Ki03k-!QrLk7m>9wYwyu&lBU-F93jfu)lzLMj+M+STX?U_E+EKMFQV|h@O*E3Gxhv$CgDV4ZL}^x;;V#S<+>tqQ)-neYgf@~moQ-9j zyK@HDmnGS%3drc}zAC?Z#41IzyTl*YuNJIZKZKLfreObeHf&jbJgel+2&A*;%QSPQW=1`_n8@Li&{ zc}UB~kB`AKTuCKv9}g;Y=~zM<^8+-4KZ~4q9zWo=bv94xqsii63y^yhqRyTl6%J~Y z<0i`@ePTsclu4&mb{SF5{PBjvS%BsxU)me_v5V>CG0+IUwF7^`d(w>cVW{WPO<1(k z&zv~3u3)d8YPXjlv@%gcZ;h?HClSz%dKh5IDk8`E+($}U*XR=EudJd1#MI=8x3|{r z+KMov5)(W6Em||m%EEvpSE1-J0`MIBjTxv8`nm0&Z$GBGo?>X8NOB{M|8(O9fyK`-kDO!%8zk7oQI@;~EScvF50#vZhe)4xms&tRLT0;j$&7b0nn6PJe`t z`fnJJ)w-vnBXV`sCyCjqh)@B^xC8lTS4E|r>(dpg>)qCluE9!|gRqpQfMg1vWEZQ< z*_gj>bdY@j0m1uAMK^=F^H5P7^46yay~0dC%0^PctVn)N{{_(lD%EEq;CS3gZ6}C< z@W5LGgN+~G1zOrEPi;RVHT*=b(GcQ0T8i?c;&$BDSif9eub8HXD!DDs zPROfE)IC5dwE^pzitzFouQK@<%FR$`@b7MR%qyO7Gwun0`-u$4Y*Us(r6FZ2Fg3$h z6vB7fwS7K9gjHK6@ypA_6@|MN2&a+z`OpKV$H`nBHTKG~=J`|ql`HGu&!WV|+~Nou z+|w@2K4Q;(=aT;!037NMSO>LXcp`JTe(qZJ>^MC?hgbznMJkOZ5RckecrZv9tsPCa zzTRFbQ}yQ8cFg%d0`=UufZ%sG`!j`2cMbIdPTO9qpG0k@Rw%wV>u(b$CB8CM&sEg} z4X!gQ6K=mKR$Ue zJ8VbMstNq|3b(2DGrE}Q(Q+>@uq40K8_jL;$8e2BRlZ>N{6Yd;Kw&afxYcowZJ=^! zYnTS322#OUebutoTO%rYQPuTlKp>b~DbSKt&>o+WG3Ej_18@=X>bQ9U7ksv5LlSWA z3KolG=H`@v`UW`j5nvBDK*^ZT^HsqhdE?K8{}cMRa`8W+fBzN;0%>BSbrzDuV2zz5 z-q?g_QF0$;7XNm4U9nzUex0~(SO2)n;)M7iWjd@Pwky>l&(^u!&x(4K4$pVOWLe+L z)@ZSI2By3Eg1#nIQoxn$$~C#}av;&w9mZKg`Rm(8M;+y;bT?n&pj{O2WFo1!u01bB zC}We6wV${bY;v~=;-TDTQ#odD0W9-182Fn!px6@<-j4v%Xn!OJ)OlHG0O}`)#ket{ z>!&)05S;0`bN%MT10<&DJtAuRg`6BLD$2|Jg zxNV?DQj_Ici^UJP(-YslZfTF3f!%ZZv&+^k6aY!jMn4ArA_l(OE;!j2(AOW5_(;UZ z57e)yPlzc1a$NvA*6->D;^DAY?@BGNN2Rs*+hAq!3wSj&aD;{ZU)ckfcQ%AXB;mOu zvI>nv&Dxj_4w5B=YE%FU;OO%3W^wu%^;PVHz-timu0KNtd`?$iH%w2TwtrL~B|1f3 z$A#%#6!=tDK2JNJL~ldFW_>l)bnYHg zb$w}fbUZL?$VT~c%Hs9Nf&(_uo=SFV%b%@HIum$F^@C|jpwJ-T`u1V~7>#i(W99z9 zN7H=l8|B{y2cKCC%20TRFHEQ$?aWj!klvLRpJ6fVwbr?O*7GF^X*f`;o|I3AZD1@m z;8AZZ35P=ToAt|Ax6aV4)$A{w+*nGv#=+f7tVvnmV^MhHANnAJ7>V1fnwM8MW^zXR zP{*k?!9x{-Qd*P1n+f~=R0_*O|F=7e;E=Rp_Y+7;?40qFdm=qnuerOvtemkwpTAj- z;|e$#-b^J5T1gZ!q ze?oQZCwr1c?Xf6~E$^`YOqWBsdet?6zSssK$2bedjvRpN#CM|ZRpOY~Y;k&<)z@_9 z?%xKIaQB0gAQWQ5fJSGYLO=YEP{V*zOlA8 zPn+U&oFFu+wg(I}$A1W&8GIY)6w1{;M0CWbQVSr5mD((bCJ`W&5WRGSMdsc39{Rz& zqBv9yhE#+GTA4+EN4p%-dT)Ijfrib1_=p_U+DGM`=LFoQM17!hYDgBn<)psB$@)lT z`(L1UmkQiIkC(IJ-NDdvP&{M2GBx$;BWz^V>BF6CdT{ykxt>v-Axn7q>X(B zsq7Q2=cK(sT22i&9nQ+_rgrLV)&G1!q0*5;OG1ADItS!nUYX<_Svka+`MK>K9iqy% zE9a-DJhGC!#>VGh^#Ff-;uW^;%Al(NVPjVnTn&0}*3&%Xhe8ZpQhYEM`xXcODN*^m z${1}Ei7akv`|bxMwAoMZZ<96QNO(r2mfZ@tC@~qc^iu1a&iXLi)Y!q{CrJKSOMb?$ zK(euthIt8Ly?31`kmT1pFeL9I+S${yw!SYST*Jf&+Hr#zM9#C6{QGF{<4;W%+P~CqWNM85Q*}-eNHv|zz#{BIOHYoij$^QR` z(Jvw0tg9#-ECl!r8}Z==^5#;|H|Sv(11&hUbDzztCM1jUXV1XVojOZCF3(3278C0P z%IE?ZxH;`kFy52w>pWV2*8ZO>(EY2F)}KWk;eQjq`Lpu;b>=?uYj{iewPMP`>k97` z9sLnN!23VpcVYw4o3ykvkY-LvWjTCBMF#-V1j5d85f7S(|_8n%U{61Mbb?E_K@{$GRh*SEia^=laZEA#AcSoU|t zB7?ue8+lr<82WK}Rn;$nVg(;jpmwYc14HyHe(&~l|2=*Yh!w5hUmbL+G51VO$^mAK zXg`kk6DrdQ*uUE7<~@KBOM3xnp2FtPR`NW9+YILt6YV9FKBKD_%?8z(qKmUKd0}s^M*Z-!F{|~4A zJwATFpk2W4Mfq><@AVn@{&zv3=us)IG=}iz2gI>KBtWf@@-ITPkBYKX;G7fqhgJD0 z4xrBR-}i7xeD#=S)Ea2?+6^c)TYRDiS~rt-a*)y~scebM_|ZJ6^qBI4WWBy5Fj*@2 z08saSlgpPg+!5OEiwK`oYcdyB(FYSA=y_F*qZr7i%6ibc;ZJyZ_1cfDO~h-Lu?tI^ z-|=0hcHTaR132D4_s!FLbz(WDf>}yOa#Af&dR`U>Pa3JUCJaGrG~z?3K{_1Q>lK}} z)2tf_d7=g2ccYUw8Ap#GiK2*mJ^J|a{`C2q|U)@ z8<4WSp`ojk$E2c)I?qr4%XokagY%4PVjjH~EFsh-ydKP}zGCA`pNDL2A3L2LBCqpJ zRkE zs|*|?{~n>b-%bHd5!`P7D8AS3QZD9NyPF~Hhz%(nF38R3Fuhe>cl=V15a`$c@5#Lp zCV2~K@(!;41`p{M2$Qj69c-&c^BRDM3lA@7bBnAPl%9y~HUDd2Ar_G30h*q*=XEu> zySpRj1?l|1t-}}rl$!ApIoljRqL2i5erXP+CY{;+uU)Il)lwxSi|$A^Dj z)&XV$8|{{6>6u?@MT%#lJJ_2i4iPu|b90ezV46uF4eSFMxe%+74xSTM^|vsNF^aip z=0D!!9~U#4eTri<;50WsCMv(bT8eubY&BeI(TQ(h*gzIWU!Ai>T>2qCohdRqaFS^M zLH*GtkVXu5#tZL2ZWxP2IKU2JsawLpkjMtg2jIlsmT)WOCT;fa$rX7ye{tLI9Vdl+ zg<+K@t{?rdSR%(L8N$NbwxTek!osYwV^FEF?D$-PU${D86COE??NNckwGm--0| zb}du?3;nN=Qw)jDu&wcgbR;niFH$zeM|Oax*FYHi%APg%8IdkF{52?NEg%yXciCdlzxv_AEklsce-$rl@e$ryK!3 z4(DaLH)q8@#@&@(R=K(xi_Jc4vPup>Hobu|>chiSLAXr*L4z=GxSV-K8elSh_e24P z&A8#2JLijw^|s2I*QKv7yPOk65W@yQ(6BK4Mtj`(5vkV9jc5g{P00|EA| zaam_B6cf-tO3*8Wi&&eDk_ab0%0AMw6LvW{+nEE(LNwtyqe_pVBZu*?=fLtEF$RfI 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�tty9&tBdIC2s$ER)5giPGW9&;nw3{ns*G~V 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 jlH3ZPO0uQT4Fdib%yomr literal 0 HcmV?d00001 From 01f3147259f1c4024528b4cea9de32fc35d79675 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Thu, 16 Jul 2026 01:17:41 +0200 Subject: [PATCH 40/42] Add a Projects section to the root README with teasers for imdb and votee. imdb leads with screenshots since it is the most recent and complete project. --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index 7dfe9f8..10fb36e 100644 --- a/README.md +++ b/README.md @@ -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 / Redoc) - 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. + +Swagger UI showing grouped, fully-documented imdb endpoints + +Grafana dashboard breaking down Six Degrees latency against the other three endpoints + +A real distributed trace in Tempo, opened directly from Grafana + +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` 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 `>`, 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. From e6e2a4aa252829c92737efce0bd99c08688d9353 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Thu, 16 Jul 2026 01:46:31 +0200 Subject: [PATCH 41/42] Fix a real JWT bug from code review: refresh tokens could authenticate as bearer tokens and access tokens could be redeemed at refresh. Pin floating Testcontainers image tags and remove Redoc entirely instead of pinning its CDN script. Both attack vectors verified closed live against the running service; two false-positive Jackson import findings verified and left as is. --- README.md | 2 +- imdb/README.md | 2 +- .../imdb/application/AuthUseCaseImpl.java | 5 +++ .../ControllerObservationInterceptor.java | 4 +- .../security/JwtAuthenticationFilter.java | 10 ++++- .../infrastructure/security/JwtService.java | 19 ++++++++- .../security/SecurityConfig.java | 2 +- imdb/src/main/resources/static/redoc.html | 13 ------- .../imdb/TestcontainersConfiguration.java | 10 ++++- .../imdb/application/AuthUseCaseImplTest.java | 39 +++++++++++++++++++ .../openapi/OpenApiIntegrationTest.java | 6 --- .../security/JwtAuthenticationFilterTest.java | 14 ++++++- .../security/JwtServiceTest.java | 12 ++++++ 13 files changed, 108 insertions(+), 30 deletions(-) delete mode 100644 imdb/src/main/resources/static/redoc.html diff --git a/README.md b/README.md index 10fb36e..e48ba09 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The most recent, and most complete, project in this repo. A Spring Boot 4.1 / Ja - **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 / Redoc) - every endpoint carries a real summary, description, and per-status-code response doc, not auto-generated `delete_3`-style operationIds. +- **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. Swagger UI showing grouped, fully-documented imdb endpoints diff --git a/imdb/README.md b/imdb/README.md index cea5170..2d1b99a 100644 --- a/imdb/README.md +++ b/imdb/README.md @@ -142,7 +142,7 @@ All TTLs are long because the dataset only changes on image reload; there is no All errors are RFC 7807 `ProblemDetail` (404 for unknown IDs, 400 for malformed IDs/out-of-range `maxDegree`/missing params, 405 for the wrong HTTP method). Full contracts, request/response shapes, and error handling: [`docs/low-level-design.md`](docs/low-level-design.md) §4/§9. -Interactive API docs, generated from the live controllers: [`/swagger-ui/index.html`](http://localhost:8080/swagger-ui/index.html) (Swagger UI) or [`/redoc.html`](http://localhost:8080/redoc.html) (Redoc), both reading the same generated document at `/v3/api-docs`. +Interactive API docs, generated from the live controllers: [`/swagger-ui/index.html`](http://localhost:8080/swagger-ui/index.html), reading the generated OpenAPI document at `/v3/api-docs`. Swagger UI showing grouped, fully-documented endpoints diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java index 95bd5a7..116548a 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java @@ -47,7 +47,12 @@ public TokenPair login(LoginRequest request) { @Override public TokenPair refresh(String refreshToken) { + // Without the refreshToken() filter, a caller's own (short-lived) access token would also + // parse successfully here and mint a brand new token pair, extending their session past the + // access token's intended TTL without ever holding a real refresh token. Found by Copilot + // code review - the mirror image of the same gap in JwtAuthenticationFilter. var parsed = jwtService.parse(refreshToken) + .filter(JwtService.Parsed::refreshToken) .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); User user = userRepository.findById(parsed.userId()) .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/observability/ControllerObservationInterceptor.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/observability/ControllerObservationInterceptor.java index 959970c..3cfbb74 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/observability/ControllerObservationInterceptor.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/observability/ControllerObservationInterceptor.java @@ -29,8 +29,8 @@ public ControllerObservationInterceptor(ObservationRegistry observationRegistry) @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { if (!(handler instanceof HandlerMethod handlerMethod)) { - // Static resources (redoc.html, swagger-ui assets) and the default error handler go - // through this interceptor too but aren't a HandlerMethod - nothing worth a span there. + // Static resources (swagger-ui assets) and the default error handler go through this + // interceptor too but aren't a HandlerMethod - nothing worth a span there. return true; } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilter.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilter.java index f389219..6483d2c 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilter.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilter.java @@ -36,7 +36,15 @@ protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull Ht String header = request.getHeader("Authorization"); if (header != null && header.startsWith("Bearer ")) { String token = header.substring("Bearer ".length()); - jwtService.parse(token).ifPresent(parsed -> authenticate(parsed.userId(), parsed.roles())); + // A refresh token is a valid, correctly-signed JWT too - excluding it here is what stops + // it from working as a general-purpose bearer credential on any endpoint that only checks + // isAuthenticated() (its own roles claim is always empty, but nothing here was previously + // checking that). Found by Copilot code review; JwtService.Parsed.refreshToken() is the + // real signal (see JwtService.parse()), not roles().isEmpty() - that happened to also + // work today only because this codebase never issues a role-less access token. + jwtService.parse(token) + .filter(parsed -> !parsed.refreshToken()) + .ifPresent(parsed -> authenticate(parsed.userId(), parsed.roles())); } filterChain.doFilter(request, response); } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java index 8e62493..f6c7725 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/JwtService.java @@ -39,6 +39,7 @@ public String issueAccessToken(int userId, Set roles) { return Jwts.builder() .subject(String.valueOf(userId)) .claim("roles", roles.stream().map(Role::name).collect(Collectors.toList())) + .claim("type", "access") .issuedAt(Date.from(now)) .expiration(Date.from(now.plus(accessTokenTtl))) .signWith(key) @@ -65,12 +66,26 @@ public Optional parse(String token) { List roleNames = claims.get("roles", List.class); Set roles = roleNames == null ? Set.of() : roleNames.stream().map(Role::valueOf).collect(Collectors.toSet()); - return Optional.of(new Parsed(userId, roles)); + // "refresh" is the only value that ever means anything here - a bare/missing type claim + // is treated as an access token (not just refresh tokens predating this claim, but also + // any already-issued, not-yet-expired access token from before this check existed, so a + // rolling deploy doesn't force every logged-in session to re-authenticate). + boolean refreshToken = "refresh".equals(claims.get("type", String.class)); + return Optional.of(new Parsed(userId, roles, refreshToken)); } catch (JwtException | IllegalArgumentException e) { return Optional.empty(); } } - public record Parsed(int userId, Set roles) { + // refreshToken distinguishes a redeemable-once-for-new-tokens credential from a bearer-auth + // credential - without checking it, a refresh token satisfies JwtAuthenticationFilter just like + // an access token would (it parses and signs the same way, and simply carries no roles), and an + // access token satisfies AuthUseCaseImpl.refresh() just like a refresh token would (findById + // succeeds for its userId regardless of which token type produced it). Found by Copilot code + // review, verified against this exact codebase before fixing: JwtAuthenticationFilter's roles + // check alone happened to be a correct-by-coincidence fix given every user always has exactly + // one role, but didn't close the second, symmetric hole at the refresh endpoint - this claim is + // the actual signal both call sites should have been checking. + public record Parsed(int userId, Set roles, boolean refreshToken) { } } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java index a67a7f1..871d387 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/security/SecurityConfig.java @@ -38,7 +38,7 @@ public SecurityFilterChain securityFilterChain( .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeHttpRequests(auth -> auth .requestMatchers("/actuator/**", "/api/v1/auth/**", - "/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", "/redoc.html").permitAll() + "/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**").permitAll() // /lists/me, /users/me, and /titles/*/reviews/me must be declared before the // broader /api/v1/lists/*, /api/v1/users/*, and /api/v1/titles/** permits below - // Spring Security evaluates matchers in declaration order and the first match diff --git a/imdb/src/main/resources/static/redoc.html b/imdb/src/main/resources/static/redoc.html deleted file mode 100644 index 4035450..0000000 --- a/imdb/src/main/resources/static/redoc.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - imdb API - Redoc - - - - - - - - - diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java index bc73f83..db28b64 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/TestcontainersConfiguration.java @@ -14,7 +14,10 @@ public class TestcontainersConfiguration { @Bean @ServiceConnection LgtmStackContainer grafanaLgtmContainer() { - return new LgtmStackContainer(DockerImageName.parse("grafana/otel-lgtm:latest")); + // Pinned, not :latest - the floating tag makes a passing build today no guarantee of a + // passing build tomorrow if upstream ships a breaking change. 0.29.0 confirmed current via + // the Docker Hub API (its digest matches :latest's at the time of pinning), not guessed. + return new LgtmStackContainer(DockerImageName.parse("grafana/otel-lgtm:0.29.0")); } @Bean @@ -26,7 +29,10 @@ PostgreSQLContainer postgresContainer() { @Bean @ServiceConnection(name = "redis") GenericContainer redisContainer() { - return new GenericContainer<>(DockerImageName.parse("redis:latest")).withExposedPorts(6379); + // redis:7-alpine, not :latest - also matches the version docker-compose.yaml actually runs in + // dev/prod (README's External Services table), so the test double and the real deployment + // target are the same major version instead of silently drifting apart. + return new GenericContainer<>(DockerImageName.parse("redis:7-alpine")).withExposedPorts(6379); } } diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java index 7763c76..d2b0091 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java @@ -82,4 +82,43 @@ void loginThrowsForbiddenForAWrongPassword() { assertThatThrownBy(() -> useCase.login(new LoginRequest("ada@example.com", "wrong"))) .isInstanceOf(ForbiddenException.class); } + + @Test + void refreshIssuesNewTokensForAValidRefreshToken() { + given(jwtService.parse("refresh-token")) + .willReturn(Optional.of(new JwtService.Parsed(1, Set.of(), true))); + given(userRepository.findById(1)) + .willReturn(Optional.of(new User(1, "ada@example.com", "hash", "Ada", null, Role.USER, 0))); + given(jwtService.issueAccessToken(1, Set.of(Role.USER))).willReturn("new-access"); + given(jwtService.issueRefreshToken(1)).willReturn("new-refresh"); + + var tokens = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder) + .refresh("refresh-token"); + + assertThat(tokens.accessToken()).isEqualTo("new-access"); + assertThat(tokens.refreshToken()).isEqualTo("new-refresh"); + } + + // Regression test for a real bug found by Copilot code review: an access token used to parse + // successfully here too (JwtService.parse doesn't care which kind of token it's given), so a + // caller could mint a fresh token pair from their own short-lived access token without ever + // holding a real refresh token, defeating the point of the access token's short TTL. + @Test + void refreshRejectsAnAccessTokenPresentedAsARefreshToken() { + given(jwtService.parse("access-token")) + .willReturn(Optional.of(new JwtService.Parsed(1, Set.of(Role.USER), false))); + var useCase = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder); + + assertThatThrownBy(() -> useCase.refresh("access-token")) + .isInstanceOf(ForbiddenException.class); + } + + @Test + void refreshThrowsForbiddenForAnUnparsableToken() { + given(jwtService.parse("garbage")).willReturn(Optional.empty()); + var useCase = new AuthUseCaseImpl(userRepository, jwtService, passwordEncoder); + + assertThatThrownBy(() -> useCase.refresh("garbage")) + .isInstanceOf(ForbiddenException.class); + } } diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/openapi/OpenApiIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/openapi/OpenApiIntegrationTest.java index f95a7a0..76fa1d4 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/openapi/OpenApiIntegrationTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/openapi/OpenApiIntegrationTest.java @@ -34,10 +34,4 @@ void swaggerUiIsPubliclyAccessible() throws Exception { mockMvc.perform(get("/swagger-ui/index.html")) .andExpect(status().isOk()); } - - @Test - void redocIsPubliclyAccessible() throws Exception { - mockMvc.perform(get("/redoc.html")) - .andExpect(status().isOk()); - } } diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java index 0cb199f..00a0e8c 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtAuthenticationFilterTest.java @@ -39,7 +39,7 @@ void clearContext() { void populatesSecurityContextForAValidBearerToken() throws Exception { given(request.getHeader("Authorization")).willReturn("Bearer good-token"); given(jwtService.parse("good-token")) - .willReturn(Optional.of(new JwtService.Parsed(7, Set.of(Role.USER)))); + .willReturn(Optional.of(new JwtService.Parsed(7, Set.of(Role.USER), false))); new JwtAuthenticationFilter(jwtService).doFilterInternal(request, response, chain); @@ -49,6 +49,18 @@ void populatesSecurityContextForAValidBearerToken() throws Exception { verify(chain).doFilter(request, response); } + @Test + void leavesSecurityContextEmptyForARefreshTokenPresentedAsBearerAuth() throws Exception { + given(request.getHeader("Authorization")).willReturn("Bearer refresh-token"); + given(jwtService.parse("refresh-token")) + .willReturn(Optional.of(new JwtService.Parsed(7, Set.of(), true))); + + new JwtAuthenticationFilter(jwtService).doFilterInternal(request, response, chain); + + assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); + verify(chain).doFilter(request, response); + } + @Test void leavesSecurityContextEmptyWithNoAuthorizationHeader() throws Exception { given(request.getHeader("Authorization")).willReturn(null); diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java index fffcfb9..f886406 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/security/JwtServiceTest.java @@ -21,6 +21,18 @@ void issuedAccessTokenParsesBackToTheSameUserAndRoles() { assertThat(parsed.userId()).isEqualTo(42); assertThat(parsed.roles()).containsExactlyInAnyOrder(Role.USER, Role.ADMIN); + assertThat(parsed.refreshToken()).isFalse(); + } + + @Test + void issuedRefreshTokenParsesBackWithNoRolesAndTheRefreshFlagSet() { + String token = jwtService.issueRefreshToken(42); + + var parsed = jwtService.parse(token).orElseThrow(); + + assertThat(parsed.userId()).isEqualTo(42); + assertThat(parsed.roles()).isEmpty(); + assertThat(parsed.refreshToken()).isTrue(); } @Test From ec2c3d2b390f5d928d8d27f2ee7a07f6e76bfb98 Mon Sep 17 00:00:00 2001 From: Ludovic Temgoua Abanda Date: Thu, 16 Jul 2026 05:23:22 +0200 Subject: [PATCH 42/42] Move every REST request/response DTO into application.rest, including PersonRef which the earlier move had left behind. Verified with a full test run and a live combined load test against the rebuilt image; admin write errors stayed at zero. --- imdb/docs/crud-expansion-plan.md | 464 +++++++++--------- .../imdb/application/AuthUseCaseImpl.java | 3 + .../imdb/application/ListUseCaseImpl.java | 2 + .../application/PersonAdminUseCaseImpl.java | 3 + .../imdb/application/ReviewUseCaseImpl.java | 1 + .../imdb/application/SixDegreesResult.java | 7 - .../application/SixDegreesUseCaseImpl.java | 3 + .../application/TitleAdminUseCaseImpl.java | 1 + .../imdb/application/UserUseCaseImpl.java | 1 + .../application/contracts/AuthUseCase.java | 6 +- .../application/contracts/ListUseCase.java | 4 +- .../contracts/PersonAdminUseCase.java | 6 +- .../application/contracts/ReviewUseCase.java | 2 +- .../contracts/SixDegreesOutcome.java | 2 +- .../contracts/TitleAdminUseCase.java | 12 +- .../application/contracts/UserUseCase.java | 2 +- .../{ => rest}/AddListItemRequest.java | 2 +- .../{ => rest}/AddWatchlistItemRequest.java | 2 +- .../{ => rest}/CreateListRequest.java | 2 +- .../{ => rest}/CreatePersonRequest.java | 2 +- .../{ => rest}/CreateTitleRequest.java | 2 +- .../application/{ => rest}/CrewRequest.java | 2 +- .../application/{ => rest}/LoginRequest.java | 2 +- .../{ => rest}/PatchPersonRequest.java | 2 +- .../{ => rest}/PatchTitleRequest.java | 2 +- .../imdb/application/{ => rest}/PathStep.java | 2 +- .../application/{ => rest}/PersonRef.java | 2 +- .../{ => rest}/PrincipalRequest.java | 2 +- .../application/{ => rest}/RatingRequest.java | 2 +- .../{ => rest}/RegisterRequest.java | 2 +- .../application/{ => rest}/ReviewRequest.java | 2 +- .../application/{ => rest}/RoleRequest.java | 2 +- .../application/rest/SixDegreesResult.java | 7 + .../application/{ => rest}/TokenPair.java | 2 +- .../{ => rest}/UpdateListRequest.java | 2 +- .../{ => rest}/UpdatePersonRequest.java | 2 +- .../{ => rest}/UpdateProfileRequest.java | 2 +- .../{ => rest}/UpdateTitleRequest.java | 2 +- .../{ => rest}/VisibilityRequest.java | 2 +- .../cache/CachingPersonAdminUseCase.java | 6 +- .../cache/CachingReviewUseCase.java | 2 +- .../cache/CachingTitleAdminUseCase.java | 12 +- .../imdb/presentation/AuthController.java | 6 +- .../imdb/presentation/ListController.java | 6 +- .../imdb/presentation/PersonController.java | 6 +- .../imdb/presentation/ReviewController.java | 2 +- .../imdb/presentation/TitleController.java | 12 +- .../imdb/presentation/UserController.java | 4 +- .../presentation/WatchlistController.java | 4 +- .../imdb/application/AuthUseCaseImplTest.java | 2 + .../PersonAdminUseCaseImplTest.java | 2 + .../application/ReviewUseCaseImplTest.java | 1 + .../TitleAdminUseCaseImplTest.java | 3 + .../imdb/application/UserUseCaseImplTest.java | 1 + .../cache/CacheEvictionIntegrationTest.java | 6 +- .../imdb/presentation/AuthControllerTest.java | 6 +- .../presentation/PersonControllerTest.java | 6 +- 57 files changed, 343 insertions(+), 314 deletions(-) delete mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/AddListItemRequest.java (69%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/AddWatchlistItemRequest.java (70%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/CreateListRequest.java (82%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/CreatePersonRequest.java (83%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/CreateTitleRequest.java (87%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/CrewRequest.java (66%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/LoginRequest.java (78%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/PatchPersonRequest.java (79%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/PatchTitleRequest.java (90%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/PathStep.java (72%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/PersonRef.java (51%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/PrincipalRequest.java (83%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/RatingRequest.java (85%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/RegisterRequest.java (85%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/ReviewRequest.java (77%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/RoleRequest.java (74%) create mode 100644 imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/SixDegreesResult.java rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/TokenPair.java (58%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/UpdateListRequest.java (83%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/UpdatePersonRequest.java (83%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/UpdateProfileRequest.java (74%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/UpdateTitleRequest.java (87%) rename imdb/src/main/java/com/ludovictemgoua/imdb/application/{ => rest}/VisibilityRequest.java (77%) diff --git a/imdb/docs/crud-expansion-plan.md b/imdb/docs/crud-expansion-plan.md index 093878a..59680dd 100644 --- a/imdb/docs/crud-expansion-plan.md +++ b/imdb/docs/crud-expansion-plan.md @@ -869,6 +869,8 @@ git commit -m "Add JwtAuthenticationFilter, security filter chain, and ProblemDe ```java package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.model.Role; import com.ludovictemgoua.imdb.domain.model.User; @@ -1026,17 +1028,15 @@ public record TokenPair(String accessToken, String refreshToken) { ```java package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.LoginRequest; -import com.ludovictemgoua.imdb.application.RegisterRequest; -import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.rest.TokenPair; public interface AuthUseCase { - TokenPair register(RegisterRequest request); + TokenPair register(com.ludovictemgoua.imdb.application.rest.RegisterRequest request); - TokenPair login(LoginRequest request); + com.ludovictemgoua.imdb.application.rest.TokenPair login(com.ludovictemgoua.imdb.application.rest.LoginRequest request); - TokenPair refresh(String refreshToken); + com.ludovictemgoua.imdb.application.rest.TokenPair refresh(String refreshToken); } ``` @@ -1044,6 +1044,9 @@ public interface AuthUseCase { package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; +import com.ludovictemgoua.imdb.application.rest.TokenPair; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; import com.ludovictemgoua.imdb.domain.model.Role; @@ -1058,50 +1061,50 @@ import java.util.Set; @Service public class AuthUseCaseImpl implements AuthUseCase { - private final UserRepository userRepository; - private final JwtService jwtService; - private final PasswordEncoder passwordEncoder; - - public AuthUseCaseImpl(UserRepository userRepository, JwtService jwtService, PasswordEncoder passwordEncoder) { - this.userRepository = userRepository; - this.jwtService = jwtService; - this.passwordEncoder = passwordEncoder; - } - - @Override - public TokenPair register(RegisterRequest request) { - if (userRepository.existsByEmail(request.email())) { - throw new ConflictException("An account with this email already exists"); - } - String hash = passwordEncoder.encode(request.password()); - User user = userRepository.insert(request.email(), hash, request.displayName(), Role.USER); - return issueTokens(user); - } - - @Override - public TokenPair login(LoginRequest request) { - User user = userRepository.findByEmail(request.email()) - .orElseThrow(() -> new ForbiddenException("Invalid email or password")); - if (!passwordEncoder.matches(request.password(), user.passwordHash())) { - throw new ForbiddenException("Invalid email or password"); - } - return issueTokens(user); - } - - @Override - public TokenPair refresh(String refreshToken) { - var parsed = jwtService.parse(refreshToken) - .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); - User user = userRepository.findById(parsed.userId()) - .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); - return issueTokens(user); - } - - private TokenPair issueTokens(User user) { - String access = jwtService.issueAccessToken(user.id(), Set.of(user.role())); - String refresh = jwtService.issueRefreshToken(user.id()); - return new TokenPair(access, refresh); - } + private final UserRepository userRepository; + private final JwtService jwtService; + private final PasswordEncoder passwordEncoder; + + public AuthUseCaseImpl(UserRepository userRepository, JwtService jwtService, PasswordEncoder passwordEncoder) { + this.userRepository = userRepository; + this.jwtService = jwtService; + this.passwordEncoder = passwordEncoder; + } + + @Override + public TokenPair register(RegisterRequest request) { + if (userRepository.existsByEmail(request.email())) { + throw new ConflictException("An account with this email already exists"); + } + String hash = passwordEncoder.encode(request.password()); + User user = userRepository.insert(request.email(), hash, request.displayName(), Role.USER); + return issueTokens(user); + } + + @Override + public TokenPair login(LoginRequest request) { + User user = userRepository.findByEmail(request.email()) + .orElseThrow(() -> new ForbiddenException("Invalid email or password")); + if (!passwordEncoder.matches(request.password(), user.passwordHash())) { + throw new ForbiddenException("Invalid email or password"); + } + return issueTokens(user); + } + + @Override + public TokenPair refresh(String refreshToken) { + var parsed = jwtService.parse(refreshToken) + .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); + User user = userRepository.findById(parsed.userId()) + .orElseThrow(() -> new ForbiddenException("Invalid or expired refresh token")); + return issueTokens(user); + } + + private TokenPair issueTokens(User user) { + String access = jwtService.issueAccessToken(user.id(), Set.of(user.role())); + String refresh = jwtService.issueRefreshToken(user.id()); + return new TokenPair(access, refresh); + } } ``` @@ -1115,9 +1118,7 @@ Expected: PASS, 4 tests green. ```java package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.LoginRequest; -import com.ludovictemgoua.imdb.application.RegisterRequest; -import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -1137,50 +1138,50 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @WithAnonymousUser class AuthControllerTest { - @Autowired - MockMvc mockMvc; - @Autowired - ObjectMapper objectMapper; - @MockitoBean - AuthUseCase authUseCase; - - @Test - void registerReturns201WithTokens() throws Exception { - given(authUseCase.register(new RegisterRequest("ada@example.com", "password123", "Ada"))) - .willReturn(new TokenPair("access", "refresh")); - - mockMvc.perform(post("/api/v1/auth/register") - .contentType("application/json") - .content(objectMapper.writeValueAsString( - new RegisterRequest("ada@example.com", "password123", "Ada")))) - .andExpect(status().isCreated()) - .andExpect(jsonPath("$.accessToken").value("access")); - } - - @Test - void registerReturns409ForADuplicateEmail() throws Exception { - given(authUseCase.register(new RegisterRequest("ada@example.com", "password123", "Ada"))) - .willThrow(new ConflictException("An account with this email already exists")); - - mockMvc.perform(post("/api/v1/auth/register") - .contentType("application/json") - .content(objectMapper.writeValueAsString( - new RegisterRequest("ada@example.com", "password123", "Ada")))) - .andExpect(status().isConflict()); - } - - @Test - void loginReturnsTokensForValidCredentials() throws Exception { - given(authUseCase.login(new LoginRequest("ada@example.com", "password123"))) - .willReturn(new TokenPair("access", "refresh")); - - mockMvc.perform(post("/api/v1/auth/login") - .contentType("application/json") - .content(objectMapper.writeValueAsString( - new LoginRequest("ada@example.com", "password123")))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.refreshToken").value("refresh")); - } + @Autowired + MockMvc mockMvc; + @Autowired + ObjectMapper objectMapper; + @MockitoBean + AuthUseCase authUseCase; + + @Test + void registerReturns201WithTokens() throws Exception { + given(authUseCase.register(new RegisterRequest("ada@example.com", "password123", "Ada"))) + .willReturn(new com.ludovictemgoua.imdb.application.rest.TokenPair("access", "refresh")); + + mockMvc.perform(post("/api/v1/auth/register") + .contentType("application/json") + .content(objectMapper.writeValueAsString( + new RegisterRequest("ada@example.com", "password123", "Ada")))) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.accessToken").value("access")); + } + + @Test + void registerReturns409ForADuplicateEmail() throws Exception { + given(authUseCase.register(new RegisterRequest("ada@example.com", "password123", "Ada"))) + .willThrow(new ConflictException("An account with this email already exists")); + + mockMvc.perform(post("/api/v1/auth/register") + .contentType("application/json") + .content(objectMapper.writeValueAsString( + new RegisterRequest("ada@example.com", "password123", "Ada")))) + .andExpect(status().isConflict()); + } + + @Test + void loginReturnsTokensForValidCredentials() throws Exception { + given(authUseCase.login(new com.ludovictemgoua.imdb.application.rest.LoginRequest("ada@example.com", "password123"))) + .willReturn(new com.ludovictemgoua.imdb.application.rest.TokenPair("access", "refresh")); + + mockMvc.perform(post("/api/v1/auth/login") + .contentType("application/json") + .content(objectMapper.writeValueAsString( + new com.ludovictemgoua.imdb.application.rest.LoginRequest("ada@example.com", "password123")))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.refreshToken").value("refresh")); + } } ``` @@ -1194,14 +1195,12 @@ Expected: FAIL - `AuthController` doesn't exist yet. ```java package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.LoginRequest; -import com.ludovictemgoua.imdb.application.RegisterRequest; -import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; +import com.ludovictemgoua.imdb.application.rest.TokenPair; import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; import jakarta.validation.Valid; -import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Size; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -1213,30 +1212,30 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("/api/v1/auth") public class AuthController { - private final AuthUseCase authUseCase; + private final AuthUseCase authUseCase; - public AuthController(AuthUseCase authUseCase) { - this.authUseCase = authUseCase; - } + public AuthController(AuthUseCase authUseCase) { + this.authUseCase = authUseCase; + } - @PostMapping("/register") - @ResponseStatus(HttpStatus.CREATED) - public TokenPair register(@Valid @RequestBody RegisterRequest request) { - return authUseCase.register(request); - } + @PostMapping("/register") + @ResponseStatus(HttpStatus.CREATED) + public TokenPair register(@Valid @RequestBody RegisterRequest request) { + return authUseCase.register(request); + } - @PostMapping("/login") - public TokenPair login(@Valid @RequestBody LoginRequest request) { - return authUseCase.login(request); - } + @PostMapping("/login") + public TokenPair login(@Valid @RequestBody LoginRequest request) { + return authUseCase.login(request); + } - @PostMapping("/refresh") - public TokenPair refresh(@RequestBody RefreshRequest request) { - return authUseCase.refresh(request.refreshToken()); - } + @PostMapping("/refresh") + public com.ludovictemgoua.imdb.application.rest.TokenPair refresh(@RequestBody RefreshRequest request) { + return authUseCase.refresh(request.refreshToken()); + } - public record RefreshRequest(@NotBlank String refreshToken) { - } + public record RefreshRequest(@NotBlank String refreshToken) { + } } ``` @@ -1528,6 +1527,7 @@ Expected: PASS, 4 tests green. ```java package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.Role; @@ -1632,7 +1632,7 @@ public record RoleRequest(@NotNull Role role) { ```java package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.UpdateProfileRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; import com.ludovictemgoua.imdb.domain.model.Role; @@ -1660,6 +1660,7 @@ public interface UserUseCase { package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.UserUseCase; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PagedResult; @@ -1690,8 +1691,10 @@ public class UserUseCaseImpl implements UserUseCase { WriteResult result = userRepository.updateProfile(userId, request.displayName(), request.bio(), request.version()); switch (result) { case NOT_FOUND -> throw new NotFoundException("No user with id " + userId); - case VERSION_CONFLICT -> throw new ConflictException("Your profile was modified concurrently - refresh and retry"); - case SUCCESS -> { } + case VERSION_CONFLICT -> + throw new ConflictException("Your profile was modified concurrently - refresh and retry"); + case SUCCESS -> { + } } return getOwnProfile(userId); } @@ -1812,8 +1815,8 @@ Expected: FAIL - `UserController` doesn't exist yet. ```java package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.RoleRequest; -import com.ludovictemgoua.imdb.application.UpdateProfileRequest; +import com.ludovictemgoua.imdb.application.rest.RoleRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.application.contracts.UserUseCase; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; @@ -2443,6 +2446,8 @@ git commit -m "Add TitleRepository write methods: insert/update/soft-delete/crew ```java package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.TitleCore; @@ -2581,11 +2586,9 @@ public record RatingRequest(@DecimalMin("0.0") @DecimalMax("10.0") double averag ```java package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.CreateTitleRequest; -import com.ludovictemgoua.imdb.application.CrewRequest; -import com.ludovictemgoua.imdb.application.PatchTitleRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CrewRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.domain.model.TitleCore; public interface TitleAdminUseCase { @@ -2594,13 +2597,13 @@ public interface TitleAdminUseCase { TitleCore update(String titleId, UpdateTitleRequest request); - TitleCore patch(String titleId, PatchTitleRequest request); + TitleCore patch(String titleId, com.ludovictemgoua.imdb.application.rest.PatchTitleRequest request); void delete(String titleId); void upsertCrew(String titleId, CrewRequest request); - void upsertRating(String titleId, RatingRequest request); + void upsertRating(String titleId, com.ludovictemgoua.imdb.application.rest.RatingRequest request); void deleteRating(String titleId); } @@ -2610,6 +2613,7 @@ public interface TitleAdminUseCase { package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; +import com.ludovictemgoua.imdb.application.rest.*; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.TitleCore; @@ -2696,7 +2700,8 @@ public class TitleAdminUseCaseImpl implements TitleAdminUseCase { case NOT_FOUND -> throw new NotFoundException("No title with id " + titleId); case VERSION_CONFLICT -> throw new ConflictException( "Title " + titleId + " was modified by someone else - refresh and retry"); - case SUCCESS -> { } + case SUCCESS -> { + } } } } @@ -2712,12 +2717,10 @@ Expected: PASS, 4 tests green. ```java package com.ludovictemgoua.imdb.infrastructure.cache; -import com.ludovictemgoua.imdb.application.CreateTitleRequest; -import com.ludovictemgoua.imdb.application.CrewRequest; -import com.ludovictemgoua.imdb.application.PatchTitleRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.PatchTitleRequest; +import com.ludovictemgoua.imdb.application.rest.RatingRequest; import com.ludovictemgoua.imdb.application.TitleAdminUseCaseImpl; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; import com.ludovictemgoua.imdb.domain.model.TitleCore; import org.springframework.cache.annotation.CacheEvict; @@ -2747,7 +2750,7 @@ public class CachingTitleAdminUseCase implements TitleAdminUseCase { @Override @CacheEvict(cacheNames = "title-detail", key = "#titleId") - public TitleCore update(String titleId, UpdateTitleRequest request) { + public TitleCore update(String titleId, com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest request) { return delegate.update(titleId, request); } @@ -2765,7 +2768,7 @@ public class CachingTitleAdminUseCase implements TitleAdminUseCase { @Override @CacheEvict(cacheNames = "title-detail", key = "#titleId") - public void upsertCrew(String titleId, CrewRequest request) { + public void upsertCrew(String titleId, com.ludovictemgoua.imdb.application.rest.CrewRequest request) { delegate.upsertCrew(titleId, request); } @@ -2838,69 +2841,71 @@ Expected: FAIL - `TitleController` has no `POST /api/v1/titles` mapping yet. - [ ] **Step 9: Add the admin endpoints to `TitleController`** ```java - private final TitleAdminUseCase titleAdminUseCase; + import com.ludovictemgoua.imdb.application.rest.*; - public TitleController(TitleSearchUseCase searchUseCase, TitleDetailUseCase detailUseCase, - TitleAdminUseCase titleAdminUseCase) { - this.searchUseCase = searchUseCase; - this.detailUseCase = detailUseCase; - this.titleAdminUseCase = titleAdminUseCase; - } +private final TitleAdminUseCase titleAdminUseCase; - @PostMapping - @org.springframework.http.HttpStatus.CREATED // placeholder marker removed below - see @ResponseStatus line - @org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.CREATED) - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public TitleCore create(@jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody - com.ludovictemgoua.imdb.application.CreateTitleRequest request) { - return titleAdminUseCase.create(request); - } +public TitleController(TitleSearchUseCase searchUseCase, TitleDetailUseCase detailUseCase, + TitleAdminUseCase titleAdminUseCase) { + this.searchUseCase = searchUseCase; + this.detailUseCase = detailUseCase; + this.titleAdminUseCase = titleAdminUseCase; +} - @org.springframework.web.bind.annotation.PutMapping("/{titleId}") - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public TitleCore update(@PathVariable String titleId, - @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody - com.ludovictemgoua.imdb.application.UpdateTitleRequest request) { - return titleAdminUseCase.update(titleId, request); - } +@PostMapping +@org.springframework.http.HttpStatus.CREATED // placeholder marker removed below - see @ResponseStatus line +@org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.CREATED) +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public TitleCore create(@jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.rest.CreateTitleRequest request) { + return titleAdminUseCase.create(request); +} - @org.springframework.web.bind.annotation.PatchMapping("/{titleId}") - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public TitleCore patch(@PathVariable String titleId, - @org.springframework.web.bind.annotation.RequestBody - com.ludovictemgoua.imdb.application.PatchTitleRequest request) { - return titleAdminUseCase.patch(titleId, request); - } +@org.springframework.web.bind.annotation.PutMapping("/{titleId}") +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public TitleCore update(@PathVariable String titleId, + @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest request) { + return titleAdminUseCase.update(titleId, request); +} - @org.springframework.web.bind.annotation.DeleteMapping("/{titleId}") - @org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT) - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public void delete(@PathVariable String titleId) { - titleAdminUseCase.delete(titleId); - } +@org.springframework.web.bind.annotation.PatchMapping("/{titleId}") +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public TitleCore patch(@PathVariable String titleId, + @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.rest.PatchTitleRequest request) { + return titleAdminUseCase.patch(titleId, request); +} - @org.springframework.web.bind.annotation.PutMapping("/{titleId}/crew") - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public void upsertCrew(@PathVariable String titleId, - @org.springframework.web.bind.annotation.RequestBody - com.ludovictemgoua.imdb.application.CrewRequest request) { - titleAdminUseCase.upsertCrew(titleId, request); - } +@org.springframework.web.bind.annotation.DeleteMapping("/{titleId}") +@org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT) +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public void delete(@PathVariable String titleId) { + titleAdminUseCase.delete(titleId); +} - @org.springframework.web.bind.annotation.PutMapping("/{titleId}/rating") - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public void upsertRating(@PathVariable String titleId, - @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody - com.ludovictemgoua.imdb.application.RatingRequest request) { - titleAdminUseCase.upsertRating(titleId, request); - } +@org.springframework.web.bind.annotation.PutMapping("/{titleId}/crew") +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public void upsertCrew(@PathVariable String titleId, + @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.rest.CrewRequest request) { + titleAdminUseCase.upsertCrew(titleId, request); +} - @org.springframework.web.bind.annotation.DeleteMapping("/{titleId}/rating") - @org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT) - @org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") - public void deleteRating(@PathVariable String titleId) { - titleAdminUseCase.deleteRating(titleId); - } +@org.springframework.web.bind.annotation.PutMapping("/{titleId}/rating") +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public void upsertRating(@PathVariable String titleId, + @jakarta.validation.Valid @org.springframework.web.bind.annotation.RequestBody + com.ludovictemgoua.imdb.application.rest.RatingRequest request) { + titleAdminUseCase.upsertRating(titleId, request); +} + +@org.springframework.web.bind.annotation.DeleteMapping("/{titleId}/rating") +@org.springframework.web.bind.annotation.ResponseStatus(org.springframework.http.HttpStatus.NO_CONTENT) +@org.springframework.security.access.prepost.PreAuthorize("hasRole('ADMIN')") +public void deleteRating(@PathVariable String titleId) { + titleAdminUseCase.deleteRating(titleId); +} ``` Replace the fully-qualified names above with proper `import` statements at the top of the file (matching @@ -3251,6 +3256,8 @@ git commit -m "Add PersonRepository write methods: insert/update/soft-delete" ```java package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PersonCore; @@ -3351,16 +3358,14 @@ public record PatchPersonRequest(String primaryName, Integer birthYear, Integer ```java package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.CreatePersonRequest; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; -import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; import com.ludovictemgoua.imdb.domain.model.PersonCore; public interface PersonAdminUseCase { - PersonCore create(CreatePersonRequest request); + PersonCore create(com.ludovictemgoua.imdb.application.rest.CreatePersonRequest request); - PersonCore update(String personId, UpdatePersonRequest request); + PersonCore update(String personId, com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest request); PersonCore patch(String personId, PatchPersonRequest request); @@ -3372,6 +3377,9 @@ public interface PersonAdminUseCase { package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PersonCore; @@ -3427,7 +3435,8 @@ public class PersonAdminUseCaseImpl implements PersonAdminUseCase { case NOT_FOUND -> throw new NotFoundException("No person with id " + personId); case VERSION_CONFLICT -> throw new ConflictException( "Person " + personId + " was modified by someone else - refresh and retry"); - case SUCCESS -> { } + case SUCCESS -> { + } } } } @@ -3467,7 +3476,7 @@ Expected: FAIL - `PersonController` has no `POST /api/v1/people` mapping yet. - [ ] **Step 8: Add the admin endpoints to `PersonController`** Add these imports: `com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase`, -`com.ludovictemgoua.imdb.application.CreatePersonRequest`, `UpdatePersonRequest`, `PatchPersonRequest`, +`com.ludovictemgoua.imdb.application.rest.CreatePersonRequest`, `UpdatePersonRequest`, `PatchPersonRequest`, `com.ludovictemgoua.imdb.domain.model.PersonCore`, `jakarta.validation.Valid`, `org.springframework.http.HttpStatus`, `org.springframework.security.access.prepost.PreAuthorize`, `org.springframework.web.bind.annotation.{PostMapping,PutMapping,PatchMapping,DeleteMapping,RequestBody,ResponseStatus}`: @@ -3846,10 +3855,10 @@ Create `CachingPersonAdminUseCase`: ```java package com.ludovictemgoua.imdb.infrastructure.cache; -import com.ludovictemgoua.imdb.application.CreatePersonRequest; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; import com.ludovictemgoua.imdb.application.PersonAdminUseCaseImpl; -import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; import com.ludovictemgoua.imdb.domain.model.PersonCore; import org.springframework.cache.annotation.CacheEvict; @@ -3927,7 +3936,7 @@ public class CachingPersonAdminUseCase implements PersonAdminUseCase { ``` Add `import com.ludovictemgoua.imdb.domain.model.PrincipalCredit;` and -`import com.ludovictemgoua.imdb.application.PrincipalRequest;` to `TitleController.java`'s imports (all the +`import com.ludovictemgoua.imdb.application.rest.PrincipalRequest;` to `TitleController.java`'s imports (all the Spring annotation imports needed here were already added in Task 3.2's cleanup). - [ ] **Step 7: Run the full unit and integration suites** @@ -3962,9 +3971,7 @@ specific previously-cached key is gone. package com.ludovictemgoua.imdb.infrastructure.cache; import com.ludovictemgoua.imdb.TestcontainersConfiguration; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.RatingRequest; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; @@ -4004,7 +4011,7 @@ class CacheEvictionIntegrationTest { assertThat(cacheManager.getCache("title-detail").get("tt0000100")).isNotNull(); var current = titleDetailUseCase.getDetail("tt0000100"); - titleAdminUseCase.update("tt0000100", new UpdateTitleRequest( + titleAdminUseCase.update("tt0000100", new com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest( current.primaryTitle(), current.originalTitle(), current.titleType(), current.startYear(), current.endYear(), current.runtimeMinutes(), current.genres(), 0)); @@ -4028,7 +4035,7 @@ class CacheEvictionIntegrationTest { // and call sixDegreesUseCase.compute("nm0000001", "nm0000002", 7) here, then assert // cacheManager.getCache("six-degrees").get("1-2") is not null (matching the "min-max" key // convention, LLD §6) before calling personAdminUseCase.patch(...) below and re-asserting null. - personAdminUseCase.patch("nm0000001", new PatchPersonRequest("Kevin Bacon Jr.", null, null, List.of(), 0)); + personAdminUseCase.patch("nm0000001", new com.ludovictemgoua.imdb.application.rest.PatchPersonRequest("Kevin Bacon Jr.", null, null, List.of(), 0)); assertThat(cacheManager.getCache("six-degrees").get("1-2")).isNull(); } @@ -4612,8 +4619,7 @@ Expected: FAIL - `WatchlistController` doesn't exist yet. ```java package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.AddWatchlistItemRequest; -import com.ludovictemgoua.imdb.application.VisibilityRequest; +import com.ludovictemgoua.imdb.application.rest.AddWatchlistItemRequest; import com.ludovictemgoua.imdb.application.contracts.WatchlistUseCase; import com.ludovictemgoua.imdb.domain.model.WatchlistView; import com.ludovictemgoua.imdb.infrastructure.security.CurrentUser; @@ -4656,7 +4662,7 @@ public class WatchlistController { } @PutMapping("/api/v1/watchlist/visibility") - public void updateVisibility(Authentication authentication, @Valid @RequestBody VisibilityRequest request) { + public void updateVisibility(Authentication authentication, @Valid @RequestBody com.ludovictemgoua.imdb.application.rest.VisibilityRequest request) { watchlistUseCase.updateVisibility(CurrentUser.requireId(authentication), request.visibility()); } @@ -5022,6 +5028,7 @@ git commit -m "Add reviews table and ReviewRepository" ```java package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.model.Review; import com.ludovictemgoua.imdb.domain.repository.ReviewRepository; @@ -5086,7 +5093,7 @@ public record ReviewRequest(@Min(1) @Max(10) int rating, String body, int versio ```java package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.Review; @@ -5096,7 +5103,7 @@ public interface ReviewUseCase { Review getMine(int userId, String titleId); - Review update(int userId, String titleId, ReviewRequest request); + Review update(int userId, String titleId, com.ludovictemgoua.imdb.application.rest.ReviewRequest request); void delete(int userId, String titleId, int expectedVersion); @@ -5110,6 +5117,7 @@ public interface ReviewUseCase { package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PagedResult; @@ -5273,12 +5281,11 @@ Expected: FAIL initially with compile errors everywhere `new TitleDetail(...)` o ```java package com.ludovictemgoua.imdb.infrastructure.cache; -import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.application.ReviewUseCaseImpl; import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.Review; -import com.ludovictemgoua.imdb.utils.ImdbIds; import org.springframework.cache.annotation.CacheEvict; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Service; @@ -5333,7 +5340,7 @@ public class CachingReviewUseCase implements ReviewUseCase { ```java package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.Review; @@ -5973,8 +5980,6 @@ public record AddListItemRequest(@NotBlank String titleId) { ```java package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.CreateListRequest; -import com.ludovictemgoua.imdb.application.UpdateListRequest; import com.ludovictemgoua.imdb.domain.model.CustomList; import com.ludovictemgoua.imdb.domain.model.CustomListView; import com.ludovictemgoua.imdb.domain.model.PagedResult; @@ -5983,7 +5988,7 @@ import java.util.Optional; public interface ListUseCase { - CustomList create(int userId, CreateListRequest request); + CustomList create(int userId, com.ludovictemgoua.imdb.application.rest.CreateListRequest request); CustomListView getById(int listId, Optional viewerUserId); @@ -5991,7 +5996,7 @@ public interface ListUseCase { PagedResult getPublic(int page, int size); - void update(int listId, int userId, UpdateListRequest request); + void update(int listId, int userId, com.ludovictemgoua.imdb.application.rest.UpdateListRequest request); void delete(int listId, int userId, int expectedVersion); @@ -6005,6 +6010,8 @@ public interface ListUseCase { package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.ListUseCase; +import com.ludovictemgoua.imdb.application.rest.CreateListRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateListRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; @@ -6177,9 +6184,8 @@ Expected: FAIL - `ListController` doesn't exist yet. ```java package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.AddListItemRequest; -import com.ludovictemgoua.imdb.application.CreateListRequest; -import com.ludovictemgoua.imdb.application.UpdateListRequest; +import com.ludovictemgoua.imdb.application.rest.AddListItemRequest; +import com.ludovictemgoua.imdb.application.rest.CreateListRequest; import com.ludovictemgoua.imdb.application.contracts.ListUseCase; import com.ludovictemgoua.imdb.domain.model.CustomList; import com.ludovictemgoua.imdb.domain.model.CustomListView; @@ -6240,7 +6246,7 @@ public class ListController { @PutMapping("/{listId}") public void update(Authentication authentication, @PathVariable int listId, - @Valid @RequestBody UpdateListRequest request) { + @Valid @RequestBody com.ludovictemgoua.imdb.application.rest.UpdateListRequest request) { listUseCase.update(listId, CurrentUser.requireId(authentication), request); } @@ -6253,7 +6259,7 @@ public class ListController { @PostMapping("/{listId}/items") @ResponseStatus(HttpStatus.CREATED) public void addItem(Authentication authentication, @PathVariable int listId, - @Valid @RequestBody AddListItemRequest request) { + @Valid @RequestBody AddListItemRequest request) { listUseCase.addItem(listId, CurrentUser.requireId(authentication), request.titleId()); } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java index 116548a..6a50e5e 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/AuthUseCaseImpl.java @@ -1,6 +1,9 @@ package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; +import com.ludovictemgoua.imdb.application.rest.TokenPair; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; import com.ludovictemgoua.imdb.domain.model.Role; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/ListUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/ListUseCaseImpl.java index a8058f7..1af17a8 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/ListUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/ListUseCaseImpl.java @@ -1,6 +1,8 @@ package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.ListUseCase; +import com.ludovictemgoua.imdb.application.rest.CreateListRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateListRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImpl.java index c6beeef..2536f11 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImpl.java @@ -1,6 +1,9 @@ package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PersonCore; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImpl.java index c153dd7..4468f9a 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImpl.java @@ -1,6 +1,7 @@ package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PagedResult; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java deleted file mode 100644 index 3e26984..0000000 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesResult.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.ludovictemgoua.imdb.application; - -import java.util.List; - -public record SixDegreesResult(PersonRef personA, PersonRef personB, Integer degree, - boolean withinRequestedMax, List path) { -} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java index bb9c410..83a16bf 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/SixDegreesUseCaseImpl.java @@ -2,6 +2,9 @@ import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase; +import com.ludovictemgoua.imdb.application.rest.PathStep; +import com.ludovictemgoua.imdb.application.rest.PersonRef; +import com.ludovictemgoua.imdb.application.rest.SixDegreesResult; import com.ludovictemgoua.imdb.domain.model.GraphPath; import com.ludovictemgoua.imdb.domain.model.PersonResolution; import com.ludovictemgoua.imdb.domain.model.SharedTitle; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImpl.java index cba34c2..e0e9ec2 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImpl.java @@ -1,6 +1,7 @@ package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; +import com.ludovictemgoua.imdb.application.rest.*; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PrincipalCredit; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java index c507a47..bc043a9 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/UserUseCaseImpl.java @@ -1,6 +1,7 @@ package com.ludovictemgoua.imdb.application; import com.ludovictemgoua.imdb.application.contracts.UserUseCase; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PagedResult; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/AuthUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/AuthUseCase.java index fecd8a3..395cdcc 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/AuthUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/AuthUseCase.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.LoginRequest; -import com.ludovictemgoua.imdb.application.RegisterRequest; -import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; +import com.ludovictemgoua.imdb.application.rest.TokenPair; public interface AuthUseCase { diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ListUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ListUseCase.java index f981f91..89b2a2f 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ListUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ListUseCase.java @@ -1,7 +1,7 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.CreateListRequest; -import com.ludovictemgoua.imdb.application.UpdateListRequest; +import com.ludovictemgoua.imdb.application.rest.CreateListRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateListRequest; import com.ludovictemgoua.imdb.domain.model.CustomList; import com.ludovictemgoua.imdb.domain.model.CustomListView; import com.ludovictemgoua.imdb.domain.model.PagedResult; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/PersonAdminUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/PersonAdminUseCase.java index db133fa..b6a0163 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/PersonAdminUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/PersonAdminUseCase.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.CreatePersonRequest; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; -import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.domain.model.PersonCore; public interface PersonAdminUseCase { diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ReviewUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ReviewUseCase.java index 2902fd3..0415052 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ReviewUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/ReviewUseCase.java @@ -1,6 +1,6 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.Review; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java index c84a1d3..57e0da2 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/SixDegreesOutcome.java @@ -1,6 +1,6 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.SixDegreesResult; +import com.ludovictemgoua.imdb.application.rest.SixDegreesResult; import com.ludovictemgoua.imdb.domain.model.PersonCandidate; import java.util.List; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleAdminUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleAdminUseCase.java index f7ff6ba..465c53a 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleAdminUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/TitleAdminUseCase.java @@ -1,11 +1,11 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.CreateTitleRequest; -import com.ludovictemgoua.imdb.application.CrewRequest; -import com.ludovictemgoua.imdb.application.PatchTitleRequest; -import com.ludovictemgoua.imdb.application.PrincipalRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CrewRequest; +import com.ludovictemgoua.imdb.application.rest.PatchTitleRequest; +import com.ludovictemgoua.imdb.application.rest.PrincipalRequest; +import com.ludovictemgoua.imdb.application.rest.RatingRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.domain.model.PrincipalCredit; import com.ludovictemgoua.imdb.domain.model.TitleCore; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java index 248ad3b..62cd48e 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/contracts/UserUseCase.java @@ -1,6 +1,6 @@ package com.ludovictemgoua.imdb.application.contracts; -import com.ludovictemgoua.imdb.application.UpdateProfileRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; import com.ludovictemgoua.imdb.domain.model.Role; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AddListItemRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/AddListItemRequest.java similarity index 69% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/AddListItemRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/AddListItemRequest.java index 2e1d56a..0237a43 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AddListItemRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/AddListItemRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AddWatchlistItemRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/AddWatchlistItemRequest.java similarity index 70% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/AddWatchlistItemRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/AddWatchlistItemRequest.java index 867d121..b1c68cc 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/AddWatchlistItemRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/AddWatchlistItemRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CreateListRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreateListRequest.java similarity index 82% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/CreateListRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreateListRequest.java index 5374807..40b8b9e 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CreateListRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreateListRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import com.ludovictemgoua.imdb.domain.model.Visibility; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CreatePersonRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreatePersonRequest.java similarity index 83% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/CreatePersonRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreatePersonRequest.java index 3739da4..7cf642d 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CreatePersonRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreatePersonRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CreateTitleRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreateTitleRequest.java similarity index 87% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/CreateTitleRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreateTitleRequest.java index 6021ffa..1b294b2 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CreateTitleRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CreateTitleRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CrewRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CrewRequest.java similarity index 66% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/CrewRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CrewRequest.java index eadddca..2676dce 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/CrewRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/CrewRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import java.util.List; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/LoginRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/LoginRequest.java similarity index 78% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/LoginRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/LoginRequest.java index c23835c..b837746 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/LoginRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/LoginRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PatchPersonRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PatchPersonRequest.java similarity index 79% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/PatchPersonRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PatchPersonRequest.java index c1e0a2a..ec69bcd 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PatchPersonRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PatchPersonRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import java.util.List; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PatchTitleRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PatchTitleRequest.java similarity index 90% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/PatchTitleRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PatchTitleRequest.java index ae18dc8..4a72f24 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PatchTitleRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PatchTitleRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import java.util.List; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PathStep.java similarity index 72% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PathStep.java index d5733be..21b9661 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PathStep.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PathStep.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import com.ludovictemgoua.imdb.domain.model.SharedTitle; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PersonRef.java similarity index 51% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PersonRef.java index ac31063..375b1bf 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PersonRef.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PersonRef.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; public record PersonRef(String id, String name) { } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PrincipalRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PrincipalRequest.java similarity index 83% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/PrincipalRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PrincipalRequest.java index c6c3bac..458b5c4 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/PrincipalRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/PrincipalRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/RatingRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RatingRequest.java similarity index 85% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/RatingRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RatingRequest.java index 0661a45..7bf9672 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/RatingRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RatingRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMin; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/RegisterRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RegisterRequest.java similarity index 85% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/RegisterRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RegisterRequest.java index 08e66ea..fa2ece7 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/RegisterRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RegisterRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/ReviewRequest.java similarity index 77% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/ReviewRequest.java index cbc6132..ab58ade 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/ReviewRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/ReviewRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.Max; import jakarta.validation.constraints.Min; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/RoleRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RoleRequest.java similarity index 74% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/RoleRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RoleRequest.java index cf9daf2..76b1554 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/RoleRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/RoleRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import com.ludovictemgoua.imdb.domain.model.Role; import jakarta.validation.constraints.NotNull; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/SixDegreesResult.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/SixDegreesResult.java new file mode 100644 index 0000000..35d8391 --- /dev/null +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/SixDegreesResult.java @@ -0,0 +1,7 @@ +package com.ludovictemgoua.imdb.application.rest; + +import java.util.List; + +public record SixDegreesResult(PersonRef personA, PersonRef personB, Integer degree, + boolean withinRequestedMax, List path) { +} diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TokenPair.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/TokenPair.java similarity index 58% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/TokenPair.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/TokenPair.java index 9283b2d..9353595 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/TokenPair.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/TokenPair.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; public record TokenPair(String accessToken, String refreshToken) { } diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateListRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateListRequest.java similarity index 83% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateListRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateListRequest.java index 8c8d299..3e0bfdc 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateListRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateListRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import com.ludovictemgoua.imdb.domain.model.Visibility; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdatePersonRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdatePersonRequest.java similarity index 83% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdatePersonRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdatePersonRequest.java index 5c95e1f..6c94873 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdatePersonRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdatePersonRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateProfileRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateProfileRequest.java similarity index 74% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateProfileRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateProfileRequest.java index e1d7a56..fcfd907 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateProfileRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateProfileRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateTitleRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateTitleRequest.java similarity index 87% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateTitleRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateTitleRequest.java index 0b1eaca..1717a34 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/UpdateTitleRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/UpdateTitleRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import jakarta.validation.constraints.NotBlank; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/application/VisibilityRequest.java b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/VisibilityRequest.java similarity index 77% rename from imdb/src/main/java/com/ludovictemgoua/imdb/application/VisibilityRequest.java rename to imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/VisibilityRequest.java index 212cc75..8bdcf1a 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/application/VisibilityRequest.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/application/rest/VisibilityRequest.java @@ -1,4 +1,4 @@ -package com.ludovictemgoua.imdb.application; +package com.ludovictemgoua.imdb.application.rest; import com.ludovictemgoua.imdb.domain.model.Visibility; import jakarta.validation.constraints.NotNull; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingPersonAdminUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingPersonAdminUseCase.java index c41736d..8696062 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingPersonAdminUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingPersonAdminUseCase.java @@ -1,9 +1,9 @@ package com.ludovictemgoua.imdb.infrastructure.cache; -import com.ludovictemgoua.imdb.application.CreatePersonRequest; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; import com.ludovictemgoua.imdb.application.PersonAdminUseCaseImpl; -import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; import com.ludovictemgoua.imdb.domain.model.PersonCore; import org.springframework.cache.annotation.CacheEvict; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingReviewUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingReviewUseCase.java index 326dd10..74d109f 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingReviewUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingReviewUseCase.java @@ -1,6 +1,6 @@ package com.ludovictemgoua.imdb.infrastructure.cache; -import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.application.ReviewUseCaseImpl; import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; import com.ludovictemgoua.imdb.domain.model.PagedResult; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java index 4024f0e..b2fc9f3 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/infrastructure/cache/CachingTitleAdminUseCase.java @@ -1,12 +1,12 @@ package com.ludovictemgoua.imdb.infrastructure.cache; -import com.ludovictemgoua.imdb.application.CreateTitleRequest; -import com.ludovictemgoua.imdb.application.CrewRequest; -import com.ludovictemgoua.imdb.application.PatchTitleRequest; -import com.ludovictemgoua.imdb.application.PrincipalRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CrewRequest; +import com.ludovictemgoua.imdb.application.rest.PatchTitleRequest; +import com.ludovictemgoua.imdb.application.rest.PrincipalRequest; +import com.ludovictemgoua.imdb.application.rest.RatingRequest; import com.ludovictemgoua.imdb.application.TitleAdminUseCaseImpl; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; import com.ludovictemgoua.imdb.domain.model.PrincipalCredit; import com.ludovictemgoua.imdb.domain.model.TitleCore; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java index a9a691a..d103e82 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/AuthController.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.LoginRequest; -import com.ludovictemgoua.imdb.application.RegisterRequest; -import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; +import com.ludovictemgoua.imdb.application.rest.TokenPair; import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ListController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ListController.java index c93a119..241d79b 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ListController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ListController.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.AddListItemRequest; -import com.ludovictemgoua.imdb.application.CreateListRequest; -import com.ludovictemgoua.imdb.application.UpdateListRequest; +import com.ludovictemgoua.imdb.application.rest.AddListItemRequest; +import com.ludovictemgoua.imdb.application.rest.CreateListRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateListRequest; import com.ludovictemgoua.imdb.application.contracts.ListUseCase; import com.ludovictemgoua.imdb.domain.model.CustomList; import com.ludovictemgoua.imdb.domain.model.CustomListView; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java index 06dd1f6..9106f94 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/PersonController.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.CreatePersonRequest; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; -import com.ludovictemgoua.imdb.application.UpdatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ReviewController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ReviewController.java index eba8eb6..572955b 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ReviewController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/ReviewController.java @@ -1,6 +1,6 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.ReviewRequest; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.application.contracts.ReviewUseCase; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.Review; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java index 65c277f..f25f597 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/TitleController.java @@ -1,11 +1,11 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.CreateTitleRequest; -import com.ludovictemgoua.imdb.application.CrewRequest; -import com.ludovictemgoua.imdb.application.PatchTitleRequest; -import com.ludovictemgoua.imdb.application.PrincipalRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.CrewRequest; +import com.ludovictemgoua.imdb.application.rest.PatchTitleRequest; +import com.ludovictemgoua.imdb.application.rest.PrincipalRequest; +import com.ludovictemgoua.imdb.application.rest.RatingRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; import com.ludovictemgoua.imdb.application.contracts.TitleDetailUseCase; import com.ludovictemgoua.imdb.application.contracts.TitleSearchUseCase; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java index 24f16ef..d777d1c 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/UserController.java @@ -1,7 +1,7 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.RoleRequest; -import com.ludovictemgoua.imdb.application.UpdateProfileRequest; +import com.ludovictemgoua.imdb.application.rest.RoleRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.application.contracts.UserUseCase; import com.ludovictemgoua.imdb.domain.model.PagedResult; import com.ludovictemgoua.imdb.domain.model.PublicUserProfile; diff --git a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/WatchlistController.java b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/WatchlistController.java index 1cdd246..647b09a 100644 --- a/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/WatchlistController.java +++ b/imdb/src/main/java/com/ludovictemgoua/imdb/presentation/WatchlistController.java @@ -1,7 +1,7 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.AddWatchlistItemRequest; -import com.ludovictemgoua.imdb.application.VisibilityRequest; +import com.ludovictemgoua.imdb.application.rest.AddWatchlistItemRequest; +import com.ludovictemgoua.imdb.application.rest.VisibilityRequest; import com.ludovictemgoua.imdb.application.contracts.WatchlistUseCase; import com.ludovictemgoua.imdb.domain.model.WatchlistView; import com.ludovictemgoua.imdb.infrastructure.security.CurrentUser; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java index d2b0091..07ea00f 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/AuthUseCaseImplTest.java @@ -1,5 +1,7 @@ package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.ForbiddenException; import com.ludovictemgoua.imdb.domain.model.Role; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImplTest.java index ca33b65..1e4fcd9 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImplTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/PersonAdminUseCaseImplTest.java @@ -1,5 +1,7 @@ package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.CreatePersonRequest; +import com.ludovictemgoua.imdb.application.rest.UpdatePersonRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.PersonCore; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImplTest.java index a665841..3bc1745 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImplTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/ReviewUseCaseImplTest.java @@ -1,5 +1,6 @@ package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.ReviewRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.model.Review; import com.ludovictemgoua.imdb.domain.repository.ReviewRepository; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java index f76632b..953d3d3 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/TitleAdminUseCaseImplTest.java @@ -1,5 +1,8 @@ package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.CreateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.PrincipalRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.TitleCore; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java index 35381f7..b364c67 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/application/UserUseCaseImplTest.java @@ -1,5 +1,6 @@ package com.ludovictemgoua.imdb.application; +import com.ludovictemgoua.imdb.application.rest.UpdateProfileRequest; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import com.ludovictemgoua.imdb.domain.exception.NotFoundException; import com.ludovictemgoua.imdb.domain.model.Role; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheEvictionIntegrationTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheEvictionIntegrationTest.java index f88cda4..765aede 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheEvictionIntegrationTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/infrastructure/cache/CacheEvictionIntegrationTest.java @@ -1,9 +1,9 @@ package com.ludovictemgoua.imdb.infrastructure.cache; import com.ludovictemgoua.imdb.TestcontainersConfiguration; -import com.ludovictemgoua.imdb.application.PatchPersonRequest; -import com.ludovictemgoua.imdb.application.RatingRequest; -import com.ludovictemgoua.imdb.application.UpdateTitleRequest; +import com.ludovictemgoua.imdb.application.rest.PatchPersonRequest; +import com.ludovictemgoua.imdb.application.rest.RatingRequest; +import com.ludovictemgoua.imdb.application.rest.UpdateTitleRequest; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase; import com.ludovictemgoua.imdb.application.contracts.TitleAdminUseCase; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java index 8bc5dd8..129ff48 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/AuthControllerTest.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.LoginRequest; -import com.ludovictemgoua.imdb.application.RegisterRequest; -import com.ludovictemgoua.imdb.application.TokenPair; +import com.ludovictemgoua.imdb.application.rest.LoginRequest; +import com.ludovictemgoua.imdb.application.rest.RegisterRequest; +import com.ludovictemgoua.imdb.application.rest.TokenPair; import com.ludovictemgoua.imdb.application.contracts.AuthUseCase; import com.ludovictemgoua.imdb.domain.exception.ConflictException; import tools.jackson.databind.ObjectMapper; diff --git a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java index 2da2a48..e0000c9 100644 --- a/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java +++ b/imdb/src/test/java/com/ludovictemgoua/imdb/presentation/PersonControllerTest.java @@ -1,8 +1,8 @@ package com.ludovictemgoua.imdb.presentation; -import com.ludovictemgoua.imdb.application.PathStep; -import com.ludovictemgoua.imdb.application.PersonRef; -import com.ludovictemgoua.imdb.application.SixDegreesResult; +import com.ludovictemgoua.imdb.application.rest.PathStep; +import com.ludovictemgoua.imdb.application.rest.PersonRef; +import com.ludovictemgoua.imdb.application.rest.SixDegreesResult; import com.ludovictemgoua.imdb.application.contracts.PersonAdminUseCase; import com.ludovictemgoua.imdb.application.contracts.SixDegreesOutcome; import com.ludovictemgoua.imdb.application.contracts.SixDegreesUseCase;

-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 z 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