mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-05 02:44:02 +00:00
refactor: separate transit sources and request service
This commit is contained in:
1 parent
e284a9cd34
commit
3155e4e0bf
26 files changed
+1444
-1157
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import { createTransitSource } from './source.js';
|
||||
import { createTrails } from './trails.js';
|
||||
import { createState } from './state.js';
|
||||
import { createHeight } from './height.js';
|
||||
@@ -23,15 +24,26 @@ import { TRANSIT_POLL_MS } from './policy.js';
|
||||
* @param {{services: object}} options
|
||||
* @returns {object} The data-layer module the manager registers.
|
||||
*/
|
||||
export function createTransitLayer({ services }) {
|
||||
export function createTransitLayer({
|
||||
services,
|
||||
source = createTransitSource(),
|
||||
}) {
|
||||
if (!services?.overlays || !services?.render || !services?.sprites) {
|
||||
throw new TypeError(
|
||||
'A transit layer needs overlay, render and sprite services',
|
||||
);
|
||||
}
|
||||
if (
|
||||
typeof source?.requestSnapshot !== 'function' ||
|
||||
typeof source?.getHistory !== 'function'
|
||||
) {
|
||||
throw new TypeError(
|
||||
'A transit source needs snapshot and history operations',
|
||||
);
|
||||
}
|
||||
const state = createState({ services });
|
||||
const parts = {};
|
||||
const context = { state, services, parts };
|
||||
const context = { state, services, parts, source };
|
||||
parts.trails = createTrails(context);
|
||||
parts.height = createHeight(context);
|
||||
parts.selection = createSelection(context);
|
||||
|
||||
@@ -46,7 +46,7 @@ export const ORDER_REJECTS_BEFORE_RESET = 3;
|
||||
* @param {object} context
|
||||
* @returns {object}
|
||||
*/
|
||||
export function createIngestion({ state, services, parts }) {
|
||||
export function createIngestion({ state, services, parts, source }) {
|
||||
const { governorRequestRender } = services.render;
|
||||
const { registerDynamicCredit, transitFeedCredit } = services.credits;
|
||||
|
||||
@@ -436,13 +436,9 @@ export function createIngestion({ state, services, parts }) {
|
||||
status.loading = status.count === 0;
|
||||
const promise = (async () => {
|
||||
try {
|
||||
const response = await fetch(
|
||||
`/api/transit/vehicles/${encodeURIComponent(feed.id)}`,
|
||||
{
|
||||
signal: controller.signal,
|
||||
headers: { Accept: 'application/json' },
|
||||
},
|
||||
);
|
||||
const response = await source.requestSnapshot(feed.id, {
|
||||
signal: controller.signal,
|
||||
});
|
||||
if (!response.ok) {
|
||||
// The proxy says when it will next try the operator; carrying that
|
||||
// through means the row can offer a time instead of just a shrug.
|
||||
|
||||
@@ -150,6 +150,7 @@ function groundStub(floorAt) {
|
||||
function harness(
|
||||
t,
|
||||
{
|
||||
source,
|
||||
altitude = 4_000,
|
||||
floorAt = () => 12,
|
||||
at = BOSTON,
|
||||
@@ -263,6 +264,7 @@ function harness(
|
||||
/** Every call the floor cycle makes to the rendered-mesh sampler. */
|
||||
const meshCalls = [];
|
||||
const layer = createTransitLayer({
|
||||
source,
|
||||
services: {
|
||||
ground,
|
||||
mesh: {
|
||||
@@ -3639,3 +3641,35 @@ test('moving and stationary transit stay adjacent above CCTV and Bikeshare durin
|
||||
assert.equal(entry.marker.id, entry.key);
|
||||
}
|
||||
});
|
||||
|
||||
test('transit polls the supplied source and cancels it when disabled', async (t) => {
|
||||
const calls = [];
|
||||
const source = {
|
||||
async requestSnapshot(feedId, { signal }) {
|
||||
calls.push({ feedId, signal });
|
||||
return Response.json(
|
||||
snapshot(
|
||||
feedId,
|
||||
'MBTA',
|
||||
[vehicle('injected', 42.36, -71.06, reported())],
|
||||
{ fetchedAt: Date.now() },
|
||||
),
|
||||
);
|
||||
},
|
||||
async getHistory() {
|
||||
throw new Error('No selected vehicle');
|
||||
},
|
||||
};
|
||||
const app = harness(t, { source });
|
||||
globalThis.fetch = () => {
|
||||
throw new Error('Unexpected global fetch');
|
||||
};
|
||||
app.layer.enable(app.viewer);
|
||||
await app.layer.update();
|
||||
assert.ok(calls.some(({ feedId }) => feedId === 'mbta'));
|
||||
assert.ok(app.vehicles().some((entry) => entry.record.id === 'injected'));
|
||||
const before = calls.length;
|
||||
app.layer.disable(app.viewer);
|
||||
await app.layer.update();
|
||||
assert.equal(calls.length, before);
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { fetchTransitHistory } from '../../sources/transitHistory.js';
|
||||
|
||||
/** Request transit snapshots through caller-owned transport. */
|
||||
export function createTransitSource({
|
||||
fetchImpl = (...args) => fetch(...args),
|
||||
} = {}) {
|
||||
return {
|
||||
getHistory(feedId, vehicleId, { signal } = {}) {
|
||||
signal?.throwIfAborted();
|
||||
return fetchTransitHistory(feedId, vehicleId, signal, fetchImpl);
|
||||
},
|
||||
requestSnapshot(feedId, { signal } = {}) {
|
||||
signal?.throwIfAborted();
|
||||
if (typeof feedId !== 'string' || !feedId || feedId.length > 160)
|
||||
throw new TypeError('A transit feed identifier is required');
|
||||
return fetchImpl(`/api/transit/vehicles/${encodeURIComponent(feedId)}`, {
|
||||
signal,
|
||||
headers: { Accept: 'application/json' },
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
import { fetchTransitHistory } from '../../data/transitProxy.js';
|
||||
import { getRegisteredTransitFeed } from '../../data/transitFeeds.js';
|
||||
import * as Cesium from 'cesium';
|
||||
import {
|
||||
@@ -23,7 +22,7 @@ export const TRAIL_VERTEX_LIMIT = 2048;
|
||||
const STEP_M = 25;
|
||||
|
||||
/** Shared prepared paths. Floors are aligned to work with Google 3D tiles. */
|
||||
export function createTrails({ state, services, parts }) {
|
||||
export function createTrails({ state, services, parts, source }) {
|
||||
let historyRequest = null;
|
||||
let requestCount = 0,
|
||||
abortCount = 0;
|
||||
@@ -233,7 +232,10 @@ export function createTrails({ state, services, parts }) {
|
||||
const controller = new AbortController();
|
||||
historyRequest = controller;
|
||||
requestCount++;
|
||||
fetchTransitHistory(entry.feedId, entry.record.id, controller.signal)
|
||||
source
|
||||
.getHistory(entry.feedId, entry.record.id, {
|
||||
signal: controller.signal,
|
||||
})
|
||||
.then((payload) => {
|
||||
if (
|
||||
controller.signal.aborted ||
|
||||
|
||||
Reference in new issue
Block a user