mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-05 04:04:07 +00:00
fix(roadtrip): stop pacing the joins between days that come back from the route cache
With connected days, every join between two days kept its one-request-a-second slot even when the route came back from the device's cache, so a long road trip still waited about a second per join on every open. A join answered from the cache now gives its slot back; requests that go out stay spaced as before. Refs #2794
This commit is contained in:
@@ -803,6 +803,34 @@ describe('useRoadtripRoutes', () => {
|
||||
}
|
||||
})
|
||||
|
||||
it('FE-ROADTRIP-ROUTES-052: a join this device routed before is not paced like a request (#2794)', async () => {
|
||||
// A join kept its request slot whatever answered it, so a month of connected days
|
||||
// waited half a minute on every open with every road already on the device. The
|
||||
// clock is held still, so every answer reads as one from the cache; a join that
|
||||
// still waited its turn would wait 1.1 s of real time, past what waitFor gives it.
|
||||
const clock = vi.spyOn(performance, 'now').mockImplementation(() => 10_000)
|
||||
try {
|
||||
const MUNICH: [number, number] = [48.1374, 11.5755]
|
||||
const INNSBRUCK: [number, number] = [47.2692, 11.4041]
|
||||
const BOZEN: [number, number] = [46.4983, 11.3548]
|
||||
setting({ roadtrip_connect_days: true })
|
||||
const daysList = [day(1, 1), day(2, 2), day(3, 3)]
|
||||
const assignments = {
|
||||
...map(1, [{ id: 1, at: HAMBURG, time: '09:00' }, { id: 2, at: LUENEBURG }]),
|
||||
...map(2, [{ id: 3, at: BERLIN, time: '09:00' }, { id: 4, at: MUNICH }]),
|
||||
...map(3, [{ id: 5, at: INNSBRUCK, time: '09:00' }, { id: 6, at: BOZEN }]),
|
||||
} as AssignmentsMap
|
||||
renderHook(() => useRoadtripRoutes(7, daysList, assignments))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(askedFor(LUENEBURG, BERLIN)).toHaveLength(1)
|
||||
expect(askedFor(MUNICH, INNSBRUCK)).toHaveLength(1)
|
||||
})
|
||||
} finally {
|
||||
clock.mockRestore()
|
||||
}
|
||||
})
|
||||
|
||||
it('FE-ROADTRIP-ROUTES-051: a join OSRM answered in the engine’s place is drawn, flagged, and asked for again on request', async () => {
|
||||
// Filed like any answer, it stood in for the weighed road until the page was loaded
|
||||
// again, and a picker on it read the stand-in line as the road already taken.
|
||||
|
||||
@@ -692,11 +692,19 @@ export function useRoadtripRoutes(
|
||||
* for both, so a choice being checked cannot fire into the gap a seam is keeping.
|
||||
*/
|
||||
const lastSpacedRequestAt = useRef(0)
|
||||
/** Waits until the gap since the last such request is kept, then claims the next slot. */
|
||||
const spacedRequest = useCallback(async (signal: AbortSignal): Promise<void> => {
|
||||
/**
|
||||
* Waits until the gap since the last such request is kept, then claims the next slot.
|
||||
* Hands back what gives the slot up again, for a request the cache answered.
|
||||
*/
|
||||
const spacedRequest = useCallback(async (signal: AbortSignal): Promise<() => void> => {
|
||||
const since = performance.now() - lastSpacedRequestAt.current
|
||||
if (since < REQUEST_SPACING_MS) await sleep(REQUEST_SPACING_MS - since, signal)
|
||||
if (!signal.aborted) lastSpacedRequestAt.current = performance.now()
|
||||
const before = lastSpacedRequestAt.current
|
||||
const claimed = performance.now()
|
||||
if (!signal.aborted) lastSpacedRequestAt.current = claimed
|
||||
return () => {
|
||||
if (lastSpacedRequestAt.current === claimed) lastSpacedRequestAt.current = before
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
@@ -727,7 +735,7 @@ export function useRoadtripRoutes(
|
||||
// shared routing hosts answered the tail with 429, and a refused seam
|
||||
// writes no state, so nothing changed to make the effect try again: the
|
||||
// map drew the trip in pieces and the totals came back short.
|
||||
await spacedRequest(controller.signal)
|
||||
const release = await spacedRequest(controller.signal)
|
||||
if (controller.signal.aborted) return
|
||||
try {
|
||||
// The via points on this seam, threaded in the same way the day runs thread
|
||||
@@ -735,6 +743,7 @@ export function useRoadtripRoutes(
|
||||
// shape: it is asked for on its own, so the points the traveller dropped on it
|
||||
// never reached the router and dragging one did visibly nothing.
|
||||
const shaping = viasOnLeg(seam.from, seam.to, viasByDay[seam.from.ownerDayId] ?? [])
|
||||
const startedAt = performance.now()
|
||||
const r = await calculateRouteWithLegs(
|
||||
[
|
||||
{ lat: seam.from.lat, lng: seam.from.lng },
|
||||
@@ -743,6 +752,10 @@ export function useRoadtripRoutes(
|
||||
],
|
||||
{ signal: controller.signal, profile: mode, tripId: tripId ?? null, dayId: seam.dayId, avoid },
|
||||
)
|
||||
// A seam this device routed before came back from its cache and went nowhere, so
|
||||
// its slot goes back before the store below re-runs this effect. Holding it made a
|
||||
// trip of connected days wait a second per join on every open (#2794).
|
||||
if (performance.now() - startedAt <= CACHE_HIT_MS) release()
|
||||
if (controller.signal.aborted) return
|
||||
// One leg per waypoint PAIR, so a shaped seam comes back in pieces and the rail
|
||||
// wants the whole drive: merged here, exactly as a day run folds its via legs
|
||||
|
||||
Reference in New Issue
Block a user