Start learning free

LESSON 182 OF 188 · BACKEND: INTERVIEW QUESTIONS

A Bulk Request That Half Fails

Practice

The interview question: "A client sends 500 products in one request, and 3 of them are bad. What does your API do?" The expected answer: don't throw the whole batch away. Save the good rows and report each bad row with its position and its reason, so the client fixes and resends only those 3.

The idea in one sentence: the answer holds one result per row, in the same order, each with its own status. The response as a whole answers 207 Multi-Status, which tells the client that the rows went different ways and it should read each result. To know each row's position, loop with enumerate:

emails = ["ana@shop.io", "bob", "cy@shop.io"]
for index, email in enumerate(emails):
    if "@" not in email:
        print(index, "is not an email")

This prints 1 is not an email: positions start at 0, and the loop goes on after the bad row instead of stopping there.

Your code must give these answers:

POST /products/bulk  [{"name": "Mug", "price": 12}, {"name": "", "price": 5},
                      {"name": "Lamp", "price": -3}, {"name": "Pen", "price": 2}]
  →  207  {"results": [{"index": 0, "status": 201, "id": 1},
                       {"index": 1, "status": 400, "error": "name is required"},
                       {"index": 2, "status": 400, "error": "price must be a whole number above 0"},
                       {"index": 3, "status": 201, "id": 2}]}
GET /products  →  200  [{"id": 1, "name": "Mug", "price": 12}, {"id": 2, "name": "Pen", "price": 2}]
POST /products/bulk  [{"name": "Teapot", "price": 22}, "Plant", {"name": "Plant", "price": "15"}]
  →  207  {"results": [{"index": 0, "status": 201, "id": 3},
                       {"index": 1, "status": 400, "error": "must be an object"},
                       {"index": 2, "status": 400, "error": "price must be a whole number above 0"}]}
POST /products/bulk  []  →  207  {"results": []}
POST /products/bulk  {"name": "Mug", "price": 12}  →  400  {"error": "Send a list of products"}

Your task: problem_with(item) (the reason a row is bad, or None) and save_product(item) (saves the row and returns its new id) are given. In add_bulk, loop over items with enumerate and add one result per row to results: for a bad row its index, "status": 400 and the reason as "error"; for a good row its index, "status": 201 and the new "id".


Assignment
Follow the Coding Tutorial to write the loop in add_bulk that saves the good rows and reports the bad ones.


Hint
Never return inside the loop: one bad row must not stop the others. A reason is a non-empty string and a good row gives None, so if problem: is true only for bad rows.


STEP 1 OF 6
    Ctrl + Enter to check