fix: respect query eligibility in screen sync (WealthLedger/frontend#54) #82
@@ -78,4 +78,35 @@ describe("read-only screen synchronization", () => {
|
||||
await act(async () => result.current.refresh());
|
||||
await waitFor(() => expect(gets).toBe(2));
|
||||
});
|
||||
|
||||
it("does not manually refetch disabled resources", async () => {
|
||||
vi.useFakeTimers();
|
||||
const refetch = vi.fn(() => Promise.resolve());
|
||||
|
||||
const resource = {
|
||||
isEnabled: false,
|
||||
isError: true,
|
||||
isFetching: false,
|
||||
queryKey: [],
|
||||
refetch,
|
||||
};
|
||||
|
||||
try {
|
||||
const { result, unmount } = renderHook(() =>
|
||||
useScreenSync({ screen: "accounts" }, [resource]),
|
||||
);
|
||||
|
||||
await act(async () => {
|
||||
await result.current.refresh();
|
||||
await result.current.retry();
|
||||
});
|
||||
await act(() => vi.advanceTimersByTime(1_800_000));
|
||||
|
||||
expect(refetch).not.toHaveBeenCalled();
|
||||
unmount();
|
||||
}
|
||||
finally {
|
||||
vi.useRealTimers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useEffect, useRef } from "react";
|
||||
import type { InvestmentResourceMeta } from "@/shared/api";
|
||||
|
||||
type ScreenResource = {
|
||||
isEnabled: boolean;
|
||||
isError: boolean;
|
||||
isFetching: boolean;
|
||||
meta?: InvestmentResourceMeta;
|
||||
@@ -27,23 +28,31 @@ function useScreenSync(_scope: ScreenScope, resources: ScreenResource[]) {
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
for (const resource of resourcesRef.current)
|
||||
for (const resource of resourcesRef.current) {
|
||||
if (!resource.isEnabled || resource.isFetching) continue;
|
||||
void resource.refetch().catch(() => {});
|
||||
}
|
||||
}, READ_INTERVAL_MS);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
const isRefreshing = resources.some(resource => resource.isFetching);
|
||||
const isRefreshing = resources.some(
|
||||
resource => resource.isEnabled && resource.isFetching,
|
||||
);
|
||||
|
||||
const eligible = resources.filter(
|
||||
resource => resource.isEnabled && !resource.isFetching,
|
||||
);
|
||||
|
||||
const refresh = async () => {
|
||||
if (isRefreshing) return;
|
||||
await Promise.allSettled(resources.map(resource => resource.refetch()));
|
||||
await Promise.allSettled(eligible.map(resource => resource.refetch()));
|
||||
};
|
||||
|
||||
// Retry only the HTTP read; source attempts are reported in resource metadata.
|
||||
const retry = async () => {
|
||||
const failed = resources.filter(resource => resource.isError);
|
||||
const failed = eligible.filter(resource => resource.isError);
|
||||
|
||||
if (failed.length > 0)
|
||||
await Promise.allSettled(failed.map(resource => resource.refetch()));
|
||||
|
||||
Reference in New Issue
Block a user