Repository navigation
Conversation
…ags, +reply (#5) - CAP: a LIST reply spread over lines keeps every line, and an ACK spread over lines changes nothing until its last line. - BATCH: the type is an opaque identifier, matched exactly. - PRIVMSG/NOTICE: client tags (reply, edit) only go out once message-tags is enabled. - Replies and reactions carry the ratified +reply alongside +draft/reply; +reply is read first. The service worker's notification reply does the same. - ISUPPORT: a run of \xHH escapes is decoded as UTF-8, falling back to one byte per character.
# Conflicts: # client/js/irc/handlers/privmsg.ts # docs/resources/bus-contract.md
A page load (a reload, an Android PWA brought back after a discard, an app launch) starts every channel empty until the server's history answers. Keep each channel's newest 200 messages (msgid-bearing, 7 days at most) in IndexedDB and show them as a history page as soon as the page loads. A display cache, never evidence: the restored rows are marked cached (Channel.cachedIds, MsgRef.cached) and nothing that decides what the server still has to send reads them -- the catch-up walk's known set and floor, newestServerRef, TARGETS, the ATTACH cursor -- so the connect-time fill runs exactly as before. The JOIN's first LATEST page settles them (history.ts reconcileCached): when it shares a msgid with them and holds nothing unknown inside their span they are confirmed (left in place when nothing is new, else delivered again with the new lines as one page above our JOIN); otherwise a new msg:drop event takes them out of the buffer and the page shows as it would have. A catch-up walk that stops short drops what the device kept from before the gap. Each write merges with the stored record in one transaction, so two tabs do not overwrite each other, and a redaction leaves a content-free tombstone that every merge honours. REDACT now deletes the line from the device by msgid whether or not it is still loaded -- which also fixes QueryLog keeping a redacted private line that had been trimmed from memory. Settings -> General -> Channel history turns it off and deletes everything; removing a network or parting a channel forgets it. Queries stay in querylog.ts, whose reaction logic is now shared. Tests: test/irc/historycache.ts (merge, tombstones across tabs, redaction before load, the confirm / reorder / drop / inside-span cases, cached rows never counting as server evidence). Browser: tools/scenarios/history-cache.mjs against a local nefarious2 -- restore with the socket refused, the joined-up case, a gap larger than the first page, the switch.
This branch was previously deployed
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.
Closes #219 (the display-cache version proposed there).
What
After a page load (a reload, an Android PWA brought back after it was discarded, an app launch), each channel shows its last scrollback straight away, even with no connection, instead of staying empty until
CHATHISTORYanswers.client/js/irc/historycache.tskeeps each channel's newest 200 messages, actions and notices (only those with a msgid, at most 7 days old) in IndexedDB (seance-history, one record per channel).IrcClient.restoreChannelCacheshows them as a history page as soon as the page loads.cached(Channel.cachedIds,MsgRef.cached). Nothing that decides what the server still has to send reads them: not the catch-up walk's known set or floor,newestServerRef, TARGETS, or the ATTACH cursor. The connect-time fill runs exactly as before.LATESTpage settles them (history.tsreconcileCached):msg:drop {chan, ids}bus event takes them out, and the page shows as it would have without them.keepChannelHistory, on by default) turns it off and deletes everything stored. Removing a network or parting a channel forgets it. Queries stay inquerylog.ts, whose reaction logic is now shared.Why not more
A fuller design, which would use the store to skip server catch-up, read older pages from disk, fill holes with
BETWEENand fold in QueryLog/ClosedQueries, was reviewed adversarially and set aside (see #219). The current walk can't prove that stored lines are contiguous with the server's history. ATTACH replay is capped per channel and goes around the walk. Proving coverage is a separate, larger feature that probably needs server help.Testing
test/irc/historycache.ts, 14 tests:pnpm lint,pnpm typecheckandi18n:checkare clean.tools/scenarios/history-cache.mjs, run against nefarious2ircv3.2-upgradewith the dev config (all 7 checks pass). The page dials throughlib/irc-proxy.mjs, so the socket can be refused across a reload. It covers:Open questions
evilnet/CHATHISTORYRETENTION, which could replace the fixed 7-day cap.