host/engine: visible error/retry state for failed fetches + retry on network failure
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 30s
Two engine fixes in web/orchestration.sx (rebuilt into the WASM bytecode) plus the blog CSS that surfaces them. 1. Retry on NETWORK failure, not just HTTP errors. The fetch error/catch path (the real offline / DNS / connection-refused case) previously dispatched sx:requestError and stopped — only a non-ok HTTP response with an empty body ever reached handle-retry. So "no connection" never recovered. Now the catch path calls handle-retry too, so an sx-retry element actually self-heals when the connection returns (the cap bounds the backoff interval, not the attempt count — it retries forever). 2. Visible failure state. On any failed/aborted fetch the engine adds an `.sx-error` class to the element (cleared, with the retry backoff reset, on the next success). Without it a stuck retry loop is invisible — the picker just sits "Loading…". The blog shell ships CSS so the relate picker shows "Connection problem — retrying…" / "offline, retrying…" on .sx-error. Platform-wide: any sx-get/sx-post element benefits, not just the picker. Tests: relate-picker.spec.js gains a 6th case — abort relate-options, assert .sx-error appears, un-abort, assert it clears and the picker repopulates (proving the retry loop is live). 6/6 browser + 272/272 conformance. WASM web stack rebuilt (orchestration.sxbc + the static hs-* copies refreshed by the same build). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -109,4 +109,20 @@ test.describe('relate picker', () => {
|
||||
await expect.poll(() => page.locator(RELROWS).count(), { timeout: 12000 }).toBeGreaterThanOrEqual(1);
|
||||
await expect(page.locator(RELR)).toContainText('Picker Item');
|
||||
});
|
||||
|
||||
test('a dropped relate-options fetch shows a visible error/retry state', async ({ page }) => {
|
||||
// Simulate the connection dropping for the candidate endpoint. The engine's
|
||||
// fetch rejects -> it marks .sx-error on the picker (and keeps retrying), so a
|
||||
// stuck/offline picker is VISIBLE instead of an endless silent "Loading…".
|
||||
await page.route('**/relate-options*', (route) => route.abort());
|
||||
await loginTo(page, `/${HOST}/edit`);
|
||||
await waitReady(page);
|
||||
// the filter form's "load" fetch fails -> .sx-error lands on the picker form
|
||||
await expect(page.locator(`${REL}.sx-error`)).toHaveCount(1, { timeout: 12000 });
|
||||
// and recovery: once the endpoint works again, the next retry clears the error
|
||||
// and populates (proves the retry loop is live, not a dead end).
|
||||
await page.unroute('**/relate-options*');
|
||||
await expect(page.locator(`${REL}.sx-error`)).toHaveCount(0, { timeout: 35000 });
|
||||
await expect.poll(() => page.locator(RELROWS).count(), { timeout: 12000 }).toBeGreaterThan(0);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user