Skip to content

feat: put what the shop holds into a site export - #10

Open
JasonYv wants to merge 5 commits into
test/deterministic-race-testsfrom
feature/shop-export
Open

JasonYv wants to merge 5 commits into
test/deterministic-race-testsfrom
feature/shop-export

Conversation

@JasonYv

@JasonYv JasonYv commented Oct 9, 2026

Copy link
Copy Markdown
Contributor

Stacked on #9 (the race tests).

What this is

A site export is how an operator leaves with what is theirs, and the shop handed Mallok nothing for it: variants, prices, the stock ledger, orders and inquiries were in no backup. They are now (design §19).

exportFiles returns a JSON file for each, under shop/, with a manifest and the shop's own settings: a row an object, as stored, so that an amount stays whole minor units and nothing a buyer typed is rewritten. A variant carries its product's slug as well as its translation group, which only this database knows. Carts, exchange rates and the scheduler's state stay behind, and of an inquiry the cart it came from and the mark of who sent it.

Tables are read with *, so a column a migration adds is not forgotten — and a test lists every column of every exported table, so that a new one is looked at before it leaves the shop.

A table past 5,000 rows, or files past 16 MB of text together, fail the export rather than be cut short: Mallok then says there is no backup, where a file missing rows would have passed for one.

An independent review, and what it found

Twelve things, each checked before it was acted on. The ones that mattered most:

  • A price whose variant was gone was left out, and the manifest's count with it.
  • The first limit, 20,000 rows, guarded nothing: by the review's measure that much came to more than a Worker's memory.
  • The reason for a refusal does not reach the operator. Mallok's command line and admin print the plugin's id alone and suggest disabling the plugin — which gives a backup with nothing of the shop's in it. The reason is logged now, and SECURITY.md says not to follow that suggestion.
  • Four wrong exports passed every test. Each is caught now.
  • The helper from the previous pull request checked less than it said; it is told how many readings a function makes, and refuses calls that never write.

How it was verified

Check Result
lint, type check, build, both smoke runs, the preview check Pass
Tests inside workerd 810 of 810; 28 of them the export's
Red and green 39 deliberate breakages of the export and the helper in two rounds, all noticed in the end
The smoke run reads the shop's nine variants, twenty-seven prices and one inquiry out of the export of a real local Worker, beside the inquiry plugin's own file, and was seen to fail with the export unwired

Not verified, and not there

  • mallok export itself was not run against this site: the tests read the endpoint it reads.
  • Nothing was deployed. What an export costs a Worker in CPU and memory is not known; the limits are guards, not measurements, and on the smallest plan the CPU allowance may stop an export well before them.
  • Nothing imports these files, and a shop can outgrow its export and take the site's backup with it. Both wait for Mallok.

A site export is how an operator leaves with what is theirs, and the shop
handed Mallok nothing for it: variants, prices, the stock ledger, orders and
inquiries were in no backup.

exportFiles now returns a JSON file for each, under shop/, with a manifest:
a row an object, as stored, so that an amount stays whole minor units and
nothing a buyer typed is rewritten. A variant carries its product's slug as
well as its translation group, which only this database knows. Carts, rates
and the scheduler's state stay behind, and of an inquiry the cart it came
from and the mark of who sent it.

Tables are read with *, and a test fails when a new p_shop_ table is neither
exported nor named among those left behind. A table past the row limit fails
the export by name rather than be cut short: Mallok then says there is no
backup, where a file missing rows would have passed for one.
…t do

The design gains §19. The security notes say that an export holds orders and
inquiries as stored, and that a shop can outgrow an export built in one
request.
…o race

A review showed that atTheSameMoment checked the first trip of every call
before the second of any, which is 'every reading before any write' only
for a function that reads once. It is told the number of readings now.

Two calls that never write, one after the other, look the same as two side
by side: that is refused as nothing to race for. And a call that throws
before its first wait no longer leaves the others unwaited for.
…ects a review found

- A price whose variant is gone was left out, and the manifest's count with
  it: the prices were read through a join. Every price is read now, and the
  column the export adds is named variant_sku, which no table's column is.
- Twenty thousand rows a table came, by the review's measure, to more than
  a Worker's memory, so the limit would never have named a table. It is
  five thousand rows now, and sixteen megabytes of text for the files
  together.
- Mallok's command line and admin show that the shop failed and not why,
  so the reason is logged as well.
- The shop's settings were in no export. They are in shop/settings.json.
- A line separator inside a value broke 'a row to a line' for a reader that
  splits lines the way Unicode does. It is written as an escape.

And four wrong exports passed every test: one dropping columns of an
inquiry, one dropping columns of a price, one with no order to its rows,
one holding two tables to the limit. The tests compare every table whole,
from rows put in the other way round, hold each of the nine to the limit,
and list every column of every exported table, so that a new one is looked
at before it leaves the shop.
… showed wrong

Removing the status condition does turn a race red where two different
changes of an order meet; the design said it turned none. The security
notes say what an export holds in full, and not to switch the shop off to
get a backup when its export fails.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant