aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-cli/src/meshbay_cli/tui/screens.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-16 10:41:17 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-16 10:41:17 +0200
commit4802be13580de1529b7824a2337d132d64849801 (patch)
tree6dd77bcc00a0d8e494cf687918c86b9fd8e77051 /packages/meshbay-cli/src/meshbay_cli/tui/screens.py
parentd74d371bd7c0ed25f60754e475a78975bf2dc4ee (diff)
downloadmeshbay-4802be13580de1529b7824a2337d132d64849801.tar.gz
fix(cli): apply index updates in place instead of fetching the whole index
The interactive mode fetched and re-parsed the full index on every index_delta, on the loop receiving the download: 67 times in 80 s while a node enriched a library. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-cli/src/meshbay_cli/tui/screens.py')
-rw-r--r--packages/meshbay-cli/src/meshbay_cli/tui/screens.py30
1 files changed, 29 insertions, 1 deletions
diff --git a/packages/meshbay-cli/src/meshbay_cli/tui/screens.py b/packages/meshbay-cli/src/meshbay_cli/tui/screens.py
index 39b5df3..b6fd347 100644
--- a/packages/meshbay-cli/src/meshbay_cli/tui/screens.py
+++ b/packages/meshbay-cli/src/meshbay_cli/tui/screens.py
@@ -41,6 +41,9 @@ from .panes import LocalPane, RemotePane
from .widgets import Choice, TransferStrip
PER_GROUP = 2
+# A burst of index updates that added or removed files is answered by one full
+# index, this long after the last of them.
+REFRESH_AFTER_DELTA_S = 2.0
class SignInScreen(Screen):
@@ -118,6 +121,7 @@ class MainScreen(Screen):
self._trees: dict[str, Tree] = {}
self._gates: dict[str, asyncio.Semaphore] = {}
self._watching: set[str] = set()
+ self._refreshes: dict[str, asyncio.TimerHandle] = {}
def compose(self) -> ComposeResult:
with Horizontal():
@@ -150,12 +154,36 @@ class MainScreen(Screen):
self._trees[group["id"]] = Tree.from_index(await session.index())
if group["id"] not in self._watching:
self._watching.add(group["id"])
- session.ch.on_push("index_delta", lambda _msg, g=group: self._changed(g))
+ session.ch.on_push(
+ "index_delta", lambda msg, g=group, s=session: self._delta(g, s, msg))
return self._trees[group["id"]]
def forget_tree(self, group: dict) -> None:
self._trees.pop(group["id"], None)
+ def _delta(self, group: dict, session, msg: dict) -> None:
+ """A pushed index update, applied to the tree in place. Only one that
+ adds or removes something is drawn, and asks for the whole index — once
+ for a burst, not once per message."""
+ tree = self._trees.get(group["id"])
+ if tree is None:
+ return # the next look asks for the whole index anyway
+ try:
+ structural = tree.apply_delta(session.open_delta(msg))
+ except CliError:
+ structural = True
+ if not structural:
+ return
+ pending = self._refreshes.pop(group["id"], None)
+ if pending is not None:
+ pending.cancel()
+ self._refreshes[group["id"]] = asyncio.get_running_loop().call_later(
+ REFRESH_AFTER_DELTA_S, self._refreshed, group)
+
+ def _refreshed(self, group: dict) -> None:
+ self._refreshes.pop(group["id"], None)
+ self._changed(group)
+
def _changed(self, group: dict) -> None:
"""Something changed in the group: the index is asked for again, and the
pane redrawn if it is showing that group."""