diff options
Diffstat (limited to 'packages/meshbay-hub')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/app.js | 46 |
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'); |