carlos / todomvc-bakeoff Public

Clone
git clone https://amadan.net/carlos/todomvc-bakeoff

Plain git — no account needed to clone.

Download

Download this file

1LIVE https://todo-spinel.bfj.oncarlos.com 6692def
2
3## Where it stands
4
5- The shared suite passes on the live host: 67 passed, 3 skipped (the two
6 JS-only edit tests with JS off, and the screenshot test with JS off).
7 It passes locally too, against the x86-64 build and against the arm64
8 binary under qemu, both with `SPINEL_GC_STRESS=1`.
9- `make test` (test/run.sh, 86 checks of the contract over curl and raw
10 sockets, run plain and again under GC stress) passes, against the x86-64
11 build and against the arm64 binary under qemu.
12- `scripts/boot-check.sh dist/app-linux-arm64` passes.
13- `dist/app-linux-arm64` is a static aarch64 ELF, 8.8 MB, no shared
14 libraries.
15
16## Worth knowing
17
18- **Build route.** The host Spinel compiles Ruby to C; only the C compile
19 and static link run in the emulated arm64 root (`scripts/spinel-cross`,
20 `scripts/arm64-cc`). Running the arm64 Spinel itself under emulation
21 also works but took 14 minutes for hello-world, against about 3 to 5
22 minutes this way. Both Spinels are the same commit (`abf54280`).
23- **A GC bug, fixed in the tep patch.** spinelkit's `Url.parse_query`
24 holds a decoded key in an unrooted temporary while it decodes the
25 value. On arm64 a collection in between dropped every todo title longer
26 than about a thousand characters (the first live deploy, 947e5fe,
27 failed the long-title test for this reason). On x86-64 it only shows
28 under `SPINEL_GC_STRESS=1`. `patches/2-tep-bakeoff.patch` decodes forms
29 in C instead. Worth reporting upstream to spinelkit/tep.
30- **tep rewrites words inside string literals.** Its translator turns
31 `request` into `req` even inside strings, so a 403 message reading
32 "cross-origin request refused" came out as "cross-origin req refused".
33 The app's strings avoid those words.
34- **The arm64 root** now has `libssl-dev` installed (tep's HTTP layer
35 links OpenSSL, and the static link needs `libssl.a`; it also pulls in
36 `-lz -lzstd`).
37- **One worker.** tep's server here is a single blocking process that
38 closes each connection after its response. Each request has a 10-second
39 deadline for the whole exchange, so a slow or idle client can't hold it.
40
41## Review findings (all four fixed, deployed as 6692def)
42
431. **Per-read timeout.** Replaced by one 10-second deadline per request:
44 before every read and write, the socket timeouts are set to the time
45 left. A test trickles one byte a second and is cut off within 12 s.
462. **Bodies capped at 64 KiB.** tep's C shim now reads bodies whole, up to
47 256 KiB, into a growing buffer. Above that the answer is 413. A body
48 short of its `Content-Length`, carrying a NUL, or sent chunked gets 400
49 before any handler runs, so nothing changes. tep's SQLite column
50 buffer grew from 64 KiB to 256 KiB to match. A 10,000-emoji title
51 (about 120 KB encoded) round-trips locally and on the live host.
523. **Unissued cookies accepted.** A new `visitors` table records every
53 token the server issues. A cookie that isn't in it gets a fresh random
54 token. A migration backfills the tokens of lists that already existed,
55 so current visitors keep their lists (checked against a database at the
56 old schema).
574. **`--listen` on any address.** The binary now accepts only loopback
58 (`127.0.0.0/8`, `::1`, `localhost`) and exits with status 2 for any
59 other address, a missing port, or neither `--socket` nor `--listen`.
60 tep's every-interface fallback is gone.
61
62## Review findings not fixed
63
64None.
65