<feed xmlns='http://www.w3.org/2005/Atom'>
<title>pure/serve/deliver.c, branch master</title>
<subtitle>Verified execution runtime unifying state, persistence, and replication.
</subtitle>
<id>http://git.yeowoo.org/pure/atom?h=master</id>
<link rel='self' href='http://git.yeowoo.org/pure/atom?h=master'/>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/'/>
<updated>2026-10-18T22:54:06Z</updated>
<entry>
<title>027's 4f-3a: no fixed count of inputs, views (the load's columns among them, in u16s), handlers or message fields: the header's u16s alone; a message's fields at most 64 (PURE_MESSAGE_FIELDS: a send pushes them all, as the stored sends' shapes hold them), outputs at most 255 (the store names them in a byte's count: the links and the outbox's image), the numbers of outputs a module dropped carried within it; an app's numbers of each input (last sent, saved, where the event began) in a block sized to its module's inputs (by_input), a replace laying the new one first and filling it by output name; image headers sized to the module (header_room); a view's arguments u32, a made column's field u16; pure-serve's timers grow to the module's inputs, its outlets and known senders its own count (OUTLETS, 32), a list view's JSON keys its columns on the stack for 64, else on the heap; unit test: 40 inputs and 70 views, the last of each used; counts: b40 against b39b within 0.01% with batches and without but BFS +0.09%; the bank's queries (s39b and s40 in turns, three each) in_credit -0.64%, per_branch -0.37%, field +0.34%, the rest within 0.22%; 008 and 027</title>
<updated>2026-10-18T22:54:06Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-10-18T22:54:06Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=d7caf4dfb1947d8f804e3d8ae7ef066c6e3b8fb7'/>
<id>urn:sha1:d7caf4dfb1947d8f804e3d8ae7ef066c6e3b8fb7</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Module format v7, 027's 4b-2: keyed documents gone, a keyed list of records holding bytes doing their work: no collections table, DOC, DOC_SIZE or REPLACE (106 opcodes now 103, those from LEN on moved up), keyed messages or a base revision (pure_app_message takes an input and a payload), no PureData document callbacks (a data host opens states and saves them together), no burst by document key; the header 38 bytes; pure-edit-module gone; pure-serve without /objects, ETag, If-Match and If-None-Match, 412 or an app a thread for a module of documents alone (one without states or outputs runs so); a hole closed: an instruction in no handler's, view's or function's block was never verified yet the load's later passes read its arguments (a damaged module read out of bounds once the header moved what the mutation test damaged), now blanked to CONST 0; checks moved: server_documents (DOCS_SOURCE, keyed byte documents with the app's revision, against a Python model, one and three connection threads, a restart) in place of the parity with editor.pure, pipelining and bursts through kill -9 on its inputs and views, the lent budget on a text view (lending a document's read is server_lent_views' already), clocks and tokens on it; message tests without a document host; the HTTP benchmark's document suite runs the earlier document server and the baselines alone; the count harness builds against either message API (runs.sh build: -DPURE_KEYED_MESSAGES before 4b); counts: b33 against b32 with batches within 0.002% but BFS -0.33%, without batches BFS +0.63%, knapsack +0.52%, join +0.38%; the bank's queries (s32 on a v6 module, s33 on v7) field +0.68%, found +0.44%, large +0.42%, the rest within 0.13%; 008 as v7, 027's 4b-2 as made and 4c designed</title>
<updated>2026-10-18T18:30:16Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-10-18T18:30:16Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=b22b8c3f6c5378b47c36370225d7c41d4394bb7c'/>
<id>urn:sha1:b22b8c3f6c5378b47c36370225d7c41d4394bb7c</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Deliver wires on the sending loop, a step at a time (017, 2b-2)</title>
<updated>2026-10-01T08:10:55Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-10-01T08:10:55Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=5f5603ce239dce08ae2ec4b0fa828787b220493c'/>
<id>urn:sha1:5f5603ce239dce08ae2ec4b0fa828787b220493c</id>
<content type='text'>
A wire is now a sender of link/sending.h: its request goes on a
non-blocking socket as far as the socket takes it (connect, TLS
handshake, write, answer read), and its round waits for the socket or
its deadline (10 s with nothing moved). The answer is read as it comes:
the head whole, then a sized body counted down, a chunked one (few and
small) parsed again as it grows, or a body to the close. The crypto
table (version 6) takes the TLS handshake a step at a time, and reads
and writes say what they wait for. The owner pushes a wire once a turn,
as it does a link. A host whose app sends to ten links and ten wires
has 5 threads where it had 24 (none: 3).
</content>
</entry>
<entry>
<title>Give i64 its own type in modules, lists, stores and the host (016 stage 2)</title>
<updated>2026-09-30T15:16:08Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-30T15:16:08Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=46c303a41e9dd9cd0e6bd50511e8d7253a0ef438'/>
<id>urn:sha1:46c303a41e9dd9cd0e6bd50511e8d7253a0ef438</id>
<content type='text'>
An i64 is an int64_t in a value's 8 bytes, its own stack type: CONST and
NUM_TEXT take argument 2 for one, eleven opcodes are appended (ADD, SUB
and MUL fail as overflow past its range, DIV and MOD floor and fail as
divide by zero, NEG, COMPARE with a relation, MIN, MAX, and I64_FROM and
NUM_FROM, which convert only where the value fits and else fail as
limit), and moves (LOAD, STORE, locals, items, FIELD, SEND) copy it as
they copy a number. Type codes: state 6, record field 3, message field 7
(8 bytes), view 4, local 3. v6 stays: all of it is added.

