aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-10-14 10:17:49 +0200
committerChristophe Besson <cbesson@gmail.com>2026-10-14 10:17:49 +0200
commit80ac882346b474bb7ea4e8c8afd4694bd13dd9dd (patch)
tree3aebf475a23dc3e44dff1a6c577d8af82418d024 /packages/meshbay-hub/src/meshbay_hub/static/index-dock.js
parentaf542a40aec6ffe0ac06798d99abd00a24eb9c50 (diff)
downloadmeshbay-80ac882346b474bb7ea4e8c8afd4694bd13dd9dd.tar.gz
feat(node): skip a file the disk stops answering for, then pause its root
A Windows tester's scan stuck for good on one directory of a large disk: one read that never returned held the indexer's only thread, and with it every root behind that one. - A disk call is timed by its silence, not its length: each directory entry listed and each megabyte read counts as an answer. After 60 s of silence the call is abandoned on its daemon thread, the file is noted unread and the scan goes on. - Three silent files in a row pause the root (not persisted). Resume skips the files already known to give no answer; a restart, a replug or a change to the file retries them. - The walk is per directory with os.scandir: a subdirectory that cannot be listed costs itself, and a listing that stops answering pauses the root at once. A scan no longer stats anything from the event loop. - The log names the file after 10 s of silence, the indexing band shows it, and Group settings shows the paused root, where it stuck and the unread files with their reason, on the node's machine only. - generate_http_api.py writes LF on Windows too. Verified with real kernel-blocked opens (an unacknowledged oplock) in the installed frozen app. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/index-dock.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/index-dock.js9
1 files changed, 8 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js b/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js
index 47a5818..3a9a539 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/index-dock.js
@@ -7,6 +7,7 @@ import { useStickyBand } from './sticky.js';
import { Icon } from './icon.js';
import {
fromLoopback, fromPush, mergeActivity, dockRows, hideRow, pauseRow, percent, queuedCount,
+ baseName,
} from './index-dock-model.js';
// ── Indexing dock ───────────────────────────────────────────────────────────
@@ -117,9 +118,14 @@ function DockRow({ row, error, onOpen, onPause, onHide }) {
: t(`indexdock.kind_${row.kind || 'scan'}`);
const where = row.root ? `${row.groupName} › ${row.root}` : row.groupName;
+ // A scan that sits still says what it is sitting on. It used to show a bar
+ // that had stopped, and the name of a folder.
+ const slow = !done && !error && row.slowPath;
let meta = '';
if (error) {
meta = error;
+ } else if (slow) {
+ meta = t('indexdock.slow', { secs: number(row.slowSecs), file: baseName(row.slowPath) });
} else if (listing) {
meta = t('indexdock.listing');
} else if (!done && !waiting) {
@@ -144,7 +150,8 @@ function DockRow({ row, error, onOpen, onPause, onHide }) {
onClick=${onOpen}>
<span class="index-dock-head">
<span class="index-dock-title"><strong>${status}</strong> ${where}</span>
- ${meta && html`<span class="index-dock-meta ${error ? 'index-dock-error' : ''}"
+ ${meta && html`<span class="index-dock-meta ${error || slow ? 'index-dock-error' : ''}"
+ title=${slow ? row.slowPath : null}
role=${error ? 'alert' : null}>${meta}</span>`}
</span>
<span class="index-progress-bar index-dock-bar">