bambycha / scaling-doodle

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Shopping cart microservice

This document will describe how to setup the app and provide a brief overview of the task.

Application setup

Local setup (Ruby 2.6.6 is required):

./bin/setup

Docker container:

docker-compose up --build

To run specification:

rspec spec

An example of API use with cURL requests

All examples are provided for local setup. In case of running the application containerized, please, change localhost:3000 to the corresponding resource

To create a persistant shopping cart:

curl -X POST http://localhost:3000/users/1/carts -d 'cart[user_id]=1'
Response:
{
  "data": {
    "id": "24",
    "type": "cart",
    "attributes": {
      "user_id": 1,
      "created_at": "2020-08-31T10:28:34.040Z",
      "updated_at": "2020-08-31T10:28:34.040Z"
    },
    "relationships": {
      "line_items": {
        "data": []
      }
    }
  }
}

To add line item to the shopping cart:

curl -X POST http://localhost:3000/users/1/carts/24/line_items \
-d 'line_item[cart_id]=24' \
-d 'line_item[product_id]=1' \
-d 'line_item[quantity]=1' \
-d 'line_item[title]=product' \
-d 'line_item[price]=42'
Response:
{
  "data": {
    "id": "222",
    "type": "line_item",
    "attributes": {
      "product_id": 1,
      "quantity": 1,
      "title": "product",
      "price": "42.0",
      "created_at": "2020-08-31T10:40:25.078Z",
      "updated_at": "2020-08-31T10:40:25.078Z"
    },
    "relationships": {
      "cart": {
        "data": {
          "id": "24",
          "type": "cart"
        }
      }
    }
  }
}

To remove line item from the shopping cart:

curl -X DELETE http://localhost:3000/users/1/carts/24/line_items/222

To empty the shopping cart:

  • The client can remove all items one by one from the shopping cart as it is shown in the example above.

  • Or remove shopping cart:

    curl -X DELETE http://localhost:3000/users/1/carts/24
    
  • Or create a new shopping cart to use as an empty one:

    curl -X POST http://localhost:3000/users/1/carts -d 'cart[user_id]=1'
    

To get the details of the cart:

curl http://localhost:3000/users/1/carts/1
Response:
{
  "data": {
    "id": "1",
    "type": "cart",
    "attributes": {
      "user_id": 1,
      "created_at": "2020-08-30T19:39:40.258Z",
      "updated_at": "2020-08-30T19:39:40.258Z"
    },
    "relationships": {
      "line_items": {
        "data": [
          {
            "id": "1",
            "type": "line_item"
          },
          {
            "id": "2",
            "type": "line_item"
          }
        ]
      }
    }
  },
  "included": [
    {
      "id": "1",
      "type": "line_item",
      "attributes": {
        "product_id": 1,
        "quantity": 1,
        "title": "Product Title 1",
        "price": "42.0",
        "created_at": "2020-08-30T19:39:40.296Z",
        "updated_at": "2020-08-30T19:39:40.296Z"
      },
      "relationships": {
        "cart": {
          "data": {
            "id": "1",
            "type": "cart"
          }
        }
      }
    },
    {
      "id": "2",
      "type": "line_item",
      "attributes": {
        "product_id": 2,
        "quantity": 1,
        "title": "Product Title 2",
        "price": "42.0",
        "created_at": "2020-08-30T19:39:40.302Z",
        "updated_at": "2020-08-30T19:39:40.302Z"
      },
      "relationships": {
        "cart": {
          "data": {
            "id": "1",
            "type": "cart"
          }
        }
      }
    }
  ]
}

Task overview

Here is the database representation of the monolith application schema provided:

As using shared database to build microservices is a common anti-pattern first thing we would need to do is to restructure the existing database.

To properly extract the data layer from the monolith to the microservice we need to take into account numerous things. Such as what challenges do we have or going to have in the project (high-load, load spikes, performance restrictions in time or resources). What functionality are we going to have and how our system is going to look like to provide it. What features do we provide right now and how they are going to be migrated.

Since the information of that wasn't provided for the task here is three common ways to split OMS and shopping cart system for the provided schema:

Use orders -> line_items tables to store the shopping list

By eliminating carts we greatly simplify schema. From here we can go by two different routes.

First, we can use orders table to hold information of uncompleted orders which basically can represent user's shopping cart. That's the way as Spree and many other ecommerce frameworks work. The biggest disadvantage would be that two microservices would be dependent on one database.

Second, we can use front end application to manage unfinished orders and store information about them at the front-end side. This way we eliminate a need of having shopping cart microservice at all. Which makes it the most performant and the cheapest type of microservice to have. The biggest disadvantage would be if we would need to synchronise shopping cart between different user's devices.

Extract carts table with line_items

The main disadavantage of this way that we link orders to products through another service which increate complexity. And makes OMS functionality dependable on other microservice.

Separate line_items tables for carts and orders tables

The main disadvantage of this way is that we store almost indentical data between two microservices. But this greatly benefit us in terms of performance and independability between two microservices.

That's the way this shopping_cart API is implemented in the provided application.

About


Languages

Language:Ruby 98.9%Language:Dockerfile 0.5%Language:HTML 0.5%