Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion packages/ui/src/bulletin-bitswap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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.",
);
Expand Down
6 changes: 1 addition & 5 deletions packages/ui/src/host-callbacks/Preimage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -35,7 +34,7 @@ function createPreimageLookupSubscribe(
let stopped = false;
return createResultStream<Uint8Array | undefined>(
[undefined],
(push, pushError) => {
(push, _pushError) => {
let intervalId: ReturnType<typeof setInterval> | null = null;
let initialTimeoutId: ReturnType<typeof setTimeout> | null = null;
const stopPolling = (): void => {
Expand Down Expand Up @@ -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)}`,
});
}
};

Expand Down
26 changes: 16 additions & 10 deletions packages/ui/tests/preimage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
Loading