food-truck

module
v0.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 24, 2022 License: MIT

README ยถ

๐Ÿ–๐Ÿคค Food Truck Engineering Challenge ๐Ÿ”๐Ÿšš

This repo is the output of my work on the Food Truck - Take Home Engineering Challenge

๐Ÿ“ Design & Architecture Notes

Here is a outline of some of the key decisions, trade offs, limitations & choices to this point in the project

Components & Features
  • Backend REST API server & host for frontend JS app. This is written in Go.

    Note: Co-hosting like this is preferred to prevent CORS issues, when we don't have a layer-7 routing service in front

  • Frontend JS application, written in vanilla JS
    • Frontend uses Azure Maps for visualization
  • Dockerfile to build the service + frontend as a container
  • Auto generated OpenAPI / Swagger support, with SwaggerUI
  • Middleware for CORS, logging, health checks and Prometheus metrics
  • Makefile to assist with local development and CI/CD, includes:
    • Linting with golangci-lint
    • Local hot reload with cosmtrek/air
    • Build, tag & push container images
  • Unit & integration tests
  • Runnable images are hosted here on GitHub Container Registry
  • Bicep template for deployment to Azure running as a Azure Container App
  • Dev Container with all required tooling, to support local development
  • Performance and black box REST API tests using k6
Project Structure
  • The repo adopts the "Standard Go Project Layout" which can be unfamiliar to those that have not worked with Go. A full breakdown of the repo structure is provided below
  • In addition several of my own open source projects were used to bring many reuseable assets, boilerplate and working source code:
  • The breaking up of the API code into many packages, interfaces and multiple source files was probably overkill at this point (with single endpoint etc) However it provided a common set of abstractions (routing, services, middleware, data-handlers) and also importantly testability
Data
  • SQLite DB was used rather than a CSV file, this was sourced from here https://san-francisco.datasettes.com/food-trucks. A full blown database service was felt to be overkill for the assignment but being able to use SQL queries represented a reasonable degree of "realism".
  • SQLite is very fast & powerful, but it's a extremely bad choice for a backend service with CRUD, so this decision was purely tactical and doesn't represent best/recommended practice.
  • There are some duplicates in the database, with the same name, lat & long but different IDs. This can result in less than 5 trucks being shown on the map even when 5 or more are present in the data returned from the API.
Front End
  • Purposefully kept very clean/simple, no framework required. Vue.js or React would be overkill at this point. Alpine.js was considered but with no reactive components in the app, even this minimal library would be too much.
  • Vanilla "modern" JS was used, with ES5 modules allowing code structuring and fetch for API calls.
API
  • Classic REST API, using HTTP.
  • Only queries & GETs are used with a single /trucks endpoint.
  • See api/spec.yaml for the OpenAPI description of the API, this is auto generated.
  • See the API docs for further details
Limitations, Known Issues & Backlog
  • The query for finding nearby trucks is extremely sub-optimal and a borderline hack. Switching to a database service with spatial support like Cosmos, PostgreSQL or Azure SQL should be the highest priority.
  • Fix the leaky/poor abstraction in the database spec & improve the unit testing method.
  • Auth key to Azure Maps should be fetched with API, not baked into frontend code. DONE!
  • GitHub Actions for CI & CD
    • Automate builds DONE!
    • Automate tests DONE!
  • Rate limiting on the API (should use a upstream traffic gateway, e.g. ingress controller in Kubernetes NGINX/Envoy or Azure service like App Gateway).
  • Auth in front of the API (likewise this should be handled by the gateway to do JWT validation etc).
  • Sem ver for images and releases.
  • Add CLI tool
  • Add end to end API & performance tests, k6.io is my tool of choice for this, or Postman/Newman.
  • Switch to RFC 7807 (Problem Details) for API errors https://datatracker.ietf.org/doc/html/rfc7807
  • Consider switching to dependency injection but should weigh up the pros & cons.
  • Add rest of the application functionality ;)

The rest of the readme follows in a format similar to one I use on my many open source projects on GitHub


๐Ÿšš Food Truck Application

๐Ÿƒโ€โ™‚๏ธ Getting Started

The makefile is the main starting point for working with this project, simply calling make will provide this help text. If you are using a system without access to make, I suggest using the provided dev container.

help                 ๐Ÿ’ฌ This help message :)
lint                 ๐ŸŒŸ Lint & format, will not fix but sets exit code on error
lint-fix             ๐Ÿ” Lint & format, will try to fix errors and modify code
image                ๐Ÿ“ฆ Build container image from Dockerfile
push                 ๐Ÿ“ค Push container image to registry
build                ๐Ÿ”จ Run a local build without a container
run                  ๐Ÿƒ Run server & frontend host, with hot reload for local dev
install-tools        ๐Ÿ”ฎ Install dev tools
generate             ๐Ÿ”ฌ Generate Swagger / OpenAPI spec
test                 ๐Ÿงช Run unit and integration tests
test-perf            ๐Ÿ“ˆ Run performance tests
deploy               ๐Ÿš€ Deploy to Azure using Bicep & Azure CLI

