0012. Package "read once, apply, conditional write" as FoldWrite¶
Status: Accepted
Context¶
A group of a key's inputs can be processed in two ways: hand it to the store's own group operation, or read the key's state once, apply the inputs to it in memory, and write once. The second is the fenced single-writer pattern of 0005 with per-input outcomes (0006), and every application that uses it writes the same round trip: read, skip inputs an earlier attempt already applied, apply the rest in order, write only if the store still holds what was read, retry the whole round trip on a conflict or a lost response, answer each input on its own.
Decision¶
FoldWrite(id, read, step, write, retry) is that round trip, usable as the batch call and the extract of
Ferry.perKey (write.call, write.outcome):
step(state, input)is the application's pure logic: the next state and the input's outcome. It sees the state as read, so it answers an input already applied without applying it again; that makes a retry after a lost response safe.write(key, before, after)must succeed only if the store still holdsbefore; it is skipped when nothing changed.- Inputs of one batch with the same
idare applied once and share the first one's outcome. retryis the application'sSchedule.
Handing a group to the store's group operation needs no helper: the batch call passes the batch through.
Consequences¶
- The library still holds no state across a key's batches:
FoldWritereads the state for every batch, so the process never becomes a source of truth. - An all-or-nothing group operation that rejects a whole group for one invalid input is handled inside
call, by validating first or splitting. FoldWriteSpecchecks conflicts, lost responses, repeated inputs and exhausted retries; theOrderedWritesexample uses it withOrder.byon an effective day.