Gate live feed staleness and isolate Next dev artifacts
- delay stale status for paused live feeds before surfacing disconnects - keep `next dev` output separate from production build artifacts - add coverage for the new live-feed stale threshold
This commit is contained in:
parent
4368d6db4c
commit
1161e37ef5
8 changed files with 130 additions and 6 deletions
|
|
@ -185,6 +185,11 @@ describe("live tape pausable helpers", () => {
|
|||
expect(getLiveFeedStatus("disconnected", 1000, 500, 1601)).toBe("disconnected");
|
||||
});
|
||||
|
||||
it("waits for an additional behind-delay before surfacing stale", () => {
|
||||
expect(getLiveFeedStatus("connected", 1000, 500, 2000, 15_000)).toBe("connected");
|
||||
expect(getLiveFeedStatus("connected", 1000, 500, 16_501, 15_000)).toBe("stale");
|
||||
});
|
||||
|
||||
it("keeps visible history even when live status is stale", () => {
|
||||
const projected = projectPausableTapeState([makeItem("stale", 7, 1000)], "stale", 2000);
|
||||
expect(projected.items.map((item) => item.trace_id)).toEqual(["stale"]);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ const LIVE_HOT_WINDOW_OPTIONS = parseBoundedInt(
|
|||
const LIVE_OPTIONS_STALE_MS = 15_000;
|
||||
const LIVE_NBBO_STALE_MS = 15_000;
|
||||
const LIVE_EQUITIES_STALE_MS = 15_000;
|
||||
const LIVE_FEED_BEHIND_DELAY_MS = 15_000;
|
||||
const LIVE_EQUITIES_SILENT_WARNING_MS = parseBoundedInt(
|
||||
process.env.NEXT_PUBLIC_LIVE_EQUITIES_SILENT_WARNING_MS,
|
||||
25_000,
|
||||
|
|
@ -491,7 +492,8 @@ export const getLiveFeedStatus = (
|
|||
sourceStatus: WsStatus,
|
||||
freshestTs: number | null,
|
||||
thresholdMs: number,
|
||||
now = Date.now()
|
||||
now = Date.now(),
|
||||
behindDelayMs = 0
|
||||
): WsStatus => {
|
||||
if (sourceStatus !== "connected") {
|
||||
return sourceStatus;
|
||||
|
|
@ -499,7 +501,14 @@ export const getLiveFeedStatus = (
|
|||
if (freshestTs === null) {
|
||||
return "connected";
|
||||
}
|
||||
return isFreshLiveItem(freshestTs, thresholdMs, now) ? "connected" : "stale";
|
||||
|
||||
const ageMs = now - freshestTs;
|
||||
if (ageMs <= thresholdMs) {
|
||||
return "connected";
|
||||
}
|
||||
|
||||
const behindMs = ageMs - thresholdMs;
|
||||
return behindMs > behindDelayMs ? "stale" : "connected";
|
||||
};
|
||||
|
||||
type TapeState<T> = {
|
||||
|
|
@ -945,8 +954,6 @@ export const countActiveFlowFilterGroups = (filters: OptionFlowFilters): number
|
|||
return count;
|
||||
};
|
||||
|
||||
const isFreshLiveItem = (ts: number, thresholdMs: number, now = Date.now()): boolean => now - ts <= thresholdMs;
|
||||
|
||||
export const toggleFilterValue = <T extends string>(
|
||||
values: T[] | undefined,
|
||||
value: T,
|
||||
|
|
@ -1995,7 +2002,13 @@ const usePausableTapeView = <T extends SortableItem & { seq: number }>(
|
|||
}, [config.sourceItems, getItemTs]);
|
||||
|
||||
const status = config.enabled
|
||||
? getLiveFeedStatus(config.sourceStatus, freshestTs, config.freshnessMs, clock)
|
||||
? getLiveFeedStatus(
|
||||
config.sourceStatus,
|
||||
freshestTs,
|
||||
config.freshnessMs,
|
||||
clock,
|
||||
LIVE_FEED_BEHIND_DELAY_MS
|
||||
)
|
||||
: "disconnected";
|
||||
const projected = projectPausableTapeState(data.visible, status, config.lastUpdate);
|
||||
|
||||
|
|
|
|||
16
apps/web/next.config.mjs
Normal file
16
apps/web/next.config.mjs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
import { PHASE_DEVELOPMENT_SERVER } from "next/constants.js";
|
||||
|
||||
/**
|
||||
* Keep dev and production build artifacts separate to avoid chunk/runtime
|
||||
* mismatches when `next dev` and `next build` are run in overlapping sessions.
|
||||
*
|
||||
* @param {string} phase
|
||||
* @returns {import("next").NextConfig}
|
||||
*/
|
||||
export default function nextConfig(phase) {
|
||||
const isDev = phase === PHASE_DEVELOPMENT_SERVER;
|
||||
|
||||
return {
|
||||
distDir: isDev ? ".next-dev" : ".next"
|
||||
};
|
||||
}
|
||||
|
|
@ -1,9 +1,17 @@
|
|||
import { rm } from "node:fs/promises";
|
||||
|
||||
const run = async () => {
|
||||
const port = 3000;
|
||||
const distDir = ".next-dev";
|
||||
console.log(`[web] starting Next.js dev server on port ${port}`);
|
||||
|
||||
const path = Bun.env.PATH ?? "";
|
||||
const cwd = `${import.meta.dir}/..`;
|
||||
const distPath = `${cwd}/${distDir}`;
|
||||
|
||||
// Clear potentially stale dev artifacts from interrupted prior runs.
|
||||
await rm(distPath, { recursive: true, force: true });
|
||||
console.log(`[web] cleared stale Next.js dev artifacts at ${distDir}`);
|
||||
|
||||
const child = Bun.spawn(["next", "dev", "-p", String(port)], {
|
||||
cwd,
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@
|
|||
"next-env.d.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx",
|
||||
".next/types/**/*.ts"
|
||||
".next/types/**/*.ts",
|
||||
".next-dev/types/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue