Restore scoped live history retention
This commit is contained in:
parent
1d3865c8fc
commit
d81b4c0cfb
2 changed files with 62 additions and 11 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
NAV_ITEMS,
|
NAV_ITEMS,
|
||||||
|
appendHistoryTail,
|
||||||
buildDefaultFlowFilters,
|
buildDefaultFlowFilters,
|
||||||
classifierToneForFamily,
|
classifierToneForFamily,
|
||||||
deriveAlertDirection,
|
deriveAlertDirection,
|
||||||
|
|
@ -9,6 +10,7 @@ import {
|
||||||
formatOptionContractLabel,
|
formatOptionContractLabel,
|
||||||
flushPausableTapeData,
|
flushPausableTapeData,
|
||||||
getAlertWindowAnchorTs,
|
getAlertWindowAnchorTs,
|
||||||
|
getLiveHistoryRetentionCap,
|
||||||
getOptionTableSnapshot,
|
getOptionTableSnapshot,
|
||||||
getLiveFeedStatus,
|
getLiveFeedStatus,
|
||||||
getLiveManifest,
|
getLiveManifest,
|
||||||
|
|
@ -240,6 +242,53 @@ describe("live tape pausable helpers", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("live tape history helpers", () => {
|
||||||
|
it("appends older scoped rows behind the hot live head", () => {
|
||||||
|
const liveHead = Array.from({ length: 100 }, (_, idx) =>
|
||||||
|
makeItem(`hot-${idx}`, 200 - idx, 2_000 - idx)
|
||||||
|
);
|
||||||
|
const older = [makeItem("older-1", 99, 999), makeItem("older-2", 98, 998)];
|
||||||
|
|
||||||
|
const next = appendHistoryTail([], older, liveHead, 5000);
|
||||||
|
|
||||||
|
expect(next.map((item) => item.trace_id)).toEqual(["older-1", "older-2"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("skips duplicates already present in the live head", () => {
|
||||||
|
const liveHead = [makeItem("latest", 3, 300), makeItem("duplicate", 2, 200)];
|
||||||
|
const older = [makeItem("duplicate", 2, 200), makeItem("older", 1, 100)];
|
||||||
|
|
||||||
|
const next = appendHistoryTail([], older, liveHead, 5000);
|
||||||
|
|
||||||
|
expect(next.map((item) => item.trace_id)).toEqual(["older"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("trims the history tail to the soft cap", () => {
|
||||||
|
const current = [makeItem("existing", 4, 400)];
|
||||||
|
const older = [makeItem("older-1", 3, 300), makeItem("older-2", 2, 200)];
|
||||||
|
|
||||||
|
const next = appendHistoryTail(current, older, [], 2);
|
||||||
|
|
||||||
|
expect(next.map((item) => item.trace_id)).toEqual(["existing", "older-1"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps scoped option and equity history on the normal retention cap", () => {
|
||||||
|
expect(
|
||||||
|
getLiveHistoryRetentionCap({
|
||||||
|
channel: "options",
|
||||||
|
underlying_ids: ["AAPL"],
|
||||||
|
option_contract_id: "AAPL-2025-01-17-200-C"
|
||||||
|
} as any)
|
||||||
|
).toBeGreaterThan(0);
|
||||||
|
expect(
|
||||||
|
getLiveHistoryRetentionCap({
|
||||||
|
channel: "equities",
|
||||||
|
underlying_ids: ["AAPL"]
|
||||||
|
} as any)
|
||||||
|
).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("options display formatters", () => {
|
describe("options display formatters", () => {
|
||||||
it("formats dashed option contracts as ticker strike expiry", () => {
|
it("formats dashed option contracts as ticker strike expiry", () => {
|
||||||
expect(formatOptionContractLabel("SPY-2025-01-17-450-C")).toEqual({
|
expect(formatOptionContractLabel("SPY-2025-01-17-450-C")).toEqual({
|
||||||
|
|
|
||||||
|
|
@ -510,7 +510,7 @@ const EMPTY_PAUSABLE_TAPE = {
|
||||||
dropped: 0
|
dropped: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
const appendHistoryTail = <T extends SortableItem>(
|
export const appendHistoryTail = <T extends SortableItem>(
|
||||||
current: T[],
|
current: T[],
|
||||||
incoming: T[],
|
incoming: T[],
|
||||||
liveHead: T[],
|
liveHead: T[],
|
||||||
|
|
@ -541,6 +541,16 @@ const appendHistoryTail = <T extends SortableItem>(
|
||||||
return cap > 0 ? appended.slice(0, cap) : appended;
|
return cap > 0 ? appended.slice(0, cap) : appended;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getLiveHistoryRetentionCap = (subscription: LiveSubscription): number => {
|
||||||
|
switch (subscription.channel) {
|
||||||
|
case "options":
|
||||||
|
case "equities":
|
||||||
|
return LIVE_HISTORY_SOFT_CAP;
|
||||||
|
default:
|
||||||
|
return LIVE_HISTORY_SOFT_CAP;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getLiveFeedStatus = (
|
export const getLiveFeedStatus = (
|
||||||
sourceStatus: WsStatus,
|
sourceStatus: WsStatus,
|
||||||
freshestTs: number | null,
|
freshestTs: number | null,
|
||||||
|
|
@ -2924,21 +2934,13 @@ const useLiveSession = (
|
||||||
|
|
||||||
switch (subscription.channel) {
|
switch (subscription.channel) {
|
||||||
case "options":
|
case "options":
|
||||||
mergeOlder(
|
mergeOlder(setOptionsHistory, options, getLiveHistoryRetentionCap(subscription));
|
||||||
setOptionsHistory,
|
|
||||||
options,
|
|
||||||
subscription.underlying_ids?.length || subscription.option_contract_id ? 0 : LIVE_HISTORY_SOFT_CAP
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "nbbo":
|
case "nbbo":
|
||||||
mergeOlder(setNbboHistory, nbbo);
|
mergeOlder(setNbboHistory, nbbo);
|
||||||
break;
|
break;
|
||||||
case "equities":
|
case "equities":
|
||||||
mergeOlder(
|
mergeOlder(setEquitiesHistory, equities, getLiveHistoryRetentionCap(subscription));
|
||||||
setEquitiesHistory,
|
|
||||||
equities,
|
|
||||||
subscription.underlying_ids?.length ? 0 : LIVE_HISTORY_SOFT_CAP
|
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
case "equity-quotes":
|
case "equity-quotes":
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue