Enhance ServeSession to fetch git metadata before initial patch computation

- Updated the `ServeSession:start` function to retrieve git metadata from the API before computing the initial patch. This change ensures that the server information includes relevant git details, improving synchronization accuracy.
- Disabled the polling feature in `App:startSyncReminderPolling` due to performance concerns, as it was deemed unnecessary.
- Adjusted the API service to set `git_metadata` to `None` instead of computing it, streamlining the response handling.

These changes aim to optimize the synchronization process and reduce unnecessary API calls.
This commit is contained in:
Joe 2026-03-01 16:49:54 -06:00
parent 8b4573b578
commit 491d433a6b
3 changed files with 55 additions and 64 deletions

View file

@ -542,6 +542,10 @@ function App:checkSyncReminder()
end end
function App:startSyncReminderPolling() function App:startSyncReminderPolling()
-- Feature disabled: polling GET /api/rojo every 30s is expensive and
-- the setting was hidden behind showNotifications anyway.
do return end
if if
self.syncReminderPollingThread ~= nil self.syncReminderPollingThread ~= nil
or Settings:get("syncReminderMode") == "None" or Settings:get("syncReminderMode") == "None"

View file

@ -350,48 +350,57 @@ function ServeSession:start()
self.__serverInfo = serverInfo self.__serverInfo = serverInfo
local computePatchClock = os.clock() self:setLoadingText("Fetching git metadata...")
Log.debug("[TIMING] __computeInitialPatch() starting") return self.__apiContext
return self:__computeInitialPatch(serverInfo):andThen(function(catchUpPatch) :getGitMetadata()
Log.debug( :andThen(function(gitMeta)
"[TIMING] __computeInitialPatch() completed ({} ms)", serverInfo.gitMetadata = gitMeta
string.format("%.1f", (os.clock() - computePatchClock) * 1000) end)
) :catch(function() end)
self:setLoadingText("Starting sync loop...") :andThen(function()
local computePatchClock = os.clock()
local wsClock = os.clock() Log.debug("[TIMING] __computeInitialPatch() starting")
Log.debug("[TIMING] connectWebSocket() starting") return self:__computeInitialPatch(serverInfo):andThen(function(catchUpPatch)
-- Connect WebSocket BEFORE showing confirmation so changes Log.debug(
-- during confirmation can be merged into the patch "[TIMING] __computeInitialPatch() completed ({} ms)",
-- Note: connectWebSocket returns a Promise that only resolves when string.format("%.1f", (os.clock() - computePatchClock) * 1000)
-- the connection closes, so we don't chain .andThen() on it )
self.__apiContext self:setLoadingText("Starting sync loop...")
:connectWebSocket({
["messages"] = function(messagesPacket) local wsClock = os.clock()
self:__onWebSocketMessage(messagesPacket) Log.debug("[TIMING] connectWebSocket() starting")
end, -- Connect WebSocket BEFORE showing confirmation so changes
}) -- during confirmation can be merged into the patch
:catch(function(err) -- Note: connectWebSocket returns a Promise that only resolves when
if self.__status ~= Status.Disconnected then -- the connection closes, so we don't chain .andThen() on it
self:__stopInternal(err) self.__apiContext
end :connectWebSocket({
end) ["messages"] = function(messagesPacket)
Log.debug( self:__onWebSocketMessage(messagesPacket)
"[TIMING] connectWebSocket() initiated ({} ms)", end,
string.format("%.1f", (os.clock() - wsClock) * 1000) })
) :catch(function(err)
if self.__status ~= Status.Disconnected then
local confirmClock = os.clock() self:__stopInternal(err)
Log.debug("[TIMING] __confirmAndApplyInitialPatch() starting") end
-- Now show confirmation and wait for user decision end)
return self:__confirmAndApplyInitialPatch(catchUpPatch, serverInfo):andThen(function(...) Log.debug(
Log.debug( "[TIMING] connectWebSocket() initiated ({} ms)",
"[TIMING] __confirmAndApplyInitialPatch() completed ({} ms)", string.format("%.1f", (os.clock() - wsClock) * 1000)
string.format("%.1f", (os.clock() - confirmClock) * 1000) )
)
return ... local confirmClock = os.clock()
Log.debug("[TIMING] __confirmAndApplyInitialPatch() starting")
-- Now show confirmation and wait for user decision
return self:__confirmAndApplyInitialPatch(catchUpPatch, serverInfo):andThen(function(...)
Log.debug(
"[TIMING] __confirmAndApplyInitialPatch() completed ({} ms)",
string.format("%.1f", (os.clock() - confirmClock) * 1000)
)
return ...
end)
end)
end) end)
end)
end) end)
:andThen(function() :andThen(function()
Log.debug( Log.debug(

View file

@ -404,28 +404,6 @@ impl ApiService {
Vec::new() Vec::new()
}; };
let git_metadata = if let Some(repo_root) = self.serve_session.git_repo_root() {
let tree_handle = self.serve_session.tree_handle();
let repo_root = repo_root.to_owned();
let initial_head = self
.serve_session
.initial_head_commit()
.map(|s| s.to_owned());
let t = Instant::now();
let result = tokio::task::spawn_blocking(move || {
crate::git::compute_git_metadata(&tree_handle, &repo_root, initial_head.as_deref())
})
.await
.ok();
log::debug!(
"[TIMING] handle_api_rojo: compute_git_metadata {}ms",
t.elapsed().as_millis()
);
result
} else {
None
};
log::debug!( log::debug!(
"[TIMING] handle_api_rojo: total {}ms", "[TIMING] handle_api_rojo: total {}ms",
handler_start.elapsed().as_millis() handler_start.elapsed().as_millis()
@ -446,7 +424,7 @@ impl ApiService {
sync_scripts_only: self.serve_session.sync_scripts_only(), sync_scripts_only: self.serve_session.sync_scripts_only(),
ignore_hidden_services, ignore_hidden_services,
visible_services, visible_services,
git_metadata, git_metadata: None,
}) })
} }