pivot_server

package
v0.0.0-...-8df6dae Latest Latest
Warning

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

Go to latest
Published: Nov 23, 2022 License: MIT Imports: 11 Imported by: 0

README

Challenge Summary

We are in the business of selling Star Wars themed Legos. There is a database which stores data related to all the Lego products and its inventories. The database consists of two tables with the following schema.

products

  • product_id (int): unique product identifier
  • name (string): name of the product

inventories

  • product_id (string): unique product identifier
  • inventory (int): the count of the product inventory available
  • updated_at (datetime): the datetime when the inventory was updated

We need to build a REST API to expose some basic functionality to the client to retrieve, create, and update product and inventory records.

Assumptions

  1. We do not have to use a database for this exercise, instead, a very simple in-memory datastore is provided for you (see datastore.go for the interface and helpful usage example).
  2. The test cases will automatically load the following seed data into the datastore and pass them to your server.
  3. A basic router is provided that will forward requests to the relevant handler in your server, you just need to parse the request path and body (as needed), prepare and send an appropriate response.
  4. An API spec is provided that shows all the operations you need to implement. Pay careful attention to the request methods and response codes. The tests will cover every error scenario included in the spec.

Sample Data

products

product_id name
1 R2D2
2 Millennium Falcon
3 Darth Vader
4 Yoda

inventories

product_id inventory updated_at
1 100 2022-01-01
2 200 2022-01-02
3 50 2022-01-03
4 10 2022-01-04

API Spec

The API should support the following operations

Get all inventories

URL Path: /inventories

Sample Request: GET /inventories

Sample Response:

[
  {
    "product_id": 1,
    "name": "R2D2",
    "inventory": 100,
    "updated_at": "2022-01-01T00:00:00Z"
  },
  {
    "product_id": 2,
    "name": "Millenium Falcon",
    "inventory": 200,
    "updated_at": "2022-01-02T00:00:00Z"
  }
]

Errors: N/A

Get one inventory

URL path: /inventories/{product_id}

Sample Request: GET /inventories/1

Sample response:

{
    "product_id": 1,
    "name": "R2D2",
    "inventory": 100,
    "updated_at": "2022-01-01T00:00:00Z"
}

Errors:

  • 404 (product not found): this status can also be used for invalid IDs

Create a new inventory record

URL path: /inventories/{product_id}

Sample Request: PUT /inventories/5

{
    "product_id": 5,
    "name": "C-3PO",
    "inventory": 40,
    "updated_at": "2022-09-21T00:00:00Z"
}

Sample Response:

{
   "product_id": 5,
   "name": "C-3PO",
   "inventory": 40,
   "updated_at": "2022-09-21T00:00:00Z"
}

Note: a successful create should return a 201 (created) status code.

Errors:

  • 400 (Bad Request): malformed request (including mismatch between ID in URL and request body)
  • 409 (Conflict): product with the same id already exists

Update an existing inventory

URL path: /inventories/{product_id}

Sample Request:

POST /inventories/5

{
   "inventory_adjustment": -3
}

Response:

{
   "product_id": 5,
   "name": "C-3PO",
   "inventory": 37,
   "updated_at": "2022-09-21T00:10:00Z"
}

Errors:

  • 400 (Bad Request): malformed request. In addition to malformed JSON, 400 should be returned requested update would cause inventory to drop below zero.
  • 404 (Not found): product not found

Tasks

  • Complete the methods in server.go to load data from the provided datastore and render appropriate response.
  • Ensure that your server passes all the supplied tests.

Instructor's Recommendations

The following are your instructor's recommendations on what you need to know and be comfortable with as concepts in order to successfully complete this challenge:

  • Know how to write HTTP handlers
  • Know how to read request bodies and using the json package to unmarshal payloads
  • Know how to marshal JSON payloads back to a client
  • Know which HTTP status codes to return in difference circumstances

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInsertFailed = errors.New("insert failed")
View Source
var ErrNotFound = errors.New("not found")
View Source
var ErrUpdateFailed = errors.New("udpate failed")

Functions

func InventoryRouter

