docs(adr): ADR 009 reads only committed state and sends a whole window when a range moved positions (improvise-felo.4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VdfEGXA7aJ6ftMsCc9PJze
This commit is contained in:
committed by
Edward Langley
parent
5239d3b95a
commit
13b3dff35e
@@ -140,18 +140,19 @@ aggregates are keyed by axis **items**, so a collapse, hide, show, reorder or ad
|
||||
changes no operator. The visible axis is a remap.
|
||||
|
||||
- **A new key** builds its operators as a sliced job under ADR 008's job runner. Deltas
|
||||
arriving during the build are buffered and added at install.
|
||||
arriving during the build are buffered and added at install. The finished result is the
|
||||
response to the request that asked for it, not a notice.
|
||||
- **A formula edit** is a formula delta fed to the circuit.
|
||||
- **A document swap** rebuilds everything.
|
||||
- **Saving a view definition** touches no operator.
|
||||
- **Live keys are a cache.** A key is evicted after a period in which no request names
|
||||
it (the period is set by measurement), and every eviction is announced (clause 9).
|
||||
|
||||
**Column totals and hidden rows.** This holds if hidden items travel in a request, which
|
||||
is ADR 008's open question. If they do not, totals are over all rows. A total pools only
|
||||
the drawn rows, so a hidden row leaves it. The shape key is shared and a hide is one
|
||||
client's, so totals are kept over all rows. A read subtracts the request's H hidden cells
|
||||
as a temporary overlay:
|
||||
**Column totals and hidden rows.** Totals are kept over all rows, because the shape key
|
||||
is shared and a hide is one client's. Whether hidden items travel in a request is ADR
|
||||
008's open question. If they do not, a total is read as it is kept. If they do, a total
|
||||
must leave the hidden rows out, so a read subtracts the request's H hidden cells as a
|
||||
temporary overlay:
|
||||
- `Count` subtracts;
|
||||
- `Min` and `Max` skip keys whose whole count is hidden;
|
||||
- text counts the distinct keys left;
|
||||
@@ -218,8 +219,8 @@ an **edge adapter**. So every edge has the same semantics:
|
||||
was lost.
|
||||
- **No long-lived stream assumed.** An edge may be carried as a series of requests and
|
||||
responses, for example several HTTP requests on one connection, as well as a socket.
|
||||
Every request can be retried, and a resync from a publication stamp is idempotent. A
|
||||
client asks for "notices since n", and the host answers from **one shared, bounded log
|
||||
Every request can be retried, and a resync from a watermark is idempotent. A client
|
||||
asks for "notices after my watermark", and the host answers from **one shared, bounded log
|
||||
of published notices**: a single log, not one per edge or client, holding the notices
|
||||
themselves (keys and flags, not values). A request older than the log's start is
|
||||
answered with a correction (below).
|
||||
@@ -238,18 +239,23 @@ an **edge adapter**. So every edge has the same semantics:
|
||||
applied. A watermark from another host instance or generation is behind every current
|
||||
stamp. The client holds one per shape key it reads. The host and any
|
||||
gateway keep no watermarks: a client sends its own with each request.
|
||||
- where the shared log covers the watermark, the host sends the current values of the
|
||||
keys the log lists as moved since then, restricted to the client's window, and the
|
||||
client applies `target − held` over those keys. The log holds keys and flags; values
|
||||
are always read from the model's current state, so nothing per client is kept;
|
||||
- otherwise the host sends `target` for the whole window, and the client applies
|
||||
`target − held`;
|
||||
- where the shared log covers the watermark and the covered range holds only moved
|
||||
keys, the host sends the current values of those keys, restricted to the client's
|
||||
window, and the client applies `target − held` over them. The log holds keys and
|
||||
flags, not values, so nothing per client is kept;
|
||||
- where the covered range holds an axis change, a relabel or a flag, which position
|
||||
and labels depend on, the host sends `target` for the whole window;
|
||||
- where the log no longer covers the watermark, the host sends `target` for the whole
|
||||
window, and the client applies `target − held`;
|
||||
- a full refetch is `target − ∅`.
|
||||
|
||||
A correction is labelled with the publication range it covers, so it is applied only at
|
||||
the watermark it starts from, which makes it idempotent and resumable. Its elements are
|
||||
`(key, value)` pairs with weights, in the lossless wire form, so a client, a gateway or a
|
||||
worker applies it with the same code.
|
||||
**Every read sees only the last committed state**, whether it is a correction, a
|
||||
fetch or `project`, and it is labelled with that state's stamp. A value a failed
|
||||
command wrote and then rolled back is never read. A correction is labelled with the
|
||||
publication range it covers, so it is applied only at the watermark it starts from,
|
||||
which makes it idempotent and resumable. Its elements are `(key, value)` pairs with
|
||||
weights, in the lossless wire form, so a client, a gateway or a worker applies it with
|
||||
the same code.
|
||||
|
||||
Aggregation stays on the model side (ADR 008), so the operators that aggregate run on
|
||||
the model side, which may itself span a hop. Which other edges cross a wire is a
|
||||
@@ -384,7 +390,7 @@ Step 8's required tests:
|
||||
|
||||
1. **Should notices be filtered per client?** Clause 9 sends every client every live
|
||||
shape's moved keys. That keeps the host free of per-client state, but traffic is
|
||||
O(clients × all moved keys) per batch. Filtering by topic would send each connection
|
||||
O(clients × all moved keys) per committed command. Filtering by topic would send each connection
|
||||
only its own shape's key lists. It needs one subscription per connection, which pins
|
||||
its shape in the cache. Is such a subscription "model-relevant information" the
|
||||
backend may hold? On a two-hop path the topics could instead live in a gateway.
|
||||
|
||||
Reference in New Issue
Block a user