mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(traffic): pass fetchFlowDetail through the layer's source slot
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
ae4b382262
commit
4c1ebfb877
2 files changed
+112
-17
No files matched your search
@@ -9,9 +9,18 @@ const sourceSlot = createSourceSlot(
|
|||||||
{
|
{
|
||||||
getFlowSessionStats: () => ({ tilesFetched: 0 }),
|
getFlowSessionStats: () => ({ tilesFetched: 0 }),
|
||||||
resetFlowTileCache: () => {},
|
resetFlowTileCache: () => {},
|
||||||
|
// The layer reads stale cached tiles through this; a source without it
|
||||||
|
// answers with fresh segments only.
|
||||||
|
fetchFlowDetail: async (...args) => ({
|
||||||
|
segments: await sourceSlot.source.fetchFlowForBounds(...args),
|
||||||
|
stale: false,
|
||||||
|
oldestTileAt: null,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
export const configureTrafficSource = sourceSlot.configure;
|
export const configureTrafficSource = sourceSlot.configure;
|
||||||
|
/** The source the traffic layer reads, as configured. */
|
||||||
|
export const trafficSource = sourceSlot.source;
|
||||||
const layer = createApplicationTraffic({
|
const layer = createApplicationTraffic({
|
||||||
source: sourceSlot.source,
|
source: sourceSlot.source,
|
||||||
});
|
});
|
||||||
|
|||||||
+103
-17
@@ -22,7 +22,10 @@ import { DataLayerManager, layerFeedState } from './manager.js';
|
|||||||
const LIVE_CLAIM = /\bLIVE\b|\bGPS\b|\breal[- ]?time\b/;
|
const LIVE_CLAIM = /\bLIVE\b|\bGPS\b|\breal[- ]?time\b/;
|
||||||
|
|
||||||
test('a superseded flow fetch is not an outage', () => {
|
test('a superseded flow fetch is not an outage', () => {
|
||||||
assert.equal(deriveTrafficFlowError({ name: 'AbortError', message: 'aborted' }), null);
|
assert.equal(
|
||||||
|
deriveTrafficFlowError({ name: 'AbortError', message: 'aborted' }),
|
||||||
|
null,
|
||||||
|
);
|
||||||
assert.equal(deriveTrafficFlowError(null), null);
|
assert.equal(deriveTrafficFlowError(null), null);
|
||||||
assert.equal(deriveTrafficFlowError(undefined), null);
|
assert.equal(deriveTrafficFlowError(undefined), null);
|
||||||
});
|
});
|
||||||
@@ -30,10 +33,22 @@ test('a superseded flow fetch is not an outage', () => {
|
|||||||
test('flow failures map onto short, specific reasons', () => {
|
test('flow failures map onto short, specific reasons', () => {
|
||||||
const reason = (message) => deriveTrafficFlowError(new Error(message));
|
const reason = (message) => deriveTrafficFlowError(new Error(message));
|
||||||
assert.equal(reason('flow tile 12/1/1: HTTP 503'), 'TomTom key unavailable');
|
assert.equal(reason('flow tile 12/1/1: HTTP 503'), 'TomTom key unavailable');
|
||||||
assert.equal(reason('flow tile 12/1/1: HTTP 429'), 'TomTom daily budget reached');
|
assert.equal(
|
||||||
assert.equal(reason('flow tile 12/1/1: HTTP 502'), 'TomTom upstream unreachable');
|
reason('flow tile 12/1/1: HTTP 429'),
|
||||||
assert.equal(reason('flow tile 12/1/1: HTTP 504'), 'TomTom upstream unreachable');
|
'TomTom daily budget reached',
|
||||||
assert.equal(reason('flow tile 12/1/1: HTTP 418'), 'TomTom flow error (HTTP 418)');
|
);
|
||||||
|
assert.equal(
|
||||||
|
reason('flow tile 12/1/1: HTTP 502'),
|
||||||
|
'TomTom upstream unreachable',
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
reason('flow tile 12/1/1: HTTP 504'),
|
||||||
|
'TomTom upstream unreachable',
|
||||||
|
);
|
||||||
|
assert.equal(
|
||||||
|
reason('flow tile 12/1/1: HTTP 418'),
|
||||||
|
'TomTom flow error (HTTP 418)',
|
||||||
|
);
|
||||||
assert.equal(reason('flow fetch failed'), 'TomTom flow unavailable');
|
assert.equal(reason('flow fetch failed'), 'TomTom flow unavailable');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -56,19 +71,32 @@ test('no keyless label ever implies a live feed', () => {
|
|||||||
trafficFeedPresentation({ liveMode: false, fetching: false }),
|
trafficFeedPresentation({ liveMode: false, fetching: false }),
|
||||||
trafficFeedPresentation({ liveMode: false, fetching: true }),
|
trafficFeedPresentation({ liveMode: false, fetching: true }),
|
||||||
trafficFeedPresentation({ statusUnavailable: true }),
|
trafficFeedPresentation({ statusUnavailable: true }),
|
||||||
trafficFeedPresentation({ liveMode: true, flowError: 'TomTom flow unavailable' }),
|
trafficFeedPresentation({
|
||||||
trafficFeedPresentation({ liveMode: true, fetching: true, flowError: 'TomTom flow unavailable' }),
|
liveMode: true,
|
||||||
|
flowError: 'TomTom flow unavailable',
|
||||||
|
}),
|
||||||
|
trafficFeedPresentation({
|
||||||
|
liveMode: true,
|
||||||
|
fetching: true,
|
||||||
|
flowError: 'TomTom flow unavailable',
|
||||||
|
}),
|
||||||
].map((feed) => feed.loadingLabel);
|
].map((feed) => feed.loadingLabel);
|
||||||
for (const label of labels) {
|
for (const label of labels) {
|
||||||
assert.ok(!LIVE_CLAIM.test(label), `label implies live data: ${label}`);
|
assert.ok(!LIVE_CLAIM.test(label), `label implies live data: ${label}`);
|
||||||
assert.ok(label.startsWith('SIMULATED'), `fallback label must lead with the mode: ${label}`);
|
assert.ok(
|
||||||
|
label.startsWith('SIMULATED'),
|
||||||
|
`fallback label must lead with the mode: ${label}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('simulating because the status probe failed reads differently from keyless by design', () => {
|
test('simulating because the status probe failed reads differently from keyless by design', () => {
|
||||||
const probeDown = trafficFeedPresentation({ statusUnavailable: true });
|
const probeDown = trafficFeedPresentation({ statusUnavailable: true });
|
||||||
assert.equal(probeDown.mode, 'sim');
|
assert.equal(probeDown.mode, 'sim');
|
||||||
assert.equal(probeDown.loadingLabel, 'SIMULATED — traffic service unreachable');
|
assert.equal(
|
||||||
|
probeDown.loadingLabel,
|
||||||
|
'SIMULATED — traffic service unreachable',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('a healthy keyed layer reports live flow with its real coverage', () => {
|
test('a healthy keyed layer reports live flow with its real coverage', () => {
|
||||||
@@ -76,7 +104,8 @@ test('a healthy keyed layer reports live flow with its real coverage', () => {
|
|||||||
assert.deepEqual(idle, {
|
assert.deepEqual(idle, {
|
||||||
mode: 'live',
|
mode: 'live',
|
||||||
error: null,
|
error: null,
|
||||||
loadingLabel: 'LIVE · Roads: OpenStreetMap · Flow: TomTom · 87% cov · Unmatched: simulated',
|
loadingLabel:
|
||||||
|
'LIVE · Roads: OpenStreetMap · Flow: TomTom · 87% cov · Unmatched: simulated',
|
||||||
});
|
});
|
||||||
assert.equal(
|
assert.equal(
|
||||||
trafficFeedPresentation({ liveMode: true, fetching: true }).loadingLabel,
|
trafficFeedPresentation({ liveMode: true, fetching: true }).loadingLabel,
|
||||||
@@ -100,7 +129,11 @@ test('a mid-session flow outage degrades instead of reporting stale live coverag
|
|||||||
fetching: true,
|
fetching: true,
|
||||||
flowError: 'TomTom daily budget reached',
|
flowError: 'TomTom daily budget reached',
|
||||||
});
|
});
|
||||||
assert.deepEqual(busy, down, 'the degraded state reads the same whether or not a load is in flight');
|
assert.deepEqual(
|
||||||
|
busy,
|
||||||
|
down,
|
||||||
|
'the degraded state reads the same whether or not a load is in flight',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('the rendered steady-state meta line carries the SIMULATED copy', () => {
|
test('the rendered steady-state meta line carries the SIMULATED copy', () => {
|
||||||
@@ -116,10 +149,12 @@ test('the rendered steady-state meta line carries the SIMULATED copy', () => {
|
|||||||
assert.equal(
|
assert.equal(
|
||||||
mgr._buildMetaText({
|
mgr._buildMetaText({
|
||||||
source: 'OpenStreetMap',
|
source: 'OpenStreetMap',
|
||||||
stats: stats(trafficFeedPresentation({
|
stats: stats(
|
||||||
|
trafficFeedPresentation({
|
||||||
liveMode: true,
|
liveMode: true,
|
||||||
flowError: 'TomTom daily budget reached',
|
flowError: 'TomTom daily budget reached',
|
||||||
})),
|
}),
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
'DEGRADED · OpenStreetMap · SIMULATED — TomTom daily budget reached',
|
'DEGRADED · OpenStreetMap · SIMULATED — TomTom daily budget reached',
|
||||||
);
|
);
|
||||||
@@ -128,17 +163,26 @@ test('the rendered steady-state meta line carries the SIMULATED copy', () => {
|
|||||||
test('the manager reads keyless as FALLBACK and an outage as DEGRADED', () => {
|
test('the manager reads keyless as FALLBACK and an outage as DEGRADED', () => {
|
||||||
const settled = { count: 4200, lastUpdate: Date.now() };
|
const settled = { count: 4200, lastUpdate: Date.now() };
|
||||||
assert.equal(
|
assert.equal(
|
||||||
layerFeedState({ ...settled, ...trafficFeedPresentation({ liveMode: false }) }),
|
layerFeedState({
|
||||||
|
...settled,
|
||||||
|
...trafficFeedPresentation({ liveMode: false }),
|
||||||
|
}),
|
||||||
'fallback',
|
'fallback',
|
||||||
);
|
);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
layerFeedState({ ...settled, ...trafficFeedPresentation({ liveMode: true }) }),
|
layerFeedState({
|
||||||
|
...settled,
|
||||||
|
...trafficFeedPresentation({ liveMode: true }),
|
||||||
|
}),
|
||||||
'nominal',
|
'nominal',
|
||||||
);
|
);
|
||||||
assert.equal(
|
assert.equal(
|
||||||
layerFeedState({
|
layerFeedState({
|
||||||
...settled,
|
...settled,
|
||||||
...trafficFeedPresentation({ liveMode: true, flowError: 'TomTom flow unavailable' }),
|
...trafficFeedPresentation({
|
||||||
|
liveMode: true,
|
||||||
|
flowError: 'TomTom flow unavailable',
|
||||||
|
}),
|
||||||
}),
|
}),
|
||||||
'degraded',
|
'degraded',
|
||||||
);
|
);
|
||||||
@@ -148,7 +192,10 @@ test('the shipped layer boots keyless-honest before any status check', () => {
|
|||||||
const stats = trafficLayer.getStats();
|
const stats = trafficLayer.getStats();
|
||||||
assert.equal(stats.mode, 'sim');
|
assert.equal(stats.mode, 'sim');
|
||||||
assert.equal(stats.error, null);
|
assert.equal(stats.error, null);
|
||||||
assert.ok(!LIVE_CLAIM.test(stats.loadingLabel), `boot label implies live data: ${stats.loadingLabel}`);
|
assert.ok(
|
||||||
|
!LIVE_CLAIM.test(stats.loadingLabel),
|
||||||
|
`boot label implies live data: ${stats.loadingLabel}`,
|
||||||
|
);
|
||||||
assert.equal(layerFeedState(stats), 'fallback');
|
assert.equal(layerFeedState(stats), 'fallback');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -167,3 +214,42 @@ test('zero matched dots never claims live coverage', () => {
|
|||||||
assert.match(feed.loadingLabel, /TomTom \(no matches\)/);
|
assert.match(feed.loadingLabel, /TomTom \(no matches\)/);
|
||||||
assert.ok(!LIVE_CLAIM.test(feed.loadingLabel));
|
assert.ok(!LIVE_CLAIM.test(feed.loadingLabel));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('the traffic layer source passes fetchFlowDetail through, so stale tiles reach the layer', async () => {
|
||||||
|
const { trafficSource, configureTrafficSource } =
|
||||||
|
await import('./traffic.js');
|
||||||
|
assert.equal(typeof trafficSource.fetchFlowDetail, 'function');
|
||||||
|
const base = {
|
||||||
|
requestRoads: async () => ({}),
|
||||||
|
getStatus: async () => ({}),
|
||||||
|
fetchFlowForBounds: async () => ['segment'],
|
||||||
|
};
|
||||||
|
let release = configureTrafficSource({
|
||||||
|
...base,
|
||||||
|
fetchFlowDetail: async () => ({
|
||||||
|
segments: ['segment'],
|
||||||
|
stale: true,
|
||||||
|
oldestTileAt: 1000,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
assert.deepEqual(await trafficSource.fetchFlowDetail({}), {
|
||||||
|
segments: ['segment'],
|
||||||
|
stale: true,
|
||||||
|
oldestTileAt: 1000,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
// A source without fetchFlowDetail answers with fresh segments.
|
||||||
|
release = configureTrafficSource(base);
|
||||||
|
try {
|
||||||
|
assert.deepEqual(await trafficSource.fetchFlowDetail({}), {
|
||||||
|
segments: ['segment'],
|
||||||
|
stale: false,
|
||||||
|
oldestTileAt: null,
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in new issue
Block a user