Merge pull request 'Design 47 follows ADR 0633, 0637, 0638 and 0639: the take-in by the indexer it names, and the group try (issues 1966, 1921)' (#521) from docs/47-try-and-take-in into main
This commit was merged in pull request #521.
This commit is contained in:
@@ -543,6 +543,11 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel
|
|||||||
move changed, keeping the composition while no composed fingerprint changed; the verdict names the commits it
|
move changed, keeping the composition while no composed fingerprint changed; the verdict names the commits it
|
||||||
was carried from (ADR 0548 §5, §6). A head git refuses onto the new commit is not carried: its next check is
|
was carried from (ADR 0548 §5, §6). A head git refuses onto the new commit is not carried: its next check is
|
||||||
whole (ADR 0548 §7).
|
whole (ADR 0548 §7).
|
||||||
|
- **try** — the checker's run of a delivery group's check on one or more members, each a repository at an exact
|
||||||
|
commit, before or without a pull request: the same examiner as the group's check, stricter in that a missing
|
||||||
|
candidate or a node's missing composition answer ends it as error, and owing the forge no status and no Approve.
|
||||||
|
It keeps the verdicts of the packages it passed for the check to take (ADR 0637). Asked only when the operator
|
||||||
|
asks for one (ADR 0637 §6).
|
||||||
- **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when
|
- **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when
|
||||||
the build module cloned it. The verdict holds for that commit only, goes out of date when the trunk moves, and
|
the build module cloned it. The verdict holds for that commit only, goes out of date when the trunk moves, and
|
||||||
is then carried to the new commit (ADR 0323, ADR 0548).
|
is then carried to the new commit (ADR 0323, ADR 0548).
|
||||||
@@ -703,6 +708,10 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel
|
|||||||
merged head and the group that moved it. A group reaches the mesh as one source revision (ADR 0429 §11); a
|
merged head and the group that moved it. A group reaches the mesh as one source revision (ADR 0429 §11); a
|
||||||
source revision is **delivered** when every want equals its module's fingerprint and every have equals its
|
source revision is **delivered** when every want equals its module's fingerprint and every have equals its
|
||||||
want and is healthy, derived from the keys and recorded by no part (§1).
|
want and is healthy, derived from the keys and recorded by no part (§1).
|
||||||
|
- **pending revision** — a source revision the running indexer has not taken in, because it names another build of
|
||||||
|
the indexer or follows one that does: only the named indexer's own keys are written, the rest kept in the
|
||||||
|
indexer's state `pending` until that indexer starts and takes it in (ADR 0633 §1 to §3). A group's members wait
|
||||||
|
there too until the group's end, as members still gathered (§4).
|
||||||
- **canary** — the first node of a module's nodes, ordered by ring then name: a new fingerprint reaches it
|
- **canary** — the first node of a module's nodes, ordered by ring then name: a new fingerprint reaches it
|
||||||
first and the module's other nodes only once it runs healthy there (ADR 0429 §6). Replaces sending to every
|
first and the module's other nodes only once it runs healthy there (ADR 0429 §6). Replaces sending to every
|
||||||
machine at once from release 6 (§15); a fingerprint that fails there is held and the canary set back, or for
|
machine at once from release 6 (§15); a fingerprint that fails there is held and the canary set back, or for
|
||||||
|
|||||||
@@ -4,10 +4,23 @@ status: in-progress
|
|||||||
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks]
|
code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, hq 00-META/checks]
|
||||||
updated: 2026-11-05
|
updated: 2026-11-05
|
||||||
decisions:
|
decisions:
|
||||||
|
- "ADR 0639"
|
||||||
|
- "ADR 0638"
|
||||||
|
- "ADR 0637"
|
||||||
- "ADR 0636"
|
- "ADR 0636"
|
||||||
- "ADR 0635"
|
- "ADR 0635"
|
||||||
- "ADR 0634"
|
- "ADR 0634"
|
||||||
|
- "ADR 0633"
|
||||||
|
- "ADR 0632"
|
||||||
|
- "ADR 0615"
|
||||||
|
- "ADR 0614"
|
||||||
|
- "ADR 0603"
|
||||||
|
- "ADR 0601"
|
||||||
|
- "ADR 0596"
|
||||||
|
- "ADR 0595"
|
||||||
- "ADR 0594"
|
- "ADR 0594"
|
||||||
|
- "ADR 0593"
|
||||||
|
- "ADR 0590"
|
||||||
- "ADR 0572"
|
- "ADR 0572"
|
||||||
- "ADR 0571"
|
- "ADR 0571"
|
||||||
- "ADR 0570"
|
- "ADR 0570"
|
||||||
@@ -60,6 +73,7 @@ decisions:
|
|||||||
- "ADR 0446"
|
- "ADR 0446"
|
||||||
- "ADR 0445"
|
- "ADR 0445"
|
||||||
- "ADR 0444"
|
- "ADR 0444"
|
||||||
|
- "ADR 0441"
|
||||||
- "ADR 0437"
|
- "ADR 0437"
|
||||||
- "ADR 0435"
|
- "ADR 0435"
|
||||||
- "ADR 0434"
|
- "ADR 0434"
|
||||||
@@ -602,6 +616,104 @@ From its delivery, a check is this:
|
|||||||
The assigner writes the verdict under the checker's hash of the heads it judged, in its own bucket, and the checker reads it into the
|
The assigner writes the verdict under the checker's hash of the heads it judged, in its own bucket, and the checker reads it into the
|
||||||
composition of its verdict, which says "not run" until the assigner's module exists (ADR 0528 §5).
|
composition of its verdict, which says "not run" until the assigner's module exists (ADR 0528 §5).
|
||||||
|
|
||||||
|
### A try: a delivery group's check at exact commits
|
||||||
|
|
||||||
|
*ADR 0637, ADR 0638; ADR 0593 §7, §9, ADR 0636 §4, ADR 0548 §5, ADR 0596 §1 to §3, ADR 0615, ADR 0639 §1 to
|
||||||
|
§6, §10.*
|
||||||
|
|
||||||
|
A try says beforehand whether a check will pass. It is the check's own code run on commits nobody pushed to a
|
||||||
|
pull request, and it owes the forge nothing.
|
||||||
|
|
||||||
|
- **A try is a delivery group at exact commits.** The checker's try takes one or more members, each a repository
|
||||||
|
and the exact commit asked, never a branch's head, with an optional trunk commit. One repository at one commit
|
||||||
|
is a try of one member, and the same members in any order are one try (ADR 0637 §1). Its steps are check asks
|
||||||
|
on the build seats' streams, as above.
|
||||||
|
- **A whole try runs the group's check.** It builds the case a group's pull-request check builds and runs the same
|
||||||
|
examiner: each member merged onto its trunk, the unit and integration levels on the build modules, the manifest
|
||||||
|
validator with the seat definitions of the members' commits (ADR 0636 §4), the module graph, and the
|
||||||
|
composition on every placed node (ADR 0593 §7, §9). It names every failure. A try narrowed to some tests or one
|
||||||
|
level runs only those, validates no manifest and no composition, and says so (ADR 0637 §2). A try of some tests
|
||||||
|
keeps no verdict; a try of one level keeps only that level's (ADR 0639 §4, which changes ADR 0637 §5).
|
||||||
|
- **A try is stricter than the check, on purpose.** When no candidate exists for its members, or a node gave no
|
||||||
|
composition answer, the try ends as error, never as pass, naming what it could not validate, the node by name.
|
||||||
|
A check passes such a node with a warning (ADR 0593 §9); a try cannot, because it would then not say whether the
|
||||||
|
check will pass. A try that ended as error keeps no verdict (ADR 0637 §3).
|
||||||
|
- **A whole try that waits for its candidate says why.** Its try read gives the reason it waits, and the wait is
|
||||||
|
given within the checker's step bound (ADR 0639 §5).
|
||||||
|
- **The indexer makes a try's candidate, on the checker's events.** For a whole try only, the checker emits
|
||||||
|
`try.started`, carrying the try's id and its members at their commits, and `try.ended`, carrying its id and its
|
||||||
|
state, on its stream `checks`; a narrowed try emits neither, because it makes no candidate. The events' contract
|
||||||
|
is the package `tryevent` of mesh-delivery's sdk, read by the checker and the indexer, so no other module
|
||||||
|
rebuilds for it (ADR 0638 §1). The indexer, the holder of the seat `mesh-catalog`, consumes them: on
|
||||||
|
`try.started` it writes `candidates.<try id>` with one pull per member, its modules and fingerprints from the
|
||||||
|
previews, validated with the seat definitions the members carry, and on `try.ended` it deletes it. It no longer
|
||||||
|
reads the checker's state `tries` (ADR 0638 §2, which changes ADR 0637 §4; ADR 0596 §1, §2).
|
||||||
|
- **Two reads across the seam stay until issue 1966 moves them.** The indexer reads the checker's previews, and the
|
||||||
|
checker watches the indexer's `candidates.<try id>`. Both are readers of another module's bus state that ADR 0596
|
||||||
|
§3, as ADR 0615 changes it, lets stay until their module moves; issue 1966 tracks the move to the owner's tools
|
||||||
|
or events. The forge bridge's read of the gate's `merges` state (*Taken in by the indexer it names*, below) is
|
||||||
|
the same kind.
|
||||||
|
- **A try event is never lost.** The checker publishes each try event with retry until the stream `checks`
|
||||||
|
acknowledges it, and `try.ended` carries the state on every end; whether it was sent is kept in the try's own
|
||||||
|
state, so an end after a checker restart still sends it. Only the checker's account may publish `try.*` on its
|
||||||
|
stream, a row of the checker's manifest test (ADR 0639 §2, which extends ADR 0638 §1).
|
||||||
|
- **At its start the indexer recovers the open tries before it handles the events.** It creates its consumer on
|
||||||
|
the stream `checks` first, then calls the checker's tool `checker_tries`, declared in its `invokes`, which
|
||||||
|
answers every open try, with no bound on the newest, with its members and whether it is whole (ADR 0639 §3). It writes a candidate
|
||||||
|
for each whole open try that has none, deletes every candidate whose try is not open, and only then handles the
|
||||||
|
events it holds. A try that starts or ends between the call and the consumer is heard as an event, and each
|
||||||
|
write is by try id, so a try seen both ways is written once and deleted once (ADR 0638 §3). The candidate is the
|
||||||
|
try's alone: the check, the gate and the forge bridge leave it alone, and the forge is owed no status and no
|
||||||
|
Approve (ADR 0637 §4).
|
||||||
|
- **When `checker_tries` does not answer, nothing is deleted.** The indexer deletes no candidate, its take-in at
|
||||||
|
start goes on, and it asks again on the checker's next try event and by its tool `indexer_recover_tries`; the
|
||||||
|
failure is said in `indexer_try_candidates` (its state `try-recovery`) until a recovery succeeds. In the release that brings ADR 0638, the
|
||||||
|
new indexer starts before the new checker, so the old checker does not serve `checker_tries` yet: an ordering
|
||||||
|
edge of the module graph (a served verb, ADR 0614), and the reason the failure path is needed at once (ADR 0639
|
||||||
|
§1, which changes ADR 0638 §3).
|
||||||
|
- **How long it is kept.** The checker keeps an ended try's record for 7 days, readable by `checker_try_read`, and
|
||||||
|
then removes it, so its state does not grow with every try (ADR 0639 §6). How long the stream `checks` keeps its events is not decided here (*What is not decided here*).
|
||||||
|
- **A try and a check share kept verdicts.** The try computes each package's digest as the check does and keeps
|
||||||
|
the verdict of each package it passed under that digest (ADR 0548 §5, ADR 0536 §1). The pull-request check of a
|
||||||
|
tried head runs only the packages with no kept verdict for their digest, those a moved trunk or a new head
|
||||||
|
changed, so a group tried before its push costs about one check's worth of build capacity (ADR 0637 §5, ADR 0482
|
||||||
|
§1, ADR 0548 §1).
|
||||||
|
- **No try in the normal flow.** A session asks no try; it asks a group try only when the operator asks for one,
|
||||||
|
for instance to see a group's composition before its push. The review reports a try asked without the
|
||||||
|
operator's ask (ADR 0637 §6).
|
||||||
|
- **Asked through the seat verb from the registry milestone.** The seat verb `try` takes `members` once its seat
|
||||||
|
definition in mesh-delivery-contracts gives them, at the registry milestone (issue 1966); until then a group try
|
||||||
|
is asked through the checker's own tool `checker_try`. The names a try shares between the checker and the
|
||||||
|
indexer, its group name and the two reasons a candidate waits, are defined once in mesh-delivery-sdk from that
|
||||||
|
milestone, and no copy stays in either module (ADR 0637 §7, §8).
|
||||||
|
- **The try's tools.** Beside the seat verb `try`, the checker's and the indexer's own tools, against the four
|
||||||
|
lines a module's tools answer:
|
||||||
|
|
||||||
|
| Line | The checker | The indexer |
|
||||||
|
|---|---|---|
|
||||||
|
| read everything it holds | `checker_try_read` (one try: its members, steps, composition per node, failures, why it waits), `checker_tries` (every open try), `checker_kept` (the kept verdicts by digest) | `indexer_try_candidates` (each try's candidate, and a failed recovery) |
|
||||||
|
| do by hand what it does itself | `checker_try` (ask a try) | `indexer_recover_tries` (recover the open tries now) |
|
||||||
|
| recover without help | `checker_try_end` (end a try, which emits `try.ended`) | `indexer_drop_try_candidate` (drop a try's candidate), `indexer_recover_tries` |
|
||||||
|
| one seat, many tools | the seat verb `try` from the registry milestone | the seat `mesh-catalog`'s verbs, unchanged |
|
||||||
|
|
||||||
|
- **How it is checked.** The checker's try test asks two members at exact commits and the same group in any
|
||||||
|
order, refuses five malformed asks, ends as error without a candidate, keeps no verdict from an error, and fails
|
||||||
|
naming the node on a refused composition; the examiner's table validates a try's manifests as the check does;
|
||||||
|
the whole-module test starts a placed engine and a candidate and shows that the check of a tried head runs no
|
||||||
|
package with a kept verdict (ADR 0637 §9). The indexer's take-in table writes a try's candidate on its start,
|
||||||
|
deletes it on its end, and recovers at its start (an open whole try gets its candidate, a candidate of a try not
|
||||||
|
open goes, a narrowed try gets none, a try started between the call and the consumer gets one), and the
|
||||||
|
checker's try test shows both events for a whole try, neither for a narrowed one, and `checker_tries` answering
|
||||||
|
the open tries; both manifests are accepted by the manifest validator (ADR 0638 §4). The indexer's
|
||||||
|
take-in table also has a recovery that gets no answer (no candidate deleted, the failure in `try-recovery`, the
|
||||||
|
retry on the next try event and by `indexer_recover_tries`); the checker's try test shows the retry until
|
||||||
|
acknowledgement, `try.ended` after a restart, the whole list of open tries (more than 64), the verdicts kept by a
|
||||||
|
try of some tests and of one level, the reason a waiting try gives, and an ended try's record kept 7 days and
|
||||||
|
removed after; the checker's manifest test shows that only its account publishes `try.*` (ADR 0639 §10). The registry group's review finds no copy of the shared
|
||||||
|
names. Live, the registry group is tried whole before its push, and the checker's try read names each member,
|
||||||
|
the composition per node and every failure (ADR 0637 §9); during that try `indexer_try_candidates` reads its
|
||||||
|
candidate, and after `try.ended` it is gone (ADR 0638).
|
||||||
|
|
||||||
## The Approve and the merge
|
## The Approve and the merge
|
||||||
|
|
||||||
*ADR 0421, ADR 0398 §3, ADR 0406 §1.*
|
*ADR 0421, ADR 0398 §3, ADR 0406 §1.*
|
||||||
@@ -646,6 +758,8 @@ From its delivery, a check is this:
|
|||||||
revision of `source.main` in one write (ADR 0429 §11). There is no merge window, no batch and no plan: the
|
revision of `source.main` in one write (ADR 0429 §11). There is no merge window, no batch and no plan: the
|
||||||
indexer writes each module's fingerprint at the merge, the builder claims each new fingerprint once, and the
|
indexer writes each module's fingerprint at the merge, the builder claims each new fingerprint once, and the
|
||||||
assigner writes each want when its six rules hold. A merge is never refused, held or dropped once it is made.
|
assigner writes each want when its six rules hold. A merge is never refused, held or dropped once it is made.
|
||||||
|
What of it is taken in waits only for the indexer its source revision names, or for the rest of its group
|
||||||
|
(*Taken in by the indexer it names*, below; ADR 0633).
|
||||||
- **Two merges close together are two revisions.** The second's fingerprints replace the first's in the
|
- **Two merges close together are two revisions.** The second's fingerprints replace the first's in the
|
||||||
indexer's modules; a node gets the newer fingerprint's want once its rules hold, and a fingerprint nobody wants
|
indexer's modules; a node gets the newer fingerprint's want once its rules hold, and a fingerprint nobody wants
|
||||||
any more is never applied. Nothing waits for a window to close.
|
any more is never applied. Nothing waits for a window to close.
|
||||||
@@ -665,6 +779,99 @@ From its delivery, a check is this:
|
|||||||
the move; its tools `assigner_wants`, `assigner_want`, `assigner_differences` and `node_haves` read the same
|
the move; its tools `assigner_wants`, `assigner_want`, `assigner_differences` and `node_haves` read the same
|
||||||
keys, and its events `delivered`, `moving`, `settled` and `stuck` say them on the bus.
|
keys, and its events `delivered`, `moving`, `settled` and `stuck` say them on the bus.
|
||||||
|
|
||||||
|
### Taken in by the indexer it names
|
||||||
|
|
||||||
|
*ADR 0633 with its progressive insights of 2026-11-05, which changes ADR 0603 §1, §4, §6 and §9; ADR 0639 §7, §8,
|
||||||
|
which change ADR 0633 §1, and ADR 0639 §9, §10; ADR 0636 §4, ADR 0614 §8, ADR 0601 §3, ADR 0632 §2, ADR 0441 §3, §4, ADR 0564 §2, ADR 0595
|
||||||
|
§11, ADR 0596 §3, ADR 0615.*
|
||||||
|
|
||||||
|
A change that brings a new manifest validator is judged by that validator: nothing else of it reaches the
|
||||||
|
machines until the indexer it builds runs, and the merges behind it then move on the bus's own event, never on a
|
||||||
|
timer. A group's merges arrive together.
|
||||||
|
|
||||||
|
- **A source revision names its indexer.** The indexer is the module that claims the seat `mesh-catalog`; a source
|
||||||
|
revision names the build of it whose fingerprint its module has once the revision is applied. The running
|
||||||
|
indexer takes a revision in whole only when the revision names its own build (ADR 0633 §1).
|
||||||
|
- **The indexer fixes its own build at its start.** It sets its own build once, at its start, from the build it
|
||||||
|
was started with, and never learns it later from the node-engine seat's verb `composition`. A process the
|
||||||
|
node-engine is replacing therefore keeps its old build to the end and cannot take the new revisions in with its
|
||||||
|
old manifest validator; they wait for the new process. An indexer that learnt its build lazily and kept it
|
||||||
|
could, while being replaced, learn the new fingerprint and take in with the old validator (ADR 0639 §7, which
|
||||||
|
changes ADR 0633 §1).
|
||||||
|
- **An indexer with no own build says so on the bus.** It leaves the merged message unacknowledged, so the bus
|
||||||
|
delivers it again, says so in its journal, and sends `take-in.pending` with the reason `own build unknown` for
|
||||||
|
the revision it holds, so the watchman's bound for `take-in-waits` covers that wait (ADR 0633 §1, ADR 0639 §8,
|
||||||
|
which changes it).
|
||||||
|
- **A revision that names another indexer moves only that indexer.** The running indexer writes only what
|
||||||
|
building and moving the named indexer needs: the indexer's own module entry, its manifest record, its verdict
|
||||||
|
(ADR 0614 §8), its key of the module graph and the packages the revision publishes. It keeps the rest in its own
|
||||||
|
state `pending`, one key per merge carrying the merged message whole, written by compare-and-set, and acknowledges
|
||||||
|
the merged message only once that key is written. `pending` is in the old form of bus state, the bucket the
|
||||||
|
grants part creates, not a template in `requires`; it moves when the indexer next moves its bus state (ADR 0595
|
||||||
|
§11 as ADR 0615 changes it). Nothing else of the revision reaches the module, verdict,
|
||||||
|
graph, taken, predefined, candidate or config-candidate state, so no node-engine, assigner, grants part or builder
|
||||||
|
reads it (ADR 0633 §1, which changes ADR 0603 §4).
|
||||||
|
- **Validated with the seat definitions its merges carry.** The running indexer validates the revision's
|
||||||
|
manifests, the named indexer's own among them, with the seat definitions read from the merges' trees, never a
|
||||||
|
built-in seat list. When it refuses the named indexer's manifest, the revision stays pending, and the event
|
||||||
|
`take-in.pending` and the tool `indexer_pending` say so in their field `refused` (ADR 0633 §1, its insight of
|
||||||
|
2026-11-05, ADR 0636 §4).
|
||||||
|
- **The named indexer takes it in at its start.** An indexer that starts as the build a pending revision names
|
||||||
|
takes the pending revisions in, oldest first, as one take-in judged by its own manifest validator, before it
|
||||||
|
starts its consumer on the forge bridge's stream; then it removes them from `pending`. It takes in only whole
|
||||||
|
revisions, and its validation and holds act on them as on any merge (ADR 0633 §2, ADR 0601 §3, ADR 0632 §2).
|
||||||
|
- **A merge behind a pending revision waits too, and the newest governs.** While a revision is pending, every later
|
||||||
|
merge joins the pending revisions in merge order, unrelated modules included, because its trees build on theirs;
|
||||||
|
which indexer they name is worked out over all of them. A later merge that brings the indexer's fingerprint back
|
||||||
|
to the running build, as a revert does, lets the running indexer take them all in; a pending revision that names
|
||||||
|
yet another build is taken in by the next indexer only as far as the first bullet allows (ADR 0633 §3, which
|
||||||
|
changes ADR 0603 §1 and §9).
|
||||||
|
- **A group's merges are taken in together.** The forge bridge sets the group on each member's merged message,
|
||||||
|
from the gate's `merges` state, a read of another module's bus state that ADR 0596 §3 lets stay until issue 1966
|
||||||
|
moves it, and once every approved member is merged it publishes `forge.group.merged` on
|
||||||
|
its own stream `forge`, after the last member's merged message, naming the members and their merge commits. The
|
||||||
|
indexer hears both through its one consumer, keeps each member's merged message in `pending` until the group's
|
||||||
|
end, and then takes the members in as one source revision under the first bullet. A refused member is no
|
||||||
|
group's end: the group stays gathered until it merges on, said by the wait below and the urgent condition of a
|
||||||
|
held group (ADR 0441 §3, §4); the gate passes the group's end by without counting it a refusal. A later merge in
|
||||||
|
a member's repository waits behind the group; a merge in another repository is taken in alone, unless a revision
|
||||||
|
is pending for its indexer (ADR 0633 §4, which builds ADR 0429 §11 for take-in).
|
||||||
|
- **A wait is bounded, said and recoverable.** The indexer's tool `indexer_pending` reads the pending revisions and
|
||||||
|
the members still gathered, each with its merges, the indexer build it waits for, since when and `refused`; the
|
||||||
|
view names a module waiting for its revision's indexer through that tool (ADR 0633 §5, which changes ADR 0603
|
||||||
|
§6). The indexer emits `take-in.pending` when a revision becomes pending or a group's first member is held, and
|
||||||
|
`take-in.taken` once it is taken in, both ordinary events of the indexer; each carries the wait's key, what
|
||||||
|
waits (a revision with the indexer build it waits for, or a group with its members so far), since when, and
|
||||||
|
`refused` (ADR 0633 §1, §5). The watchman writes the finding `take-in-waits` when no `take-in.taken` follows
|
||||||
|
within 60 minutes for a revision or 30 minutes for a group, and the condition keeper raises the condition from
|
||||||
|
it and clears it on `take-in.taken` (ADR 0564 §2 as ADR 0590 §2 changes it). At its start the watchman seeds its
|
||||||
|
open waits from `indexer_pending`; the bounds only raise the condition, and nothing is taken in on a timer. The hand acts, each said in the journal and the audit, are the indexer's `indexer_take_in_pending`
|
||||||
|
(take the pending revisions, or a group gathered so far, in with the running indexer, when the named indexer can
|
||||||
|
never run or the group's end never comes) and `indexer_drop_pending` (drop a pending merge a later one replaced),
|
||||||
|
and the forge bridge's `bridge_groups` (read the groups it holds open) and `bridge_group_end_again` (publish a
|
||||||
|
group's end again from the gate's `merges` state) (ADR 0633 §5). Both of the indexer's hand acts emit
|
||||||
|
`take-in.taken`: a hand take-in as any take-in does, and a hand drop naming the drop, for a merge whose wait was
|
||||||
|
said pending, so the watchman's `take-in-waits` clears; a drop of a merge never said pending emits none (ADR 0633
|
||||||
|
§5, ADR 0639 §9).
|
||||||
|
- **The check refuses an indexer the running parts could not move.** For a change to the indexer's own module, the
|
||||||
|
check validates the new indexer's manifest, found as the manifest that claims the seat `mesh-catalog`, with the
|
||||||
|
trunk's manifest validator in its sandbox and the seat definitions of the members' heads, and refuses the change
|
||||||
|
when that validator would refuse or hold it: such an indexer would never run, and every revision behind it would
|
||||||
|
wait for ever (ADR 0633 §6, ADR 0636 §4).
|
||||||
|
- **How it is checked.** One integration test starts the indexer whole against the bus: a group's two merged
|
||||||
|
messages and its end are taken in as one revision, nothing written before the end; a revision changing the
|
||||||
|
indexer writes only the indexer's own keys and shows in `indexer_pending`; restarted as the named build, the
|
||||||
|
indexer takes every pending revision in, oldest first, with no timer, and a group still gathered stays pending.
|
||||||
|
Unit tables cover a later merge joining, a revert, another named build, a refused member, a merge in a member's
|
||||||
|
and in another repository, an unknown own build, a compare-and-set conflict, both events, the watchman's two
|
||||||
|
bounds and its seeding, the view, the gate passing the end by, and each hand act; three cases cover the seat
|
||||||
|
definitions of the revision (accepted without a built-in seat list, a refusal in `refused`, the check accepting
|
||||||
|
the same candidate); and rows for an own build fixed at start (a composition answer that differs changes
|
||||||
|
nothing), for `take-in.pending` with `own build unknown`, and for a hand drop (a merge said pending emits
|
||||||
|
`take-in.taken` naming the drop, one never said pending emits none) (ADR 0639 §10). Live, the registry group's merge shows in `indexer_pending` waiting for the new indexer and
|
||||||
|
is taken in when that indexer starts, and no node-engine reads distribution's new entry before the new indexer's
|
||||||
|
hold: `node_manifest_reads` and `indexer_holds` on every node (ADR 0633, How it is checked).
|
||||||
|
|
||||||
## A backup before the apply
|
## A backup before the apply
|
||||||
|
|
||||||
*ADR 0214 §7, ADR 0233, ADR 0404, ADR 0429 §14, ADR 0539 §16.*
|
*ADR 0214 §7, ADR 0233, ADR 0404, ADR 0429 §14, ADR 0539 §16.*
|
||||||
@@ -1320,7 +1527,30 @@ R4d, the three image reworks (route-proxy, nats, automx; n8n left by ADR 0506),
|
|||||||
|
|
||||||
## What is not decided here
|
## What is not decided here
|
||||||
|
|
||||||
|
- How long the checker's stream `checks` keeps its events (*A try*, above).
|
||||||
|
- Who is granted `checker_try` and the take-in hand tools: the operator's grants, outside this design.
|
||||||
- A web view of deliveries beyond the pull request's comment.
|
- A web view of deliveries beyond the pull request's comment.
|
||||||
- Whether `mesh/delivery-group` is required on the trunks: the operator's setting, through the forge module's
|
- Whether `mesh/delivery-group` is required on the trunks: the operator's setting, through the forge module's
|
||||||
protection tool.
|
protection tool.
|
||||||
- How a builder's public SSH key reaches the forge: the forge's and the SSH client's mechanism.
|
- How a builder's public SSH key reaches the forge: the forge's and the SSH client's mechanism.
|
||||||
|
|
||||||
|
## Reviewed by architectural domain
|
||||||
|
|
||||||
|
The amendment of 2026-11-05 (ADR 0637, ADR 0638, and ADR 0633 with its insights of 2026-11-05) was reviewed by the
|
||||||
|
four reviewers by architectural domain side by side (playbook 01), and the lead ruled on every finding in round 1.
|
||||||
|
The rulings that no record decided became ADR 0639, which the text cites clause by clause. What was found, and what
|
||||||
|
answers it:
|
||||||
|
|
||||||
|
| Domain | Found | Answered by |
|
||||||
|
|---|---|---|
|
||||||
|
| seams | the indexer said to read none of the checker's state, while it reads the checker's previews and the checker watches its candidates; the forge bridge's read of the gate's `merges` unmarked | *A try* (two reads that stay under ADR 0596 §3 until issue 1966); *Taken in by the indexer it names* (the bridge's read marked the same) |
|
||||||
|
| tools | the try's tools not listed against the four lines; the hand acts not said to clear the condition | *A try* (the table of the checker's and the indexer's tools, `indexer_recover_tries` new); *Taken in* (both hand acts emit `take-in.taken`, ADR 0639 §9) |
|
||||||
|
| bus forms | the form of `pending` and the try events' contract unsaid | *Taken in* (`pending` in the old form the grants part creates); *A try* (the package `tryevent` of mesh-delivery's sdk) |
|
||||||
|
| running qualities | `checker_tries` not answering; the new indexer before the new checker in this release; a lost try event; what a narrowed try keeps; a recovery cut at 64; how long tries are kept; a try waiting for its candidate | *A try* (nothing deleted, asked again, said in `indexer_try_candidates`, the ordering edge; publish with retry, `try.ended` on every end; the narrowed try's verdicts; every open try listed; 7 days; the reason in the try read, bounded by the step bound) |
|
||||||
|
| testing | ADR 0633's live case on the node-engines' reads lost; no live case for ADR 0638 | *Taken in* (`node_manifest_reads` and `indexer_holds` on every node); *A try* (the candidate read during the registry group's try, gone after `try.ended`) |
|
||||||
|
| health and events | an own build unknown left unbounded; who raises `take-in-waits`; what the two take-in events carry | *Taken in* (`take-in.pending` "own build unknown"; the watchman's finding and the condition keeper, ADR 0564 §2; the events' body) |
|
||||||
|
| security | any account could publish a try event; a node's missing composition answer | *A try* (only the checker's account publishes `try.*`, a manifest-test row; the try ends as error naming the node, keeping no verdict) |
|
||||||
|
| upgrade | the old indexer's take-in during its replacement: a build learnt lazily and kept let a process being replaced take in with its old validator | *Taken in* (the indexer fixes its own build at its start, never later from `composition`) |
|
||||||
|
|
||||||
|
Left as notes, not in this amendment: the grants of `checker_try` and of the hand tools (the operator's), and the
|
||||||
|
test budget of the checker and the indexer.
|
||||||
|
|||||||
Reference in New Issue
Block a user