Skip to content

derekvmcintire/receipt-processor

Repository files navigation

Receipt Processor Challenge

Summary

Objective: Build a web service that implements the specified API for processing receipts.

This API was built to fulfill a code challenge for Fetch Rewards. For detailed instructions and rules, refer to the fetch-rewards/receipt-processor-challenge repository.


API Overview:

Swagger UI is available at http://localhost:3000/docs with detailed API information.

  • Endpoint: /receipts/process (POST)
    • Payload: JSON receipt (retailer, purchaseDate, purchaseTime, items, total)
    • Response: JSON with a generated receipt ID.
  • Endpoint: /receipts/{id}/points (GET)
    • Response: JSON with the number of points awarded for the receipt.
  • Endpoint: /openapi.json (GET)
    • Response: JSON that represents the openapi spec used to populate the swagger ui.
  • Endpoint: / (GET)
    • Response: JSON with a string to indicate the app is running and healthy.

Technology Used:

  • TypeScript: Although the challenge preferred Go, I chose TypeScript for familiarity and confidence in delivering the solution. I plan to build this in Go later. (11/30/2024 edit: done)
  • Fastify: I wanted a lightweight, performant framework to use, since I am aware Go is generally more performant than Node.js. Although I have never used it before, I found it intuitive and easy to get something up and running quickly.
  • Docker: One of the requirements of this challenge was to use docker, so the app is available in a docker container via npm run docker:run.
  • Jest: I used jest for unit tests.
  • Swagger: I used Swagger to generate documentation UI based on an openAPI spec generated by @fastify/swagger.
  • AutoCannon: Used for benchmarking performance
  • In-memory Storage: There is no database, data is stored in a Map and will be lost if the server is restarted.

Instructions to Run the Application

Follow these steps to set up, build, and run this application:


1. Prerequisites

Make sure the following are installed on your system:

  • Node.js (v18 or higher)
  • npm (comes with Node.js)
  • Docker (if you intend to run the application in a container)

2. Clone the Repository

git clone [email protected]:derekvmcintire/receipt-processor.git
cd receipt-processor

3. Install Dependencies

Run the following command to install all necessary dependencies:

npm install

4. Run the Application Locally

You have two options to run the application: development mode or production mode.

a. Development Mode

Run the application in development mode with TypeScript support:

npm run dev

b. Production Mode

  1. Build the application:
    npx tsc
    This will compile the TypeScript code into JavaScript files in the dist folder.
  2. Start the application:
    npm start

5. Run with Docker

Getting Started

You must have Docker installed to run this API in a Docker container. If you are unfamiliar with, or need to install it, you can reference this Documentation

a. Build the Docker Image

npm run docker:build

b. Run the Docker Container

npm run docker:run

6. Run Tests

To run all tests using Jest:

npm test

7. Format and Lint the Code

a. Check Code Formatting

npm run pretty:check

b. Automatically Fix Formatting Issues

npm run pretty

c. Run ESLint to Check Code Quality

npm run lint

8. Application Features


Troubleshooting

  • If you encounter errors during development, check the logs output in the terminal.
  • Ensure the required ports (e.g., 3000) are not in use by other applications.
  • If Docker fails to run, verify your Docker installation and ensure it is running.
  • Run docker ps to see containers that are running and docker stop <id> to stop a container then docker rm <id> to remove it.
  • If it seems like things aren't quite right, try re-building docker with --no-cache, sometimes the image can get stale. npm run docker:build:no-cache

Summary of npm Scripts

Command Description
npm run dev Runs the application in development mode with live reloading.
npm start Runs the application in production mode.
npm test Runs all Jest tests.
npm run pretty Formats code using Prettier.
npm run lint Lints the code using ESLint.
npm run docker:build Builds a Docker image for the application.
npm run docker:build:no-cache Builds a Docker image without cache
npm run docker:run Runs the application inside a Docker container on port 3000.
npm run autocannon Performs a load test. Requires a URL to be provided.
npm run autocannon:process Performs a load test on receipt/process endpoint.

Technical Decisions

This project follows several architectural and technical decisions aimed at ensuring performance, maintainability, and scalability. Some of the key decisions include:

  • Language: TypeScript (chosen for familiarity and static typing)
  • API Framework: Fastify (chosen for performance, TypeScript support, and built-in schema validation)
  • Architecture: Clean Architecture (enforces separation of concerns, keeping the application layers loosely coupled and easily testable.)

For a detailed breakdown of all technical decisions, see the TECHNICAL_DECISIONS.md file.


API Performance

Performance benchmarks were set by using AutoCannon and show high throughput and low latency, which is not surprising considering the lack of a real database.

  • API Performance:
    • receipts/points endpoint: 15,744 requests/second
    • receipts/process endpoint: 13,964 requests/second

For more details, see PERFORMANCE.md.


Test Coverage

The test suite utilizes Jest for unit tests, with near-complete coverage of core business logic:

  • PointsCalculator class
  • ReceiptEntity class
  • ReceiptService class

But also includes interface and infrastructure classes:

  • controllers
  • InMemoryReceiptRepository class

Overview

Test Suites: 6

Total Tests: 26

Code Coverage:

  • Overall statement coverage: 98.31%
  • Branch coverage: 92.1%
  • Function coverage: 96.66%
  • Line coverage: 98.3%

Coverage Chart

Test coverage is categorized into key directories, showing how well each area of the code is tested. High coverage in Entities, Services, and Utilities demonstrates that the core logic and data access layers are thoroughly tested.

Test Coverage Summary

Directory % Stmts % Branch % Funcs % Lines
All files 98.31% 92.1% 96.66% 98.3%
Entities 100% 100% 100% 100%
Services 100% 100% 100% 100%
Utils 91.66% 70% 88.88% 91.66%
Repositories 100% 100% 100% 100%
Controllers 100% 100% 100% 100%

Future Considerations

  • Logging & Monitoring: Integrate logging (pino Fastify's built-in logger is one option) and set up centralized logging. Implement performance monitoring.

  • CI/CD Workflow: Set up a GitHub Actions workflow for automated testing, linting, building Docker images, and deploying to staging/production environments.

  • Security Enhancements:

    • CORS: Fastify offers @fastify/cors to restrict API access to trusted domains.
    • HTTP Headers: Fastify offers @fastify/helmet to protect http headers.
    • Rate Limiting: Fastify offers @fastify/rate-limit to prevent abuse and DoS attacks.
    • JWT Authentication: Fastify offers @fastify/jwt for user authentication.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published