wkrzywiec / farm-to-table

MIT License
3 stars 0 forks source link

Food Delivery

master GitHub GitHub issues

This application is a simplified food delivery platform, similar to Uber Eats or Glovo. It serves as a sandbox environment for experimenting with novel concepts and technologies.

Usage

With Taskfile

The easiest way to start working with a project is to run one of the tasks from the Taskfile:

task -l

Exemplary output:

* check:        Verify local tools
* dev:backend:  Run backend apps with gradle
* dev:bff:      Run 'bff' service
* dev:delivery: Run 'delivery' service
* dev:food:     Run 'food' service
* dev:ordering: Run 'ordering' service
* infra:        Spin up dockerized infrastructure
* infra:clean:  Stop and clean all persisted data
* infra:down:   Stop infrastructure
* init:         Run all services in Docker & add initial data
* run:          Run all services in Docker

In example, in order to run all services with initial data, run the command:

task init

With docker compose

If you prefer not to install or use Taskfile, you can easily run all services with a simple command:

docker compose up -d

To explore the additional commands available in the Taskfile, please refer to the Taskfile.yaml file.

Requirements

To run all services on your local machine, you will need to have Docker installed.

To develop either a backend or frontend service, you will need the following software installed:

Please note that specific versions of each software can be found within each service.

Project description

The Food Delivery app is designed as a microservice system, aiming to replicate real-world solutions in a simplified manner.

As this project serves as my sandbox for experimenting with new concepts and technologies, it will continue to evolve over time. Initially, it primarily functions as an event-driven system, with services communicating with each other based on events.

Services

The entire system is made of 5 microservices (1 React, 4 Java/Spring):

service technology Code coverage Lines of code
ui Node, React Coverage Lines of Code
bff Java, Spring Boot Coverage Lines of Code
ordering Java, Spring Boot Coverage Lines of Code
delivery Java, Spring Boot Coverage Lines of Code
food Java, Spring Boot Coverage Lines of Code

There is an additional module - commons - for Java classes that are reused in most modules.

C4 diagrams

C4 container diagram

The "Configuration" section highlights that the backend services can be customized to utilize various components such as databases, queues, and more. As a result, it becomes challenging to have a single unified C4 container diagram that represents every profile. However, provided below is a default profile diagram for reference.

c4-container

Configuration

The majority of the backend application is designed to be configurable, allowing to specify the infrastructure components it can utilize for various tasks such as data persistence and message queuing during startup.

Currently, there is only one available profile called redis. However, there are plans to introduce additional profiles in the near future.

Default configuration (SOON)

How to access data

postgres

In order to check the content of postgres db use the pgAdmin4 bundled in docker-compose.yaml.

Link: http://localhost:5050

Credentials:

During first login you may also be asked to provide a password to postgres server. It is plain and simple - postgres.

After logging all available databases will be listed.

redis configuration

All of the infrastructure components are utilizing Redis. This profile serves as a showcase to demonstrate the versatility of Redis and its ability to support various functionalities across the application. Run it with a task:

task run

Here is the overview of a system architecture with used Redis modules:

c4-container

To check all data stored in Redis enter in a web browser: http://localhost:8181

How it works

Most of the communication is based on commands and events. E.g. in order to place an order a proper command needs to be pushed to orders Redis Stream. It's then read and processed by the ordering service and result in an event which also added to the central orders stream, so other services, like delivery can read and process further.

Also bff is reading from the orders stream to create its own read model (Command Query Responsibility Segregation, CQRS) of all deliveries and store it in Redis Hash. These are used to serve a current state of a delivery on a frontend.

Both ordering and delivery services have their own event stores in which they store relevant events, so they can event source them to make a projection of an order or a delivery.

All requests that are coming from a frontend are first queued in two Redis Task queues - ordering-inbox and delivery-inbox. These inboxes are used to store all incoming REST requests to bff before converting them to relevant commands and publishing to the orders stream.

Finally, the food service stores all available meals in the food RedisJSON store. It also has an index created which enables a full-text search of all meals on a frontend.

How the data is stored:

There are several Redis modules that are used to store data:

delivery stream

{
   "orderId":"order-2",
   "customerId":"Pam Beesly",
   "farmId":"Garden's Finest",
   "deliveryManId":"nicest-guy",
   "status":"FOOD_DELIVERED",
   "address":"Cottage Avenue 11",
   "items":[
      {
         "name":"Lemony Asparagus Penne",
         "amount":1,
         "pricePerItem":9.49
      },{
         "name":"Tea",
         "amount":1,
         "pricePerItem":1.99
      }
   ],
   "deliveryCharge":1.99,
   "tip":4.59,
   "total":18.06
}

delivery view

redis task queue

food json

food idx

How the data is accessed: