Hold 0039's page, its derived fourth number and its unpaged read - #253
Merged
Conversation
`src/server/library.rs` holds the part of docs/decisions/0039-the-page-the-item-and-what-next-up-is-not.md that a list and a count settle: the offset and the count a paged read is asked for by, the three numbers an answer carries, whether another page exists derived from those three, and which of 0010's four library reads takes a page request at all. What it prevents. A paging loop that stops after one screenful. Both paged routes take a flag that turns counting off, and with it off the server fills the total in from the page it is returning, in the same field and with the same type as a real total. The core never sends that flag, and the constant here is where that decision is written down instead of being a default nobody chose. A fourth field that can disagree with the three it came from. Whether there is another page is derived from the offset, the number of items returned and the total, and the offset of the next page moves by what came back rather than by what was asked for, which are the same number until the first short page. A request for the second hundred views answered with the first hundred. The view route takes neither an offset nor a count on either supported line, so a page request against it is refused where it is made rather than sent as nothing and answered as though it had been. The `QueryResult` name in `src/server/mod.rs` was the placeholder for this record and is replaced by the page rather than left beside it, because two names for one answer is the drift a shared core exists to remove. The means is the one this tree already carries, which is the check `## Choosing the means` asks for. What decided it here rather than habit is that the record's whole subject is arithmetic over three numbers a server sent: a means in which the derivation could not be refused by a test that deletes it would be recording the rule rather than holding it. Belongs to #39. Which of its three conditions this reaches is stated in the pull request body, and it is none of them. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
#39) The branch was cut on 2026-08-30 and eleven landings have gone past it since. Three files conflicted and every one of them is the same shape: two landings each adding their own module beside the other's. src/server/mod.rs, src/lib.rs and tests/thread_statements.rs keep both sides. 0069's destination set arrived on the mainline while this branch was open and registers itself in the same three places 0039's page does, so nothing here chooses between them. Two of the three needed a hand after the automatic resolution and both are worth naming rather than leaving to be read out of a diff. The import block for 0007's states lost its closing brace to the block spliced in beside it. And the case this branch deletes, the one asserting QueryResult, left its function header standing on top of the case that replaces it, so the page assertion was inside a function named for a type this branch removes. The suite is green at this commit: 524 in the library, 118 thread statements. 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
#39. It stays open, and the last section says which of its three conditions this reaches, which is none of them.
What changed
src/server/library.rsholds the part ofdocs/decisions/0039-the-page-the-item-and-what-next-up-is-not.mdthat a list and a count settle: the offset and the count a paged read is asked for by, the three numbers an answer carries, whether another page exists derived from those three rather than stored beside them, and which of the four library reads 0010's capability table carries takes a page request at all.The
QueryResultname insrc/server/mod.rswas this record's placeholder, documented in its own doc comment as being #39's to decide, and it is replaced bylibrary::Pagerather than left beside it. Two names for one answer is the drift a shared core exists to remove, and a placeholder that survives the issue it was waiting for is the first thing a client author reaches for.The three other files are the module being registered the way every previous landing registers one: the crate's thread assertions in
src/lib.rs, the same statements asked from outside the crate intests/thread_statements.rs, and the line in.github/coverage/pinned-surfacethatsrc/server/being an area requires of every tracked file under it.The means is the one this tree already carries, which is the check
## Choosing the meansasks for. What decided it here rather than habit is that the record's whole subject is arithmetic over three numbers a server sent. A means in which the derivation could not be refused by a test that deletes it would be recording the rule rather than holding it, and the three runs below are what that buys.What failure it prevents
A paging loop that stops after one screenful. Both paged routes take a flag that turns counting off, it defaults to on, and with it off the server builds the answer with no total and the constructor fills the field in from the page's own length. The number then arrives in the same field, with the same type, as a real total, and a caller paging until the offset plus the page length reaches the total shows a library with one screenful in it while nothing anywhere reports an error. 0039 fixes that the core never sends the flag;
THE_TOTAL_IS_ALWAYS_ASKED_FORis where that is written down rather than being a default nobody chose.A fourth field that can disagree with the three it came from. Whether there is another page is derived from the offset, the number of items returned and the total, every time it is asked. The offset the next page begins at is derived from the same three, so it moves by what came back rather than by what was asked for - the same number on every page a server answers in full, and different on the first one it does not.
A request for the second hundred views answered with the first hundred.
GET /UserViewstakes neither an offset nor a count on either supported line, so a page request carried that far would send nothing extra on the wire and the first answer would come back as though it were the page that was asked for. The caller cannot tell a request that was not sent from one that was answered in full. It is refused where it is made instead.Evidence
The module's own cases, at the commit above:
The whole suite, which is one of the two commands the README names:
The other one:
The formatter and the analyser, under the settings the two checks run:
The invariants leg, over its own rules and the tracked set:
The document check, which is what the new register line and the new module path are read by:
The size of the change:
What a guard here refuses, and the proof it bites
Three guards, each watched failing on the version of the mistake it is against, and each restored afterwards. Every run below is
cargo test --locked --lib server::library, and the green run of the same command with no violation in the tree is the first block under Evidence.Another page is derived at the boundary and not one past it. The violation is the off-by-one somebody writes when they read the total as the index of the last item:
A page request against a read that takes no paging parameters is refused and not carried. The violation is the surface that sends it anyway, which is what this looks like when somebody treats the refusal as decoration:
The next offset moves by what came back and not by what was asked for. The violation is the one that is correct on every page a full server answers, which is why it needs a short page to catch it:
What this does not cover
None of #39's three conditions. They are a test per call against a recorded fixture, paging proven across a boundary rather than within one page, and one item type across the calls. Each needs a request to have been made and a recording of one to exist. Nothing here makes a request, for the reason
src/server/transport.rsgives about itself, andtests/recorded/holds no recording.The item's fields are not decided, deliberately. 0039 fixes that every read answers with one item type and says in the same paragraph that which fields a read populates depends on what the core asks for in the server's
fieldsparameter, which belongs with the code that makes the request. SoPagecarries the item as a parameter. Nothing here makes the third condition true and nothing here can break it, because there is no read to break it with.Nothing sends the counting flag, so nothing here proves it is never sent as false.
THE_TOTAL_IS_ALWAYS_ASKED_FORis the decision written where the code that will build the query meets it. It is a constant, not a guard: no run in this tree constructs a query, so there is nothing for a check to read.Next up is refused rather than built, and that refusal is 0039's. The route exists on both server lines and answers with the same type, and it is in none of 0010's capabilities.
LibraryReadcarries the four reads that table names and no fifth. What is owed instead is either 0010 superseded by a record whose table carries the path, or #39's body saying next up is not in its scope; the second is what the decision on #39 of 2026-08-30 took, and this pull request does not edit that body.The total is not revalidated and that is on purpose. A page states the server's number and nothing more. A total smaller than the offset plus the items returned is a server contradicting itself, and this module answers "no further page" for it rather than repairing a number it did not produce.
The coverage leg was not measured on the machine this was written on. What is run here is the register's own fixtures,
.github/coverage/coverage.sh selftest, which reports every one held. The instrumented run and the bar it applies are the runner's, and the verdict on this change is the one the runner produces.Nothing was run that could raise a consent prompt on this machine. No target outside the runner's own triple was built here, so the
targetsleg is the runner's verdict as well.The mainline was brought in on 2026-09-02, and the head is no longer the one the readings above name
This branch was cut on 2026-08-30 and sat open. Eleven landings went past it, so
every command above that names
origin/the-page-the-total-and-the-unpaged-read-39was run at
449f15c88587a6c2022cd2300d592035ab96a309and reproduces at thatcommit rather than at the head. Nothing in
src/server/library.rsmoved: themerge touched three files and none of them is that one.
Three files conflicted and all three are the same shape: 0069's destination set
landed on the mainline while this branch was open, in #287, and it registers
itself in the same three places 0039's page does. Both sides are kept and
nothing chooses between them.
Two needed a hand after the automatic resolution, and each is a defect the
resolution introduced rather than something either side wrote. The import block
for 0007's states lost its closing brace to the block spliced in beside it. And
the case this branch deletes, the one asserting
QueryResult, left its functionheader standing on top of the case that replaces it, so the page assertion sat
inside a function named for a type this branch removes. Both are repaired in the
merge commit and its message says so.
The suite at the head, rather than at the commit the sections above measured:
The gate legs that need no network, at the same head:
Who has read it
TWO PEOPLE HAVE NOW, AND THE SENTENCE THAT STOOD HERE SAID ONE. It said nobody
other than the author had read it and that the evidence carried the change in
place of a review. That was true on 2026-08-30 and is not true now: the change
was read end to end on 2026-09-02, before the mainline was brought in, which is
what the merge above is. What that second reading checked is the arithmetic the
three derived numbers rest on - that
has_another_pagecompares the offset pluswhat came back against the total rather than against what was asked for, that
next_page_beginning_atderives its offset from the same three so the two cannotdisagree, and that
answered_wholeproduces a page reporting no second pagerather than one reporting an unknown - and the refusal in
ask_for, which iswhat stops a page request reaching a route that would drop it.
The negative half stays negative. Nobody but me has read the merge commit, and
none of #39's three conditions is met by anything here.