wkrzywiec / food-delivery-redis

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Food Delivery app

This is a very simple food delivery distributed system. It allows to search for food and then order them with a delivery.

image-1 image-2 image-3 image-4

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

Overview video (Optional)

Here's a short video that explains the project and how it uses Redis:

Watch the video

How it works

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

architecture

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:

  • orders - Redis Stream, used to store commands and events as JSON. It stores all events that are happening across the entire system. bff is publishing commands into it. ordering & delivery are publishing events. Exemplary event:
{
   "header": {
      "messageId":"c065e910-1806-4ab5-b1c9-8c8a105323f6",
      "channel":"orders",
      "type":"FoodDelivered",
      "itemId":"order-2",
      "createdAt":"2022-08-28T12:14:10.557171900Z"
   },
   "body":{
      "orderId":"order-2"
   }
}

orders stream

  • ordering::[orderId] & delivery::[orderId] - Redis Streams, used to store only events relevant events for each service as JSON. Each order/delivery has its own stream. They hold the same events as it's in the orders stream.

delivery stream

  • delivery-view - Redis Hash, used to store delivery read models used for a frontend. field in the hash stores an orderId and value stores a projection of a delivery. Data is populated here by the bff service. Exemplary delivery view:
{
   "orderId":"order-2",
   "customerId":"Pam Beesly",
   "restaurantId":"Ristorante Da Aldo",
   "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

  • __rq - Redis task queue, two inboxes (ordering-inbox & delivery-inbox) used to store incoming REST request and queue their processing. Their entire lifecycle is managed by the library sonus21/rqueue. Data is here populated and consumed by the bff service.

redis task queue

  • food:[foodId] - RedisJSON document, stores information about meals. Data are populated by the food service.

food json

  • food-idx - RedisJSON index, index for food:[foodId] RedisJson document used to enable full-text search of meal name.

food idx

How the data is accessed:

  • orders - bff, ordering & delivery are consumers of this stream. They're using standard Spring Boot StreamListener.
  • ordering::[orderId] & delivery::[orderId] - ordering & delivery services are the producers and consumers for these event stores. They're using the Spring Boot RedisTemplate to achieve it.
  • delivery-view - bff is adding and fetching data from this hash using the Spring Boot RedisTemplate.
  • __rq - bff is queueing and consuming data from the task queue using the sonus21/rqueue library.
  • food:[foodId] & food-idx - bff is using the RedisLab's StatefulRediSearchConnection to full-text search available meals.

How to run it locally?

Prerequisites

  • Docker - v20.10.17 (tested on, but earlier should work too)
  • Docker Compose - v2.7.0

Local installation

Vanilla

Run all commands in a terminal:

  1. Start redis
docker-compose up -d redis
  1. Create food-idx
docker run --rm -it --network food-delivery-redis_default redis redis-cli -h redis FT.CREATE food-idx ON JSON PREFIX 1 "food:" SCHEMA $.name AS name TEXT
  1. Start all services
docker-compose up -d bff ordering delivery food ui
  1. Run script to populate Redis with initial data
bash init-data.sh
Shutting down
  1. Stop all containers
docker-compose down --rmi local
  1. Clean data:
docker volume rm food-delivery-redis_redis-data 

With Taskfile

In case you've got installed Taskfile just run the command:

task init
Shutting down

Run a command:

task infra-clean

More Information about Redis Stack

Here some resources to help you quickly get started using Redis Stack. If you still have questions, feel free to ask them in the Redis Discord or on Twitter.

Getting Started

  1. Sign up for a free Redis Cloud account using this link and use the Redis Stack database in the cloud.
  2. Based on the language/framework you want to use, you will find the following client libraries:

The above videos and guides should be enough to get you started in your desired language/framework. From there you can expand and develop your app. Use the resources below to help guide you further:

  1. Developer Hub - The main developer page for Redis, where you can find information on building using Redis with sample projects, guides, and tutorials.
  2. Redis Stack getting started page - Lists all the Redis Stack features. From there you can find relevant docs and tutorials for all the capabilities of Redis Stack.
  3. Redis Rediscover - Provides use-cases for Redis as well as real-world examples and educational material
  4. RedisInsight - Desktop GUI tool - Use this to connect to Redis to visually see the data. It also has a CLI inside it that lets you send Redis CLI commands. It also has a profiler so you can see commands that are run on your Redis instance in real-time
  5. Youtube Videos

About

License:MIT License


Languages

Language:Java 61.2%Language:Groovy 26.2%Language:JavaScript 9.5%Language:Shell 1.9%Language:HTML 0.9%Language:CSS 0.3%