summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/app.js46
1 files changed, 27 insertions, 19 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js
index f9bcd43..1530ff5 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js
@@ -925,12 +925,12 @@ function CreateGroupWizard({ token, username, onCreated }) {
{ label: t('wizard.step_create_hub'), status: 'pending' },
{ label: t('wizard.step_attach'), status: 'pending' },
];
+ steps.push({ label: t('wizard.step_index'), status: 'pending' });
// Only a step at all when it does something — the common case (every
// app left on, the default) has nothing to set and no reason to show a
- // step for it.
+ // step for it. After indexing (see the execution order below for why).
if (enabledApps.length < APPS.length)
steps.push({ label: t('wizard.step_apps'), status: 'pending' });
- steps.push({ label: t('wizard.step_index'), status: 'pending' });
if (roots.length > 1)
steps.push({ label: t('wizard.step_add_roots'), status: 'pending' });
steps.push({ label: t('wizard.step_gek'), status: 'pending' });
@@ -994,11 +994,31 @@ function CreateGroupWizard({ token, username, onCreated }) {
update('done');
advance();
- // 3. Narrow the enabled apps down, if the operator unchecked any —
- // before the scan below, so a member who joins while it is still
- // running never briefly sees an app meant to be off. Same
- // not-hosted-yet race as steps 4+ below: the group is attached, but
- // may not have reached groups_ctx yet.
+ // 3. Wait for the node's own initial scan of this group to finish —
+ // the group is not usable for anything below (apps, extra roots, GEK)
+ // until this finishes: daemon.py registers a brand-new group in
+ // groups_ctx only once its initial scan completes (ui/app.py's
+ // index-status docstring — "it is not yet authorized for member
+ // connections either way"), so nothing scoped to the group can
+ // succeed before this, no matter how many times it's retried. Can
+ // take tens of minutes on a slow disk with a large library — the node
+ // keeps scanning on its own either way (test_hot_reload_survives_
+ // client_close.py); this step is only about not lying about it.
+ update('running');
+ await platform.waitForGroupHosted(gid, setIndexProgress);
+ update('done');
+ advance();
+
+ // 4. Narrow the enabled apps down, if the operator unchecked any.
+ // Used to run *before* the scan above, reasoning that a member
+ // joining mid-scan should never briefly see an app meant to be off —
+ // but nobody can join before the group is hosted either (same
+ // authorization gate the comment above names), so that concern never
+ // applied, and placing it here means the retry below is defensive
+ // rather than the only thing standing between this step and an
+ // indefinite "Group not hosted on this node" (found live against a
+ // real, several-thousand-file library: withRetry's five attempts
+ // don't come close to covering a scan that takes minutes).
if (enabledApps.length < APPS.length) {
update('running');
await withRetry(() => platform.node.call(
@@ -1007,18 +1027,6 @@ function CreateGroupWizard({ token, username, onCreated }) {
advance();
}
- // 4. Wait for the node's own initial scan of this group to finish —
- // the group is not usable for anything below (extra roots, GEK) until
- // this finishes, so nobody lands on a page that looks broken, or hits
- // a "not configured" error from racing ahead of it. Can take tens of
- // minutes on a slow disk with a large library — the node
- // keeps scanning on its own either way (test_hot_reload_survives_
- // client_close.py); this step is only about not lying about it.
- update('running');
- await platform.waitForGroupHosted(gid, setIndexProgress);
- update('done');
- advance();
-
// 5. Add extra roots (if >1)
if (roots.length > 1) {
update('running');