Hold 0007's four states where two clock readings and a counter decide them - #262
Merged
Merged
Conversation
… them 0007 decides that slow and absent are separate conditions, that the core reports four states rather than one pending state, and that it reports them progressively as a request ages rather than once at the end. None of it was in the tree: the 400 ms threshold existed nowhere, and neither did any of the four names. `src/server/states.rs` holds the part two readings of one clock and a counter settle. A request is late at 400 ms and abandoned at the deadline the transport already declares, each said once and never unsaid, because a loop polling every frame would report `late` sixty times a second and a client receiving it twice cannot tell one slow request from two. A reading first taken past the deadline reports the abandonment alone: the late report exists so a client can commit to a cached answer with budget left to draw it, and five seconds later that budget is spent. Three transport outcomes are evidence the server is absent and need no threshold, because none of them waited. A refused certificate is not one of them, which 0007 names as the near miss: it is a server that answered, and reporting it as unreachable sends a person looking for a network problem that does not exist. The abandonment count is here rather than beside the retry policy, and that closes a gap `src/server/retry.rs` states about itself: 0038 decides that a call spending all three attempts is one abandonment rather than three, that module records the decision and enforces nothing, and a loop charging three would pass every check in it. `ConsecutiveAbandonments::abandoned` takes no attempt count, so there is nothing to charge three of, and a success resets the run because the count is of consecutive abandonments rather than of abandonments. What that prevents is the two failures 0007 exists against: a client told its server is gone because one endpoint was slow, and a person shown a spinner and then an error for a request that was about to succeed. #44 stays open. Its condition drives the fake server at several delays and asserts the sequence for each, including the case where a cached answer exists; the request is #27 and the cached answer is #43. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The issue this belongs to
#44. This does not close it, and the reason is at the end.
What changed
src/server/states.rsholds the part of 0007 two readings of one clock and acounter settle. Before it, neither the 400 ms threshold nor any of the four state
names existed anywhere in this tree.
AgingRequestanswers what a reading of the steady clock has newly made true. Arequest is late at 400 ms and abandoned at the deadline
src/server/transport.rsalready declares - read from that constant rather than written a second time -
and each is said once and never unsaid. A reading first taken past the deadline
reports the abandonment alone rather than a
latethat stopped being usefulseconds ago; that is a decision and the argument for it is on the function.
what_an_outcome_saysanswers whether a transport outcome is evidence the serveris absent. Three are, and none of them needs a threshold because none of them
waited. A refused certificate is not, which is the near miss 0007 names.
ConsecutiveAbandonmentscounts abandonments against one server with no successbetween them, and answers
unreachableon the second. It takes no attempt count,so there is nothing to charge three of, and a success resets the run.
The 400 ms carries its derivation rather than only its value: it is one third of
the 1.2 seconds #62 publishes, so a client can commit to a cached answer with two
thirds of the budget left to read, decode and draw. That is a choice rather than a
measurement, and the constant says so.
What failure it prevents
The two 0007 exists against, both of which are a client drawing the wrong thing
because the core told it one pending state.
A person told their server is gone because one endpoint was slow. That is a
client treating
abandonedandunreachableas the same thing, and the reason ithappens is that a core reporting one failure gives it nothing else to treat them
as. The counter here is what makes them different: one abandonment is a fact about
a request and two consecutive ones are a fact about the server.
A person shown a spinner and then an error for a request that was about to
succeed. That is a client treating
lateandabandonedas the same thing, andWhatToReportkeeps them apart at the point the core says either.Beside those, a gap
src/server/retry.rsstates about itself and could not close.0038 decides that a call spending all three attempts is one abandonment rather
than three, because 0007 declares a server unreachable after two consecutive ones;
that module records the decision, enforces nothing, and says in as many words that
a loop charging three would pass every check in it. Charging three now fails a
case, and the signature has no argument to charge it with.
None of the three has happened here. There is no request loop in this tree to have
got any of them wrong yet, which is the point of deciding before the caller
exists.
Evidence
Every command run at
0fa121b3bbb98aafd3116839b1775dc6b90dd48a, the head beingpushed.
The legs of the gate this machine can run, each by its own script and each by its
own exit code:
Every case here moves an injected clock rather than waiting on one, which is what
0102 requires of the suite and why a five second threshold costs microseconds:
the whole module runs in 0.00s above.
What a guard here refuses, and the proof it bites
Four violations, each applied to the working tree, run, and reverted.
The threshold is reached at rather than passed. The one-character mistake:
Each state is said once. The violation is the guard on what has already been
said, dropped from the abandonment arm:
A success ends the run. The violation is a counter that only ever rises, which
declares a server gone on two abandonments a week apart with a thousand successful
calls between them:
A refused certificate is not an absent server. This is 0007's own near miss,
and the violation is the arm moved by one line:
With all four restored:
What this does not cover
#44's own condition is untouched and this does not close it. It drives the
fake server at several delays and asserts the exact sequence of stages for each,
including the case where a cached answer exists and the case where none does.
Nothing here makes a request for a delay to answer, which is #27, and nothing here
produces the cached answer or its age, which is #43. The readings already on the
issue about both are not restated in this body.
The payload each report carries is not here. 0007 has the report at nought
carry whether a cached answer exists and its age, and the later reports carry the
same. That number is 0043's and the read that produces it is #43, so this holds
the states a report is built around and not the report.
Nothing charges the counter. The rule now has a subject and a near miss, and
no loop in this tree runs a call, so a caller that charged three abandonments per
call would still fail nothing - there is no caller. That is stated in the module
as well, so a later reader does not take the row for coverage of the loop.
No recovery. What happens after a server is declared unreachable is 0045 and
is already in
src/server/recovery.rs. Nothing here probes, and nothing herereports a server answering again.
The coverage leg was not judged on this machine. Its instrumentation reads
zero lines for every area here, on this branch and on an unmodified checkout of
the default branch alike, so the number is absent rather than low.
.github/workflows/coverage.ymlruns on this pull request and is what judges it.The pinned-surface register carries the new module with its reason.
Three other legs were not run here.
headlessneeds a program this machinedoes not carry (
ip: command not found),thread-detectorneeds a nightlycompiler this tree deliberately does not pin, and
mutationis weekly rather thana pull-request leg. None was skipped by editing anything; they were not run.
Who has read it
Nobody but me has read this change. There is no second reader on this board
tonight, and the evidence above stands in place of one rather than the question
being left open.