Back to Feed
article 4m read

A relay that turned almost any broken sales response into "nothing sold"

A helper in the relay feeding my ordering system made an empty list out of error objects and blank bodies, and passed partial pages on as complete; now it rejects the malformed and partial answers it can detect, keeps honest empties, and says plainly what it still can't detect.

Article DepthPractice

Flow

Test answers on each side of the line

  1. 1Must fail: wrong shape

    Error object with a 200, null, blank body, cut-off JSON, a junk row next to a good one.

  2. 2Must fail: partial

    A 206, a next-page header, a link that lists next as its second value.

  3. 3Must fail: bad rows

    A sale with no item list, an item with no quantity.

  4. 4Must pass

    A real empty list, and a package with zero on hand.

Whatever the ordering system buys depends partly on yesterday's sales, and the relay that fetched those sales would hand it an empty list for almost any bad response that came back with a 200.

The relay sits between the planner and the stores' sales system. It fetches stock, sales and stock changes. The planner only sees lists, so the relay is the last spot that can say "I'm not sure".

How bad answers turned into empty lists

Almost every read ended in a helper that kept a list if it got one and made an empty list out of anything else. An error message with a 200, a blank body, or an object where the list should be all came out as "nothing".

That's the costly way to be wrong. As I understand it, no sales means no demand, so orders shrink, and no stock means bare shelves, so orders grow. I wouldn't expect anything in an error log.

The status check let partial answers through too. A 206, or a 200 with a "next page" header, counted as fine. Page one went through as if it were everything.

The package tests now also send one good row plus a junk value, and the whole answer must fail. I'd bet the old read just kept the good row. If so, it looked fine. The total was just low.

I can't point to a bad order this caused. The planner would have trusted it either way.

The rule now

Three changes in one day fixed sales, then dated stock, then packages. Each read now takes an answer only if the status is exactly 200, no header says there's more, the body parses, and it's a list of objects. Sales also need a real ID, a real date and a real item list, with a number for each quantity. If one row is bad, the whole answer is refused. Anything that fails becomes a 502 with a named error, so the planner hears "I couldn't tell" instead of "nothing sold".

I left the old helper alone for other callers, and they behave as before. The package reads also got a time limit and a size limit.

Which answers fail and which pass

The tests are tables. Bad answers must fail, and the reply must not be a list. Two honest answers must pass: a real empty list, and a package with zero on hand. Skip those and the next cleanup turns every empty list into an error.

Copies that disagree

Long ranges are fetched in month-sized chunks, so a row on the edge can show up twice. The old code kept the first copy. Now it compares the copies and stops with an error when they differ.

Stock at a moment

A new read gives stock at an exact time. Every row's own timestamp must match that time, and every row must name its product.

A short answer with no warning

The sales system has no page count and no total. If it ever cuts an answer short with no signal, the relay can't tell. The docs say so, but saying so doesn't catch it.

The next-page check I got wrong

My first check for a next page was a plain text match. It missed a link that lists next as its second value, and it missed spaces around the equals sign. The next change replaced it with one that splits the value into words and looks for next as a whole word. For one commit, my own check for partial answers was itself partial.

Keep reading

Pick up a connected idea or branch into a nearby one.

5 paths forward