๐Ÿš€ Installing / Deploying

Deploy to Azure using make deploy this will deploy to Azure Container Apps (NOTE: only certain regions presently supported) plus the Azure Maps account. Set AZURE_IMAGE variable when running make deploy in order to deploy your own image, otherwise ghcr.io/benc-uk/food-truck:latest will be used.

Deployment is done through Bicep with a set of template & modules. You will need Azure CLI with the Bicep add-on installed.

๐Ÿƒ Running Locally

Before running locally you will need to deploy Azure Maps account in Azure and obtain the shared access key. This can easily be done with the Azure CLI, e.g.

RES_GROUP=__CHANGE_ME__
az maps account create --name food-truck-maps --resource-group $RES_GROUP --kind Gen2 --sku G2
echo Access key is: $(az maps account keys list --name food-truck-maps --resource-group $RES_GROUP --query primaryKey -o tsv)

๐Ÿ“ฆ Running as a container

  • PRE-REQS: Docker engine installed locally and Docker CLI
  • Build the images locally make image
    • Be sure to override and set your own IMAGE_REG and IMAGE_REPO e.g. make image IMAGE_REPO=myfoodtruck
  • ALTERNATIVELY: Run the public image directly using
docker run --rm -it -p 8080:8080 \
  -e AZURE_MAPS_KEY=__YOUR_MAPS_KEY__ \
  ghcr.io/benc-uk/food-truck:latest

๐Ÿ“ NOTE! When running in a container the frontend is served from a different path, /app/ so to access it locally use http://localhost:8080/app/ (Note the trailing slash!)

๐Ÿ’ป Running using Go

If you do not have Go installed, then open the repo the provided dev container, this has all the tools you will need

Copy .env.sample to .env and edit the file, setting AZURE_MAPS_KEY to the correct value.

Now run the server and backend API using:

make run

Access the app using http://localhost:8080/app/

๐Ÿงช Running Tests

Run the integration tests and unit tests with:

make test

๐Ÿ—๏ธ Architecture

Standard SPA (Single Page Application) style frontend with REST backend

                   โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                   โ”‚             CONTAINER             โ”‚
 โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”     โ”‚ โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚
 โ”‚           โ”‚HTTP โ”‚ โ”‚             โ”œโ”€โ”€โ”€โ”€โ–บ            โ”‚ โ”‚
 โ”‚ FRONTEND  โ”œโ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ–บ  REST API   โ”‚    โ”‚  SQLITE DB โ”‚ โ”‚
 โ”‚ (BROWSER) โ”‚     โ”‚ โ”‚             โ—„โ”€โ”€โ”€โ”€โ”ค            โ”‚ โ”‚
 โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜     โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚
                   โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

๐Ÿ”ง Configuration

The following env vars are used by the backend server. .env (aka dotenv) is looked for and loaded when working locally

Setting / Variable Purpose Default
AZURE_MAPS_KEY Azure Maps shared access key None
PORT Port the server will listen on 8080
DATABASE_PATH Path to the database file "./data/food-trucks.db"
FRONTEND_DIR Where the frontend HTML/JS is located for static serving "./web/client"

๐Ÿ“‚ Repository Structure

A brief description of the top-level directories of this project is as follows:

โ”œโ”€โ”€ api          - API spec and docs
โ”œโ”€โ”€ build        - Build assets, Dockerfiles etc
โ”œโ”€โ”€ cmd          - Go source for executables, main server is here
โ”œโ”€โ”€ data         - Application data, SQLite db file(s)
โ”œโ”€โ”€ deploy       - Deployment assets, Bicep templates to deploy to Azure
โ”œโ”€โ”€ pkg          - Go source packages
โ”‚   โ”œโ”€โ”€ api      - Base API common
โ”‚   โ”œโ”€โ”€ data     - Data layer for calling SQLite
โ”‚   โ””โ”€โ”€ trucks   - Truck API and service
โ”œโ”€โ”€ scripts      - Some helper scripts
โ”œโ”€โ”€ tests        - End to end performance tests
โ””โ”€โ”€ web
    โ””โ”€โ”€ client   - The application frontend source code

๐ŸŒ REST API

See the API documentation for full information about the food truck API(s)

To aid development work and testing a REST API file is provided api/test-api.http this requires the REST Client extension for VSCode and allows for making test calls to the API from within VSCode

Other Endpoints

  • /config - Used by the frontend to get configuration, i.e. the Azure Maps key
  • /metrics - Metrics in Prometheus format for observability
  • /status - Simple status API
  • /health - Heath check for use with Kubernetes & load balancer probes
  • /swagger - Swagger UI

๐Ÿชต Change Log

See complete change log

โš–๏ธ License

This project uses the MIT software license. See full license file

Directories ยถ

Path Synopsis
pkg
api

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL