From c79868cffbc61dc343e5bd6522d4ff68c03debaf Mon Sep 17 00:00:00 2001 From: John O'Keefe Date: Tue, 18 Aug 2026 09:52:32 -0400 Subject: [PATCH] fix(sync): bootstrap book UUID via push before first pull MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the first open of a freshly downloaded book there is no cached bookhoard UUID yet, since it is only learned from a successful push response. Pulling at that point simply failed with "Push progress first", which also broke auto sync on open. - onReaderReady auto sync: if no UUID is cached, push once to bootstrap identity (the server resolves the book by format-aware SHA-256 and returns the UUID, which we then cache); otherwise pull as before - getProgress: when no UUID is cached, instead of showing the dead-end "Push progress first" message, show "Linking this book to Bookhoard first…", push once via _bootstrapUUIDThenPull, and retry the pull once the UUID is cached - _bootstrapUUIDThenPull: new helper that pushes, waits 2s for the UUID to be cached, then performs the originally-requested pull, falling back to an error message on failure After this bootstrap both push and pull work without ordering. --- main.lua | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/main.lua b/main.lua index 20e67e2..fb9d717 100644 --- a/main.lua +++ b/main.lua @@ -100,7 +100,17 @@ end function Bookhoard:onReaderReady() if self.settings.auto_sync then UIManager:nextTick(function() - self:getProgress(true, false) + -- On the first open of a freshly downloaded book there is no cached + -- bookhoard UUID yet (it is only learned from a successful push + -- response). Pulling now would just fail with "Push progress first". + -- Instead, push once to bootstrap identity: the server resolves the + -- book by SHA-256 (format-aware) and returns the UUID, which we then + -- cache. After that, push and pull both work without ordering. + if not self:getBookhoardUUID() then + self:updateProgress(true, false) + else + self:getProgress(true, false) + end end) end self:registerEvents() @@ -992,12 +1002,16 @@ function Bookhoard:getProgress(ensure_networking, interactive) local book_uuid = self:getBookhoardUUID() if not book_uuid then + -- No cached UUID yet (first open of a freshly downloaded book). Bootstrap + -- it by pushing once: the server resolves the book by SHA-256 and returns + -- the UUID, which the push handler caches. Then retry the pull. if interactive then UIManager:show(InfoMessage:new{ - text = _("No Bookhoard UUID for this document. Push progress first."), + text = _("Linking this book to Bookhoard first…"), timeout = 3, }) end + self:_bootstrapUUIDThenPull(interactive) return end @@ -1008,6 +1022,23 @@ function Bookhoard:getProgress(ensure_networking, interactive) self.pull_timestamp = now end +-- Establish the bookhoard UUID for the current document by pushing once, then +-- (once cached) perform the originally-requested pull. Used when a pull is +-- requested before any push has run on a newly downloaded book. +function Bookhoard:_bootstrapUUIDThenPull(interactive) + self:updateProgress(false, false) + UIManager:scheduleIn(2, function() + if self:getBookhoardUUID() then + self:_doGetProgress(interactive) + elseif interactive then + UIManager:show(InfoMessage:new{ + text = _("Could not link this book. Check your network and try again."), + timeout = 3, + }) + end + end) +end + function Bookhoard:_doGetProgress(interactive) local book_uuid = self:getBookhoardUUID() if not book_uuid then return end