func InventoryRouter(s InventoryServer) http.HandlerFunc

func LoadCSV

func LoadCSV(ds Datastore, data string) error

func LoadSeedData

func LoadSeedData(ds Datastore) error

Types

type Datastore

type Datastore interface {
	GetAllProductIDs() []int
	GetProductByID(int) (Product, error)
	GetInventoryByID(int) (Inventory, error)
	InsertProduct(Product) error
	UpdateProduct(Product) error
	InsertInventory(Inventory) error
	// ConditionallyUpdateInventory performs a compare-and-set operation, updating the inventory only if the current
	// value for the given item matches the supplied prev value. This is to prevent concurrent read-modify-write
	// operations from overwriting each other. Proper usage:
	// prev := ds.GetInventoryById(id)
	// updated := prev
	// updated.Inventory = prev.Inventory + 10
	// ds.ConditionallyUpdateInventory(prev, updated)
	ConditionallyUpdateInventory(prev Inventory, new Inventory) error
}

type Inventory

type Inventory struct {
	ID        int
	Inventory int
	UpdatedAt time.Time
}

type InventoryAdjustment

type InventoryAdjustment struct {
	Adjustment int `json:"inventory_adjustment"`
}

type InventoryServer

type InventoryServer interface {
	HandleGetInventories(w http.ResponseWriter, r *http.Request)
	HandleGetInventory(w http.ResponseWriter, r *http.Request)
	HandleCreateInventory(w http.ResponseWriter, r *http.Request)
	HandleUpdateInventory(w http.ResponseWriter, r *http.Request)
}

type MemoryInventoryStore

type MemoryInventoryStore struct {
	// contains filtered or unexported fields
}

func NewMemoryDatastore

func NewMemoryDatastore() *MemoryInventoryStore

func (*MemoryInventoryStore) ConditionallyUpdateInventory

func (m *MemoryInventoryStore) ConditionallyUpdateInventory(prev Inventory, new Inventory) error

func (*MemoryInventoryStore) GetAllProductIDs

func (m *MemoryInventoryStore) GetAllProductIDs() []int

func (*MemoryInventoryStore) GetInventoryByID

func (m *MemoryInventoryStore) GetInventoryByID(id int) (Inventory, error)

func (*MemoryInventoryStore) GetProductByID

func (m *MemoryInventoryStore) GetProductByID(id int) (Product, error)

func (*MemoryInventoryStore) InsertInventory

func (m *MemoryInventoryStore) InsertInventory(inventory Inventory) error

func (*MemoryInventoryStore) InsertProduct

func (m *MemoryInventoryStore) InsertProduct(product Product) error

func (*MemoryInventoryStore) UpdateProduct

func (m *MemoryInventoryStore) UpdateProduct(product Product) error

type MyInventoryServer

type MyInventoryServer struct {
	// contains filtered or unexported fields
}

func (*MyInventoryServer) HandleCreateInventory

func (m *MyInventoryServer) HandleCreateInventory(w http.ResponseWriter, r *http.Request)

HandleCreateInventory should handle PUT /inventories/{product_id} requests

func (*MyInventoryServer) HandleGetInventories

func (m *MyInventoryServer) HandleGetInventories(w http.ResponseWriter, r *http.Request)

HandleGetInventories should handle GET /inventories requests

func (*MyInventoryServer) HandleGetInventory

func (m *MyInventoryServer) HandleGetInventory(w http.ResponseWriter, r *http.Request)

HandleGetInventory should handle GET /inventory/{product_id} requests

func (*MyInventoryServer) HandleUpdateInventory

func (m *MyInventoryServer) HandleUpdateInventory(w http.ResponseWriter, r *http.Request)

HandleUpdateInventory should handle POST /inventories/{product_id} requests

type Product

type Product struct {
	ID   int
	Name string
}

type ProductInventory

type ProductInventory struct {
	ProductID int       `json:"product_id"`
	Name      string    `json:"name"`
	Inventory int       `json:"inventory"`
	UpdatedAt time.Time `json:"updated_at"`
}

ProductInventory is a useful struct for some requests and responses

Jump to

Keyboard shortcuts

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