You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit c1598bc
Browse filesBrowse the repository at this point in the historyBrowse files
gluck
committed
show reads from the tail, so a long aria has one
`show` pulled its history with a single forward read from LT 0, and the
angelus caps one aria.read at 1000 entries. Every selector then paged that
prefix in memory. The result was not a clipped view, it was a confident wrong
one. On a 4000 message fixture:
# aria 41df723c: 499 turns (showing 490-499) <- the aria has 2000 turns
figaro show -a -> turns 1..499 <- claims that is all of it
figaro show --from 1900 -> "no turn in range" <- the tail, unreachable
Nothing said a word, because the response carries Total and the old code read
it and threw it away. `show` is how a tail gets snapshotted, and the tail was
the one region no selector could reach.
It now walks BACKWARD from the end, one page at a time, on the keyset cursor
the store already implements (aria.read's Before returns the last n entries
below a cursor), and stops as soon as the selector is covered. Length stops
being a limit: the last 10 turns of a 2000 turn aria cost one page, 21 ms,
the same as the last 10 of a short one.
What the walk has to get right, and how:
- TURN IDS STAY THE ADDRESS. appendMsg stores TurnID on every durable write,
so a tail window numbers itself exactly as the head would have. For an aria
written before ids existed, derivedIDs spots it and falls back to the
forward read: numbering a legacy tail from 1 at an arbitrary point would
print a wrong coordinate for `fork <id>:<turn>`, which is worse than
showing less.
- A TURN CUT BY A PAGE BOUNDARY IS DROPPED, not rendered as an answer to
nothing. Every selector therefore asks for one more turn than it shows.
- THE HEADER CLAIMS ONLY WHAT IS KNOWN. A total appears when the walk reached
the head; otherwise the line says the range and which end it came from. A
window reporting its own size as the aria's is the original bug.
- --max-bytes is the one cap and it is opt-in. It clips the OLDEST turns of
the selection, never the newest, and says so on stderr. Diagnostics all go
to stderr, so `figaro show > snapshot.txt` holds the conversation alone.
Also here, because the bug hunt produced them:
- parseShowArgs is a named function now. --max-bytes spent two rounds
declared in the registry and parsed by nobody: cmdkit consumed the flag,
the reassembly in cli.go dropped it, and show exited 0 having ignored it,
while the unit test for the clipper it feeds passed the whole time. A
parser you can only reach through a daemon is one nothing tests.
TestEveryShowFlagIsWiredThrough now walks the chain argv walks, source
reassembly included.
- The perf fixture generator stamps TurnID, as the agent does. Without it
every synthetic aria is a legacy one, and the modern path this commit is
about never runs.
Verified in a dev shell (.#share-hush) against two generated stores, one with
stored turn ids and one without, and driven by hand in a tmux pty: the
default view lands on turns 1991..2000, --from 1995 and --before 1500 reach,
-a walks to 2000 turns, -j carries the real ids with more.before set, -v
reports "4 of 4002 messages", and --max-bytes 50 leaves turn 2000 alone.
Not done, deliberately: the 1000 entry cap stays (a sane per-call bound the
walk now makes invisible), and the turn-aware server-side paging named in
aria.go's SEAM comment is still the refactor this does correctly by hand.
showNote("this aria stores no turn ids (written before they existed), so its turns can only be counted from the head: showing the first %d of %d entries", len(w.entries), w.total)
// while ids are gapless and 1-based; printing lo+1 here would be a fourth
189
149
// coordinate system in the one command that just collapsed three.
190
150
iflo>=hi {
191
-
fmt.Printf("# aria %s: %d turns (no turn in range)\n\n", figaroID, len(turns))
151
+
ifw.atHead {
152
+
fmt.Printf("# aria %s: %d turns (no turn in range)\n\n", figaroID, len(turns))
153
+
} elseifw.fromHead {
154
+
fmt.Printf("# aria %s: no turn in that range within the first %d turns\n\n", figaroID, len(turns))
155
+
} else {
156
+
// The count is NOT known here: the walk stopped as soon as the
157
+
// selector was covered, so len(turns) is the size of the window,
158
+
// not of the aria. Printing it as a total restates the old bug.
159
+
fmt.Printf("# aria %s: no turn in that range within the %d turns walked back from the tail\n\n", figaroID, len(turns))
160
+
}
192
161
return
193
162
}
194
-
fmt.Printf("# aria %s: %d turns (showing %d–%d) · [N] is the turn to fork/send at\n\n", figaroID, len(turns), turns[lo].ID, turns[hi-1].ID)
163
+
ifw.atHead {
164
+
fmt.Printf("# aria %s: %d turns (showing %d..%d) · [N] is the turn to fork/send at\n\n", figaroID, len(turns), turns[lo].ID, turns[hi-1].ID)
165
+
} elseifw.fromHead {
166
+
// The legacy path: a forward read that stopped at the angelus's cap.
167
+
// Say FIRST, because that is what it is.
168
+
fmt.Printf("# aria %s: turns %d..%d, the first %d of %d entries · [N] is the turn to fork/send at\n\n", figaroID, turns[lo].ID, turns[hi-1].ID, len(w.entries), w.total)
169
+
} else {
170
+
fmt.Printf("# aria %s: turns %d..%d, walked back from the tail of %d entries · [N] is the turn to fork/send at\n\n", figaroID, turns[lo].ID, turns[hi-1].ID, w.total)
0 commit comments