- Folds with PURE_FOLD_INTEGER sum (overflow fails), keep the most or
  least of, or count the different i64s; distinct's set keeps an i64's
  -1 apart from its free mark. Blocks with an i64 run item by item.
- A list's kinds are its stored header's (number, text, bytes, bool,
  integer): integer columns are int64_t, ordered as integers as keys
  (found without guide keys for now), stored in 8 bytes and logged as
  zigzag varints of any size. Records name their fields' type in one
  array (record_field_type) in place of text and bool flags.
- A number, a bool and an i64 carry over each other by one rule,
  pure_cell_as, wherever one becomes another: a module replaced, a stored
  value or item read by another module, a waiting send recast. A u32
  field delivers to an i64 one.
- The host reads i64 fields from JSON, rows and queries as integer digits
  in range and nothing else, and shows every digit in views, tables,
  deliveries and pure-run. Faults are named by one function,
  pure_fault_name, in place of three tables; overflow is new.

test-module: 28 arithmetic cases at the range's ends, relations,
conversions both ways, 14 refusals, a keyed i64 list app (order, a sum
that overflows, a failed add undone, messages and sends of 8 bytes, every
digit as text), recasts, replacement between numbers, bools and i64s, and
three stored runs against memory with restarts (46 images written).
</content>
</entry>
<entry>
<title>Give bools their own type in the module format (v6, 016 stage 1)</title>
<updated>2026-09-30T14:24:56Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-30T14:24:56Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=bfa54e02881f56b3a969220ecaac706542046149'/>
<id>urn:sha1:bfa54e02881f56b3a969220ecaac706542046149</id>
<content type='text'>
A condition was a number, non-zero being true: a flag was a number field,
a view showed 1 for true, and nothing kept a number from standing for a
bool or a bool from being added to. Now the verifier has a bool among its
stack types, and a verified module never mixes the two. No opcode is new:

- CONST with argument 1 is a bool (+0 or 1), NUM_TEXT with argument 1
  writes one as true or false; LOAD and STORE take a number or a bool
  state, locals may hold a bool (2).
- Comparisons (LT to NE, TEXT_COMPARE) and LIST_HAS give a bool; AND, OR
  and NOT take and give them; JZ, REQUIRE, filters and folds' tests take
  one (count and first leave a bool, sum, max, min and distinct a number
  and a bool); EQ and NE compare two bools too.
