{"id":51440490,"url":"https://github.com/target/tech-case-studies","last_synced_at":"2026-07-05T11:01:19.163Z","repository":{"id":363381208,"uuid":"1239102908","full_name":"target/tech-case-studies","owner":"target","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-25T16:21:04.000Z","size":312,"stargazers_count":2,"open_issues_count":3,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-25T17:23:04.938Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/target.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-14T19:05:50.000Z","updated_at":"2026-06-25T16:18:49.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/target/tech-case-studies","commit_stats":null,"previous_names":["target/tech-case-studies"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/target/tech-case-studies","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/target%2Ftech-case-studies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/target%2Ftech-case-studies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/target%2Ftech-case-studies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/target%2Ftech-case-studies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/target","download_url":"https://codeload.github.com/target/tech-case-studies/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/target%2Ftech-case-studies/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35151638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-05T11:01:18.204Z","updated_at":"2026-07-05T11:01:19.151Z","avatar_url":"https://github.com/target.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tech-case-studies\n\n## Overview\n\nA collection of containerized microservices used for technical interviews. Candidates pull the images (or build from source), run them locally, and build client applications against their APIs. All data is synthetic.\n\n## Services\n\n| Service      | Port | Description                                                                                              |\n| ------------ | ---- | -------------------------------------------------------------------------------------------------------- |\n| product  | 8080 | Read-only REST API serving synthetic product catalog, pricing, and inventory availability                |\n| cart | 8081 | Shopping cart REST API with CRUD operations. Calls product at runtime for item and price enrichment. |\n\n**Note:** All data returned by these services is mocked/sample data intended for interviewing purposes only. It does not represent real or production retail data.\n\n## Running the application\n\n### Option 1: docker compose (recommended)\n\nBuild and run both services together:\n\n```sh\n./gradlew clean build\ndocker compose build\ndocker compose up\n```\n\nThe services will be available at:\n\n- product: \u003chttp://localhost:8080/product/v1/\u003e\n- cart: \u003chttp://localhost:8081/cart/v1/\u003e\n\nTo stop the services:\n\n```sh\ndocker compose down\n```\n\n### Option 2: docker run (individual services)\n\nBuild and run each service separately. Note that cart depends on product, so product must be running first.\n\n```sh\n# Build both JARs\n./gradlew clean build\n\n# Build and run product\ndocker build -t product product/\ndocker run -d -p 8080:8080 --name product product\n\n# Build and run cart\ndocker build -t cart cart/\ndocker run -p 8081:8081 --name cart --link product:product cart\n```\n\n### OpenAPI specs\n\nBoth services expose Swagger UI and OpenAPI docs:\n\n| Service      | Swagger UI                                    | API docs                         |\n| ------------ | --------------------------------------------- | -------------------------------- |\n| product  | \u003chttp://localhost:8080/swagger-ui/index.html\u003e | \u003chttp://localhost:8080/docs\u003e |\n| cart | \u003chttp://localhost:8081/swagger-ui/index.html\u003e | \u003chttp://localhost:8081/docs\u003e |\n\nHTTP request files for use with IntelliJ or VS Code are available at:\n\n- `product/product.http`\n- `cart/cart.http`\n\n## product endpoints\n\n### Get price\n\n**`GET /product/v1/prices/{id}`**\n\n```sh\ncurl -X GET \"http://localhost:8080/product/v1/prices/123456\"\n```\n\n### Get item\n\n**`GET /product/v1/items/{id}`**\n\n```sh\ncurl -X GET \"http://localhost:8080/product/v1/items/123456\"\n```\n\n### List items\n\n**`GET /product/v1/items`**\n\nSupports filtering by `small_description` query parameter.\n\n```sh\ncurl -X GET \"http://localhost:8080/product/v1/items\"\ncurl -X GET \"http://localhost:8080/product/v1/items?small_description=jersey\"\n```\n\n### Get availability\n\n**`GET /product/v1/availability/{id}`**\n\n```sh\ncurl -X GET \"http://localhost:8080/product/v1/availability/123456\"\n```\n\n## cart endpoints\n\ncart depends on product at runtime. When a cart is read, the service calls product over HTTP to enrich each line item with product details and pricing. It then calculates taxes (by product category) and delivery charges.\n\n### Get cart\n\n**`GET /cart/v1/carts/{id}`**\n\n```sh\ncurl 'http://localhost:8081/cart/v1/carts/100' -i -X GET\n```\n\n### Create cart\n\n**`POST /cart/v1/carts`**\n\nRequest body: array of objects with `item_id` (string) and `quantity` (integer).\n\n```sh\ncurl 'http://localhost:8081/cart/v1/carts' -i -X POST \\\n  -H 'Content-Type: application/json' \\\n  -d '[\n    {\"item_id\" : \"123456\", \"quantity\": 1},\n    {\"item_id\" : \"789123\", \"quantity\": 2}\n  ]'\n```\n\n### Add item to cart\n\n**`POST /cart/v1/carts/{id}/items`**\n\n```sh\ncurl 'http://localhost:8081/cart/v1/carts/100/items' -i -X POST \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"item_id\" : \"456788\", \"quantity\": 2}'\n```\n\n### Update item quantity\n\n**`PATCH /cart/v1/carts/{id}/items/{item_id}`**\n\n```sh\ncurl 'http://localhost:8081/cart/v1/carts/100/items/456788' -i -X PATCH \\\n  -H 'Content-Type: application/json' \\\n  -d '{\"quantity\": 3}'\n```\n\n### Remove item from cart\n\n**`DELETE /cart/v1/carts/{id}/items/{item_id}`**\n\nRemoving the last item from a cart also removes the cart.\n\n```sh\ncurl 'http://localhost:8081/cart/v1/carts/100/items/456788' -i -X DELETE\n```\n\n## Customizing data\n\nYou can customize the data returned by product by creating your own CSV files and mounting them into the container. See [product/data-formats.md](product/data-formats.md) for details.\n\n## Induced behaviors (latency and failure simulation)\n\nBoth services support configurable induced behaviors that simulate latency and failures. By setting the `DEFAULT_BEHAVIOR` environment variable, you can run the same APIs in different modes (normal, slow, or randomly failing) without changing any code.\n\nSee [product/induced_behaviors.md](product/induced_behaviors.md) for available modes, environment variables, and usage examples.\n\n## Performance benchmarking\n\nA startup time benchmarking script is available at `product/scripts/benchmark-startup.sh`. See `product/scripts/README.md` for usage details.\n\n## Project structure\n\n```txt\ntech-case-studies/\n  product/                 # Read-only data API (port 8080)\n    src/\n    Dockerfile\n    build.gradle.kts\n  cart/                # Shopping cart API (port 8081)\n    src/\n    Dockerfile\n    build.gradle.kts\n  docker-compose.yml           # Orchestrates both services\n  build.gradle.kts             # Root Gradle build (shared config)\n  settings.gradle.kts          # Multi-project includes\n  gradle/libs.versions.toml    # Shared dependency versions\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftarget%2Ftech-case-studies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftarget%2Ftech-case-studies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftarget%2Ftech-case-studies/lists"}