Files
three-kid-family/README.md

5.2 KiB

Three Kid Family Application

A Spring Boot application that manages person records and identifies families matching specific criteria: couples with exactly three children where at least one child is under 18 years old.

Overview

This service processes person records in real-time, maintaining bidirectional relationship integrity between partners, parents, and children. After each record is received, it immediately determines if any stored person satisfies the "valid parent" pattern and returns all matching individuals.

Valid Parent Criteria

A person is considered a valid parent when they meet the following conditions:

  1. Has a partner - partnerId is not null
  2. Has exactly 3 children - childIds contains exactly 3 IDs
  3. Shared parenthood - All 3 children list both this person AND their partner as parents
  4. At least one minor - At least one child has a birthDate making them 18 years old or younger

Features

  • Bidirectional relationship integrity - Relationships are automatically synchronized in both directions (if A lists B as a child, B automatically lists A as a parent)
  • Real-time validation - Pattern matching occurs immediately after each upsert
  • In-memory caching - Valid parents are cached for optimal performance
  • Concurrent request handling - Method-level locking prevents race conditions
  • PostgreSQL persistence - All data is stored in a PostgreSQL database

Architecture

Key Components

  • PersonController - REST API endpoint handler
  • PersonService - Core business logic with relationship management and caching
  • PersonRepository - JPA repository for database operations
  • Person - Domain entity representing an individual with relationships

Design Decisions

Method-level locking over optimistic locking: The service uses @Locked annotations rather than database-level optimistic locking to prevent transaction conflicts when relationship graphs overlap between concurrent requests. This provides better performance for workloads with high relationship overlap.

In-memory valid parent cache: Rather than querying the database for valid parents after each upsert, the service maintains a Set<Person> cache that is incrementally updated. This reduces database load.

Related persons map pattern: The retrieveRelatedOf() method fetches all partner/parent/child entities in a single query and passes them through the call chain, avoiding N+1 queries in most scenarios.

API Reference

POST /api/v1/people

Upsert a person record and receive all currently matching valid parents.

Request Body:

{
  "id": 1,
  "name": "John Doe",
  "birthDate": "1992-03-14",
  "partner": {"id": 2},
  "parent1": {"id": 3},
  "parent2": {"id": 4},
  "children": [
    {"id": 5},
    {"id": 6},
    {"id": 7}
  ]
}

Response:

  • 200 OK - One or more valid parents exist. Returns array of all matching persons.
  • 204 No Content - No valid parents currently match the criteria.

Note: The specification requests HTTP 444, but since this is a non-standard nginx status code, the implementation returns 204 No Content instead.

DELETE /api/v1/people (Phase 2 - Not Implemented)

Delete person records and blacklist their IDs permanently.

Request Body:

[1, 2, 3]

Development Instructions

Requirements

  • Java 21+ (OpenJDK or Eclipse Temurin recommended)
  • Maven 3.9+
  • Docker & Docker Compose (for containerized deployment)
  • PostgreSQL 15 (or use Docker Compose setup)

Local Development Setup

  1. Clone the repository

    git clone <repository-url>
    cd threekidfamily
    
  2. Configure database connection (if not using Docker)

    Edit application.properties or set environment variables:

    SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/mydb
    SPRING_DATASOURCE_USERNAME=myuser
    SPRING_DATASOURCE_PASSWORD=mypassword
    
  3. Build the application

    mvn clean package
    
  4. Run tests

    mvn test
    
  5. Run locally

    mvn spring-boot:run
    

The application will be available at http://localhost:8080

Docker Deployment

The easiest way to run the application with its PostgreSQL database:

docker-compose up --build

The application will be available at http://localhost:8080

Performance Considerations

Optimizations

  • Caching strategy: Valid parents are cached in-memory and incrementally updated
  • Batch operations: Related persons are fetched in bulk to minimize database queries
  • Defensive copies: Returned collection is deep-copied to prevent external mutations

Known Limitations

  1. Phase 2 not implemented: DELETE endpoint and blacklisting functionality is not yet available
  2. HTTP 444 substitution: Returns 204 instead of the specified HTTP 444 status code
  3. MAX_RELATED_ASSUMPTION: The service assumes no single person has more than 1000 related individuals (partners, parents, children). This prevents potential memory issues.
  4. Full table scan on startup: populateCache() loads all persons into memory on startup. For very large datasets, consider implementing pagination or streaming.