All checks were successful
deploy / deploy (push) Successful in 1m12s
Proof: Emergency cleanup showed normalized quote lifecycle tables, not raw quotes alone, filled the Postgres PVC. History-writer now prunes old non-success quote rows across raw quotes, normalized demand, decisions, commands, executor results, and outcome attributions while preserving completed quote settlement rows and a 30 minute live window. Targeted retention tests, full npm test, and operator dashboard bundle build pass. Assumptions: completed quote outcomes and attributed successful quote ids are the durable settlement evidence to retain; short recent live rows may be retained temporarily so in-flight attribution is not erased mid-cycle. Still fake: venue-native terminal fill ids and fee-complete realized PnL remain unavailable; historical non-success quote analytics pruned during emergency recovery are intentionally no longer readable.
43 lines
2.7 KiB
JavaScript
43 lines
2.7 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { readFileSync } from 'node:fs';
|
|
|
|
const source = readFileSync(new URL('../src/apps/history-writer.mjs', import.meta.url), 'utf8');
|
|
|
|
test('history writer replays durable topics but joins the raw quote firehose live', () => {
|
|
assert.match(source, /durableHistoryConsumerCount\s*=\s*3/);
|
|
assert.match(source, /durableConsumers\.push\(await createConsumer/);
|
|
assert.match(source, /liveEvidenceConsumerCount\s*=\s*2/);
|
|
assert.match(source, /groupId:\s*`\$\{config\.kafkaConsumerGroupHistory\}-live`/);
|
|
assert.match(source, /groupId:\s*`\$\{config\.kafkaConsumerGroupHistory\}-raw`/);
|
|
assert.match(source, /liveEvidenceTopics\s*=\s*\[[\s\S]+config\.kafkaTopicNormSwapDemand[\s\S]+config\.kafkaTopicDecisionTradeDecision/);
|
|
assert.match(source, /current quote\/decision truth visible/);
|
|
assert.match(source, /rawQuoteConsumer\.subscribe\(\{[\s\S]+fromBeginning:\s*false/);
|
|
assert.match(source, /historyConsumer\.subscribe\(\{[\s\S]+fromBeginning:\s*true/);
|
|
assert.match(source, /liveEvidenceTopics[\s\S]+fromBeginning:\s*false/);
|
|
assert.match(source, /Raw quote volume is a live firehose/);
|
|
assert.match(source, /runHistoryConsumer\(historyConsumer\)/);
|
|
assert.match(source, /runHistoryConsumer\(rawQuoteConsumer\)/);
|
|
assert.match(source, /eachBatch/);
|
|
assert.match(source, /insertHistoryEvents/);
|
|
assert.match(source, /rawQuoteHistoryPruneIntervalMs\s*=\s*60 \* 1000/);
|
|
assert.match(source, /rawQuoteHistoryRetainRecentMs\s*=\s*30 \* 60 \* 1000/);
|
|
assert.match(source, /rawQuoteHistoryPruneBatchSize\s*=\s*500_000/);
|
|
assert.match(source, /rawQuoteHistoryPruneMaxBatches\s*=\s*20/);
|
|
assert.match(source, /quoteLifecycleHistoryPruneIntervalMs\s*=\s*60 \* 1000/);
|
|
assert.match(source, /quoteLifecycleHistoryRetainRecentMs\s*=\s*30 \* 60 \* 1000/);
|
|
assert.match(source, /quoteLifecycleHistoryPruneBatchSize\s*=\s*100_000/);
|
|
assert.match(source, /quoteLifecycleHistoryPruneMaxBatches\s*=\s*10/);
|
|
assert.match(source, /pruneRawNearIntentsQuoteHistory/);
|
|
assert.match(source, /pruneNonSuccessfulQuoteLifecycleHistory/);
|
|
assert.match(source, /maxBatches:\s*rawQuoteHistoryPruneMaxBatches/);
|
|
assert.match(source, /maxBatches:\s*quoteLifecycleHistoryPruneMaxBatches/);
|
|
assert.match(source, /batch\.topic === config\.kafkaTopicRawNearIntentsQuote/);
|
|
assert.match(source, /maybePruneQuoteLifecycleHistory/);
|
|
});
|
|
|
|
test('history writer passes tracked assets into portfolio valuation', () => {
|
|
assert.match(source, /trackedAssets:\s*tradingConfig\.trackedAssets/);
|
|
assert.match(source, /valuationAssets:\s*inputs\.valuationAssets \|\| \[\]/);
|
|
assert.match(source, /inputs\.valuationAssets[\s\S]+asset\.priceId/);
|
|
});
|