unrip/test/history-writer-static.test.mjs
philipp 2f455f0140
All checks were successful
deploy / deploy (push) Successful in 55s
Bound quote lifecycle rollup catch-up
Proof: Quote lifecycle retention now runs without blocking history-writer readiness, prevents concurrent maintenance passes, and bounds historical rollup catch-up before fail-closed pruning; regression tests cover the bounded stale-watermark path.
Assumptions: Forty-eight DB-backed rollup granularity windows per pass is sufficient to catch up historical backlog without returning the entire raw quote firehose in one query.
Still fake: Initial historical backlog may require multiple scheduled passes before pruning can begin; already-pruned non-success detail cannot be reconstructed.
2026-06-06 16:01:13 +02:00

45 lines
2.8 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, /quoteLifecycleRetentionMaintenanceIntervalMs\s*=\s*60 \* 1000/);
assert.match(source, /runQuoteLifecycleRetentionMaintenance/);
assert.match(source, /loadQuoteLifecycleRetentionSummary/);
assert.match(source, /maybeRunQuoteLifecycleRetentionMaintenance/);
assert.match(source, /quoteLifecycleRetentionMaintenanceInFlight/);
assert.match(source, /quoteLifecycleRetentionMaintenanceTimer\s*=\s*setInterval/);
assert.match(source, /quoteLifecycleRetentionStartupTimer\s*=\s*setTimeout/);
assert.match(source, /void maybeRunQuoteLifecycleRetentionMaintenance\(\{\s*force:\s*true\s*\}\)/);
assert.match(source, /clearTimeout\(quoteLifecycleRetentionStartupTimer\)/);
assert.match(source, /clearInterval\(quoteLifecycleRetentionMaintenanceTimer\)/);
assert.match(source, /retention_mode/);
assert.match(source, /storage_pressure/);
assert.doesNotMatch(source, /RetainRecentMs/);
assert.doesNotMatch(source, /PruneBatchSize/);
assert.doesNotMatch(source, /pruneRawNearIntentsQuoteHistory/);
assert.doesNotMatch(source, /pruneNonSuccessfulQuoteLifecycleHistory/);
});
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/);
});