From 344ac8028a9b6352968de25dc790e2894a401c7a Mon Sep 17 00:00:00 2001 From: pgherveou Date: Mon, 13 Jul 2026 22:54:55 +0200 Subject: [PATCH] fix(ui): keep preimage lookup polling --- packages/ui/src/bulletin-bitswap.ts | 9 +++++++- packages/ui/src/host-callbacks/Preimage.ts | 6 +---- packages/ui/tests/preimage.test.ts | 26 +++++++++++++--------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/ui/src/bulletin-bitswap.ts b/packages/ui/src/bulletin-bitswap.ts index 06dca7cc..143d8e0b 100644 --- a/packages/ui/src/bulletin-bitswap.ts +++ b/packages/ui/src/bulletin-bitswap.ts @@ -12,6 +12,7 @@ import { isRemoteChainSupported, } from "@dotli/protocol/client"; import { isSandboxOrigin } from "@dotli/config/config"; +import { getBackend } from "@dotli/config/mode"; import { getActiveServicesConfig } from "@dotli/config/network"; import { log } from "@dotli/shared/log"; import { serializeError } from "@dotli/shared/errors"; @@ -200,7 +201,13 @@ function isBitswapGetMessage(value: unknown): value is BitswapGetMessage { /** Idempotent. Call once at host startup. */ export function listenForSandboxBitswap(): void { - if (!isRemoteChainSupported(getActiveServicesConfig().bulletin.genesis)) { + if (getBackend() === "rpc-gateway") { + log.warn( + "[dot.li bitswap-relay] Bitswap is unavailable in RPC gateway mode; sandbox bitswap requests will fail.", + ); + } else if ( + !isRemoteChainSupported(getActiveServicesConfig().bulletin.genesis) + ) { log.warn( "[dot.li bitswap-relay] Bulletin not in supported chain set; sandbox bitswap requests will fail.", ); diff --git a/packages/ui/src/host-callbacks/Preimage.ts b/packages/ui/src/host-callbacks/Preimage.ts index c2ff22ac..1bf06c41 100644 --- a/packages/ui/src/host-callbacks/Preimage.ts +++ b/packages/ui/src/host-callbacks/Preimage.ts @@ -6,7 +6,6 @@ import type { PreimageHost } from "@parity/truapi-host"; import { hashToCid } from "@dotli/content/preimage"; import { fetchFromIpfs } from "@dotli/content/ipfs"; import { getBackend } from "@dotli/config/mode"; -import { serializeError } from "@dotli/shared/errors"; import { log } from "@dotli/shared/log"; import { bitswapGet } from "../bulletin-bitswap"; import { toHex } from "@dotli/shared/hex"; @@ -35,7 +34,7 @@ function createPreimageLookupSubscribe( let stopped = false; return createResultStream( [undefined], - (push, pushError) => { + (push, _pushError) => { let intervalId: ReturnType | null = null; let initialTimeoutId: ReturnType | null = null; const stopPolling = (): void => { @@ -83,9 +82,6 @@ function createPreimageLookupSubscribe( } } catch (err) { log.warn(`[${label}] preimage lookup via ${backend} failed:`, err); - pushError({ - reason: `preimage lookup via ${backend} failed: ${serializeError(err)}`, - }); } }; diff --git a/packages/ui/tests/preimage.test.ts b/packages/ui/tests/preimage.test.ts index 73c04dcd..9a5e87ac 100644 --- a/packages/ui/tests/preimage.test.ts +++ b/packages/ui/tests/preimage.test.ts @@ -40,33 +40,39 @@ describe("preimage host callbacks", () => { expect("submitPreimage" in adapters).toBe(false); }); - it("emits lookup backend failures as stream errors", async () => { + it("keeps polling after transient lookup backend failures", async () => { vi.useFakeTimers(); try { const { lookupPreimage } = createPreimageAdapters("myapp"); const missingKey = new Uint8Array(32); + const found = new Uint8Array([1, 2, 3]); mocks.fetchFromIpfs.mockRejectedValueOnce( new Error("gateway unavailable"), ); + mocks.fetchFromIpfs.mockResolvedValueOnce({ data: found }); const iterator = lookupPreimage(missingKey)[Symbol.asyncIterator](); const first = await iterator.next(); const secondPromise = iterator.next(); + let secondSettled = false; + void secondPromise.then(() => { + secondSettled = true; + }); await vi.advanceTimersByTimeAsync(1000); - const second = await secondPromise; - const done = await iterator.next(); expect(first.done).toBe(false); expect(first.value.isOk()).toBe(true); expect(first.value._unsafeUnwrap()).toBeUndefined(); - expect(second.done).toBe(false); - expect(second.value.isErr()).toBe(true); - expect(second.value._unsafeUnwrapErr().reason).toContain( - "preimage lookup via rpc-gateway failed: gateway unavailable", - ); - await vi.advanceTimersByTimeAsync(10_000); + expect(secondSettled).toBe(false); expect(mocks.fetchFromIpfs).toHaveBeenCalledTimes(1); - expect(done.done).toBe(true); + + await vi.advanceTimersByTimeAsync(9000); + const second = await secondPromise; + expect(second.done).toBe(false); + expect(second.value.isOk()).toBe(true); + expect(second.value._unsafeUnwrap()).toEqual(found); + expect(mocks.fetchFromIpfs).toHaveBeenCalledTimes(2); + await iterator.return?.(); } finally { vi.useRealTimers(); }