- Type codes: state 5, record field 2, message field 6 (one byte in the
  prefix, 0 or 1, or the message fails as limit), view 3. A bool's
  constant, initial value and default are +0 or 1; a list is not keyed by
  one. PUREMOD6: v5 modules are built again.

At run time a bool is a number's 0 or 1, so leaf-at-a-time folds run as
before. A number that becomes a bool (a module replaced, a stored state
or item read again, a waiting send recast) keeps 0 (either sign) and 1
and takes the default otherwise; a bool that becomes a number is 0 or 1.

The host carries bools on every boundary: JSON true and false only (a
row's field too), a query's true and false, true and false in views,
table JSON and HTTP deliveries; a link takes a bool only into a bool.

A stored outbox's field types were read back with a check that refused
bool (at or past rows): a node whose output had a bool field and a send
waiting could not start again. test-module now stores such a send and
opens it (it fails on the old check), beside 28 bool refusals of the
verifier and bool states, fields, views, sends, links and migration.
The lane generator makes numbers and bools apart.
</content>
</entry>
<entry>
<title>Hold a window of each output's sends in its transport, not the outbox</title>
<updated>2026-09-30T02:32:07Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-30T02:32:07Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=d9e0b6870201d9200b3c225903b43b850475600b'/>
<id>urn:sha1:d9e0b6870201d9200b3c225903b43b850475600b</id>
<content type='text'>
A link's ring and a wire's queue took every saved send of their output
and kept it until delivered: with the receiver down they held the
outbox a second time, 178 B and 313 B more a send (104). Each outlet now
holds a window, --window bytes (4 MiB) and 65,536 sends past what its
receiver has, at least one; the outbox keeps the rest.

The owner remembers each outlet's place in the outbox and looks on from
there after a save and after its transports deliver. Places move back by
the sends that left the outbox since (PureApp.sends_gone), so a trim
before a place skips nothing, and sends queued before are not looked at
again however many wait. pure_app_sent reads a send by its place (the
newest-first visit it replaces is gone); pure_link_held and
pure_wire_held say what a transport holds.

With the receiver down a node now grows by the outbox alone once the
window is full: 219 and 218 B a send over the link and HTTP (399 and
534 B before). check.py server_windows keeps the receivers of a sender's
two outputs, one linked and one over HTTP, down through 300 buys with a
2,000-byte window, then starts them: each applies all 300 once. Without
the refill after deliveries the link stops at 117.
</content>
</entry>
<entry>
<title>Wait on the monotonic clock everywhere a deadline is waited for</title>
<updated>2026-09-30T02:17:59Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-30T02:17:59Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=385754c2d00ba3f4c74a22f55d4756e101f215b1'/>
<id>urn:sha1:385754c2d00ba3f4c74a22f55d4756e101f215b1</id>
<content type='text'>
Review 004's timer fix (103) counted the deadlines on the monotonic
clock, but the owner still slept until a wall-clock time: with the
clock set back an hour a node's timers would stop for that hour. So
would a wire's pause between tries, and a lone commit after a group
would wait an hour for the others to join it. The test's LD_PRELOAD
moves only what the process reads, so there each wait ended at once
instead, and the timers went on ticking while the owner spun a core.

core/wait.h makes conditions that wait on the monotonic clock
(pthread_condattr_setclock; macOS keeps the wall clock) and deadlines
on it. The owner's waits, the wire's pauses and the group commit's
gathering use them.

clock-back.so can now move the clock forward too (CLOCK_SHIFT_S), and
check.py server_clocks moves it an hour each way under a node with a
timer and a wire to a port no one listens on, and under a document
server whose three threads commit together, then one alone. Before:
back, 159 % CPU and 50,886 tries in 1.2 s; forward, 1 tick, 1 try, and
a lone commit that never ended. After: 59 ticks, 0 % CPU, 4 tries and a
lone commit of 2.6 ms, both ways.
</content>
</entry>
<entry>
<title>Bound what an app holds (--memory): refuse what would grow past it</title>
<updated>2026-09-30T02:04:03Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-30T02:04:03Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=a6df26a8499522033277ce4f3cd76eee155169ee'/>
<id>urn:sha1:a6df26a8499522033277ce4f3cd76eee155169ee</id>
<content type='text'>
pure-serve --memory BYTES gives the app a budget of state bytes: its
lists' items as they are stored, its texts, the outbox and the numbers
heard (docs/design/013-memory-budget.md). The count is deterministic,
the same on any device. An event after which the states hold more than
the budget, and more than before it, fails with the fault memory and
changes nothing; HTTP answers 503 memory. One that frees or keeps them
goes on, so an app over its budget can always shrink.

Sends waiting for their receivers are state: a full outbox refuses the
next send until some are stored, which is the backpressure a slow
receiver puts on clients. A delivery refused for memory is not heard:
the link keeps it (c9c0edf) and HTTP senders try again after 503.

An answer (--reply) now takes its send out of the outbox in its own
event (pure_app_answer), so it has the room its send held. Apart, an app
whose outbox filled the budget could never apply an answer that keeps
anything, and the send leaves only after its answer: both would stay for
good. An answer that still does not fit waits, with the wire's after it,
and is tried again every 100 ms: pure_wire_answer leaves it in place
until pure_wire_answered.

Checks: test-module memory_budget (refused and undone, freeing over the
budget, a full outbox, a delivery not heard, answers that fit or wait,
across a restart); check.py server_memory (a sender refused 503 memory
with its receiver down and taking buys once it is up; a receiver
restarted below what it keeps, refusing 7 times in 2 s, then taking all)
and server_answers_memory (answers wait while receipts fill the budget,
then apply once each; the API called once per order). The stats report
state_bytes and memory_refused.
</content>
</entry>
<entry>
<title>Put the links and the crypto they use in link/, a part of their own</title>
<updated>2026-09-29T06:06:27Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-29T06:06:27Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=a052b95c8135cdc5f9b91f8efc991cac80fbbe8b'/>
<id>urn:sha1:a052b95c8135cdc5f9b91f8efc991cac80fbbe8b</id>
<content type='text'>
libpure-link.a holds them; pure-serve and the M5 harness link it instead
of naming its source files.
</content>
</entry>
<entry>
<title>Take a message's rows over HTTP</title>
<updated>2026-09-28T03:31:43Z</updated>
<author>
<name>eunhhu</name>
<email>necpition205@gmail.com</email>
</author>
<published>2026-09-28T03:31:43Z</published>
<link rel='alternate' type='text/html' href='http://git.yeowoo.org/pure/commit/?id=92290c5102e7fbb1248a0f215b1099de4d00c143'/>
<id>urn:sha1:92290c5102e7fbb1248a0f215b1099de4d00c143</id>
<content type='text'>
A rows field's JSON value is an array of objects naming the record's
fields (numbers, strings; a field left out takes its default). The
connection thread encodes them as the list's stored form, which may be
longer than the JSON, grows the request's input by that much
(pure_runtime_grow: charged to the payload budget as admission charges an
input, 503 payload_budget when it does not fit) and places them after the
body, so the owner still applies a message it need not parse. A message
whose only variable field is rows takes a body that is not JSON as those
rows in their stored form: a bulk insert without JSON. An API's answer
(--reply) gives rows the same way. A delivered batch holds no rows.

server_rows loads 30,000 stock rows in one JSON request (some 250,000
rows a second, against 6,500 with a request a row) and 20,000 more as
bytes, refuses a load with a key already there whole (409 exists), then
checks 400 random orders against a model (294 applied, 106 refused with
none of their rows applied), texts with escapes and Korean, a walk that
removes, and a restart that keeps every state and no rows.

The format's document (008) describes walks, rows fields and lists of
rows, and OUTER_ROW.
</content>
</entry>
</feed>
