Don't let an in-flight poll undo a cursor reset - #2220
Draft
mpretty-cyro wants to merge 1 commit into
Draft
mpretty-cyro wants to merge 1 commit into
mpretty-cyro wants to merge 1 commit into
Conversation
A swarm's cursors are reset so its history is fetched again: on promotion to admin, on being kicked, when a group's data is deleted, by the multipart config migration, and on account create or load. A poll of that swarm already in flight finished afterwards and wrote its newest hash back, undoing the reset, so the history was never fetched. Resets are now counted per swarm in LokiAPIDatabase, and a poll takes the count before reading any cursor. setLastMessageHashValue takes that snapshot and skips the write if the swarm was reset since, with the check and the write under the same lock as the reset. Counting, rather than comparing cursor values, also catches a cursor that was already empty. GroupPoller's namespace values become replaceable so a JVM test can drive a real poll; they default to libsession's.
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 bug
Some events reset a swarm's poll cursors so the next poll fetches the swarm's history again. If a poll of that swarm is already in flight, it finishes after the reset and writes its newest hash back as the cursor. That undoes the reset, and the history is never fetched. The window is one poll round trip. It happens in practice because a promotion arrives through the user's own swarm while the group's poller is running.
Reset sites
Every reset goes through
LokiAPIDatabase, so the guard covers all of them:GroupManagerV2Impl.handlePromotionGroupManagerV2Impl.handleKickedConfigToDatabaseSync.deleteGroupDataPollermultipart-config migrationCreateAccountManager/LoadAccountManagerThe guard
LastMessageHashResetscounts resets, per swarm and for all swarms.GroupPollerandPollerboth take it at the top of the poll.setLastMessageHashValuenow requires that snapshot. It skips the write when the swarm has been reset since then.The guard counts resets instead of comparing cursor values. A cursor that was already empty reads the same before and after a reset, so a value comparison would let the poll write its hash back.
The in-flight poll's messages are still handled. Only its cursor write is dropped. The next poll starts from the beginning, and dedupe absorbs the messages it fetches twice.
Testing
GroupPollerCursorResetTestdrives the realGroupPoller.manualPollOnce()and holds the group messages retrieve open while the reset happens. Cases:To make that possible,
GroupPollergets a small seam,namespaces, which defaults to libsession's values. JVM tests can't load the native library those values come from.The cursor store in the test is a fake that uses the production
LastMessageHashResetsthe same wayLokiAPIDatabasedoes. The SQL wiring inLokiAPIDatabaseitself isn't under test, because it needs SQLCipher.Poller's two writes use the same guard, but no test drives them.Mutations, each killed by the test: