mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-14 23:32:20 +00:00
fix(news): keep a refused key refused during a slow read, and read Local when Conflicts fails
A slow re-read of a refused key read as unavailable until it landed; it now stays refused. The first-read wait is 10 s, for a margin under the browser's 15 s. A failed Conflicts read no longer stops Local's refresh, which the server reads on its own. Tests cover GDELT's wait, the refused key and a caller abort past the timeout, and fail rather than hang; the docs say what a section serves meanwhile.
This commit is contained in:
1 parent
c6ae4c44d7
commit
61424e4256
7 files changed
+176
-42
No files matched your search
@@ -1428,6 +1428,8 @@ export function createNewsLayer({
|
||||
}
|
||||
unavailable = cause?.unavailable === true;
|
||||
error = cause?.message || FEED_UNAVAILABLE;
|
||||
// Local is read apart: Conflicts failing leaves it reading.
|
||||
void refreshInView({ force: inView.active });
|
||||
return true;
|
||||
} finally {
|
||||
signal?.removeEventListener('abort', abort);
|
||||
|
||||
@@ -799,6 +799,47 @@ test('without Liveuamap reports or a Local area, nothing is credited', async (t)
|
||||
assert.deepEqual(credits, []);
|
||||
});
|
||||
|
||||
test('a failed Conflicts read leaves Local reading with each refresh', async (t) => {
|
||||
t.mock.timers.enable({ apis: ['setTimeout'] });
|
||||
const failure = () => new Error('News feed unavailable');
|
||||
let local = failure();
|
||||
const { layer } = fixture(t, {
|
||||
height: 1_000_000,
|
||||
source: {
|
||||
getHotspots: async () => {
|
||||
throw failure();
|
||||
},
|
||||
getFeed: async (query) => {
|
||||
if (!query.at) throw failure();
|
||||
if (local) throw local;
|
||||
return {
|
||||
reports: [report('inside', { relevance: 'minor' })],
|
||||
nextBefore: null,
|
||||
};
|
||||
},
|
||||
getAreaOutline: async () => ukraine,
|
||||
},
|
||||
});
|
||||
layer.enable();
|
||||
await layer.update();
|
||||
layer.setParams({ filters: { section: 'local' } });
|
||||
await flush();
|
||||
assert.equal(
|
||||
layer.getRowControls().feed.inView.error,
|
||||
'News feed unavailable',
|
||||
);
|
||||
// The area's read lands meanwhile; Conflicts still fails.
|
||||
local = null;
|
||||
await layer.update();
|
||||
await flush();
|
||||
const view = layer.getRowControls().feed;
|
||||
assert.deepEqual(
|
||||
view.inView.items.map((item) => item.id),
|
||||
['inside'],
|
||||
);
|
||||
assert.equal(view.error, 'News feed unavailable');
|
||||
});
|
||||
|
||||
test('a failed read keeps the layer on with an error; disable clears the overlay', async (t) => {
|
||||
const { layer, entries } = fixture(t, {
|
||||
source: { getFeed: async () => Promise.reject(new Error('boom')) },
|
||||
|
||||
@@ -176,12 +176,24 @@ test('reads time out and follow the caller signal', async () => {
|
||||
);
|
||||
});
|
||||
const slow = createNewsSource({ fetchImpl: hang, timeoutMs: 20 });
|
||||
// Out of time it reads unavailable, in the app's words, and is retried.
|
||||
// Out of time it reads unavailable, in the app's words, as retryable.
|
||||
await assert.rejects(slow.getHotspots(), {
|
||||
message: 'News feed unavailable',
|
||||
code: 'timeout',
|
||||
retryable: true,
|
||||
});
|
||||
// The caller's abort stays its own, even once the time is up too.
|
||||
const late = (_url, { signal }) =>
|
||||
new Promise((_, reject) => {
|
||||
setTimeout(() => reject(signal.reason), 40);
|
||||
});
|
||||
const leaving = new AbortController();
|
||||
const gone = createNewsSource({ fetchImpl: late, timeoutMs: 20 }).getFeed(
|
||||
{},
|
||||
{ signal: leaving.signal },
|
||||
);
|
||||
leaving.abort(new Error('gone'));
|
||||
await assert.rejects(gone, /gone/);
|
||||
const caller = new AbortController();
|
||||
const pending = createNewsSource({ fetchImpl: hang }).getFeed(
|
||||
{},
|
||||
|
||||
Reference in new issue
Block a user