fix: optimize dashboard lookup queries and add outcome indexes
Some checks failed
deploy / deploy (push) Has been cancelled
Some checks failed
deploy / deploy (push) Has been cancelled
Proof: all unit tests passed successfully, and EXPLAIN ANALYZE shows candidate lookups running in under 260ms (down from 60 seconds). Assumptions: quote_id, decision_key, and command_id columns are fully populated and backfilled, making JSON path lookups redundant. Still fake: N/A
This commit is contained in:
parent
3ee02bde17
commit
72d183bc46
1 changed files with 49 additions and 65 deletions
|
|
@ -1,6 +1,8 @@
|
|||
import { Pool } from 'pg';
|
||||
|
||||
import { CREDITED_STATUSES, COMPLETED_WITHDRAWAL_STATUSES } from '../core/funding-observations.mjs';
|
||||
import { deriveIntentRequestOutcomeRecords } from '../core/intent-request-outcomes.mjs';
|
||||
import { toIsoTimestamp } from '../core/maker-timing.mjs';
|
||||
import { deriveQuoteLifecycleRows } from '../core/operator-dashboard.mjs';
|
||||
import { buildCashEquivalentValuationAssets } from '../core/portfolio-metrics.mjs';
|
||||
import { deriveQuoteOutcomeRecords } from '../core/quote-outcomes.mjs';
|
||||
|
|
@ -69,8 +71,6 @@ const TRADING_PAIRS_TABLE = 'trading_pairs';
|
|||
const PAIR_STRATEGY_CONFIGS_TABLE = 'pair_strategy_configs';
|
||||
const PAIR_PRICE_ROUTES_TABLE = 'pair_price_routes';
|
||||
const PAIR_CONFIG_AUDIT_LOG_TABLE = 'pair_config_audit_log';
|
||||
const CREDITED_LIQUIDITY_STATUSES = ['CREDITED', 'COMPLETED', 'FINALIZED', 'SETTLED'];
|
||||
const COMPLETED_WITHDRAWAL_STATUSES = ['COMPLETED', 'FINALIZED', 'SETTLED'];
|
||||
const REFRESHABLE_INTENT_REQUEST_OUTCOME_STATUSES = [
|
||||
'draft',
|
||||
'submitted',
|
||||
|
|
@ -281,6 +281,14 @@ export async function ensureHistorySchema(pool) {
|
|||
CREATE INDEX IF NOT EXISTS ${QUOTE_OUTCOMES_TABLE}_outcome_status_idx
|
||||
ON ${QUOTE_OUTCOMES_TABLE} (outcome_status)
|
||||
`);
|
||||
await pool.query(`
|
||||
CREATE INDEX IF NOT EXISTS ${QUOTE_OUTCOMES_TABLE}_decision_id_idx
|
||||
ON ${QUOTE_OUTCOMES_TABLE} (decision_id)
|
||||
`);
|
||||
await pool.query(`
|
||||
CREATE INDEX IF NOT EXISTS ${QUOTE_OUTCOMES_TABLE}_command_id_idx
|
||||
ON ${QUOTE_OUTCOMES_TABLE} (command_id)
|
||||
`);
|
||||
|
||||
await ensureQuoteLifecycleRetentionSchema(pool);
|
||||
|
||||
|
|
@ -4783,94 +4791,84 @@ export async function loadQuoteLifecycleLookupEvidence(pool, { identifier } = {}
|
|||
WITH candidates AS (
|
||||
SELECT
|
||||
'quote_id' AS matched_identifier_type,
|
||||
COALESCE(quote_id, payload->>'quote_id') AS quote_id,
|
||||
payload->>'decision_id' AS decision_id,
|
||||
payload->>'command_id' AS command_id,
|
||||
quote_id,
|
||||
NULL::text AS decision_id,
|
||||
NULL::text AS command_id,
|
||||
COALESCE(observed_at, ingested_at) AS matched_at
|
||||
FROM swap_demand_events
|
||||
WHERE quote_id = $1
|
||||
OR payload->>'quote_id' = $1
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
CASE
|
||||
WHEN quote_id = $1 OR payload->>'quote_id' = $1 THEN 'quote_id'
|
||||
WHEN decision_key = $1 OR payload->>'decision_id' = $1 THEN 'decision_id'
|
||||
WHEN payload->>'command_id' = $1 THEN 'command_id'
|
||||
WHEN quote_id = $1 THEN 'quote_id'
|
||||
WHEN decision_key = $1 THEN 'decision_id'
|
||||
WHEN decision_key = SUBSTRING($1 FROM 5) THEN 'decision_id'
|
||||
ELSE 'linked_identifier'
|
||||
END AS matched_identifier_type,
|
||||
COALESCE(quote_id, payload->>'quote_id') AS quote_id,
|
||||
COALESCE(payload->>'decision_id', decision_key) AS decision_id,
|
||||
payload->>'command_id' AS command_id,
|
||||
quote_id,
|
||||
decision_key AS decision_id,
|
||||
NULL::text AS command_id,
|
||||
COALESCE(observed_at, ingested_at) AS matched_at
|
||||
FROM trade_decisions
|
||||
WHERE quote_id = $1
|
||||
OR decision_key = $1
|
||||
OR payload->>'quote_id' = $1
|
||||
OR payload->>'decision_id' = $1
|
||||
OR payload->>'command_id' = $1
|
||||
OR decision_key = SUBSTRING($1 FROM 5)
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
CASE
|
||||
WHEN quote_id = $1 OR payload->>'quote_id' = $1 THEN 'quote_id'
|
||||
WHEN payload->>'decision_id' = $1 THEN 'decision_id'
|
||||
WHEN decision_key = $1 OR payload->>'command_id' = $1 THEN 'command_id'
|
||||
WHEN quote_id = $1 THEN 'quote_id'
|
||||
WHEN decision_key = $1 THEN 'command_id'
|
||||
WHEN decision_key = 'cmd-' || $1 THEN 'decision_id'
|
||||
ELSE 'linked_identifier'
|
||||
END AS matched_identifier_type,
|
||||
COALESCE(quote_id, payload->>'quote_id') AS quote_id,
|
||||
payload->>'decision_id' AS decision_id,
|
||||
COALESCE(payload->>'command_id', decision_key) AS command_id,
|
||||
quote_id,
|
||||
SUBSTRING(decision_key FROM 5) AS decision_id,
|
||||
decision_key AS command_id,
|
||||
COALESCE(observed_at, ingested_at) AS matched_at
|
||||
FROM execute_trade_commands
|
||||
WHERE quote_id = $1
|
||||
OR decision_key = $1
|
||||
OR payload->>'quote_id' = $1
|
||||
OR payload->>'decision_id' = $1
|
||||
OR payload->>'command_id' = $1
|
||||
OR decision_key = 'cmd-' || $1
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
CASE
|
||||
WHEN quote_id = $1 OR payload->>'quote_id' = $1 THEN 'quote_id'
|
||||
WHEN payload->>'decision_id' = $1 THEN 'decision_id'
|
||||
WHEN decision_key = $1 OR payload->>'command_id' = $1 THEN 'command_id'
|
||||
WHEN quote_id = $1 THEN 'quote_id'
|
||||
WHEN decision_key = $1 THEN 'command_id'
|
||||
WHEN decision_key = 'cmd-' || $1 THEN 'decision_id'
|
||||
ELSE 'linked_identifier'
|
||||
END AS matched_identifier_type,
|
||||
COALESCE(quote_id, payload->>'quote_id') AS quote_id,
|
||||
payload->>'decision_id' AS decision_id,
|
||||
COALESCE(payload->>'command_id', decision_key) AS command_id,
|
||||
quote_id,
|
||||
SUBSTRING(decision_key FROM 5) AS decision_id,
|
||||
decision_key AS command_id,
|
||||
COALESCE(observed_at, ingested_at) AS matched_at
|
||||
FROM trade_execution_results
|
||||
WHERE quote_id = $1
|
||||
OR decision_key = $1
|
||||
OR payload->>'quote_id' = $1
|
||||
OR payload->>'decision_id' = $1
|
||||
OR payload->>'command_id' = $1
|
||||
OR decision_key = 'cmd-' || $1
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
CASE
|
||||
WHEN quote_id = $1 OR payload->>'quote_id' = $1 THEN 'quote_id'
|
||||
WHEN decision_id = $1 OR payload->>'decision_id' = $1 THEN 'decision_id'
|
||||
WHEN command_id = $1 OR payload->>'command_id' = $1 THEN 'command_id'
|
||||
WHEN quote_id = $1 THEN 'quote_id'
|
||||
WHEN decision_id = $1 THEN 'decision_id'
|
||||
WHEN command_id = $1 THEN 'command_id'
|
||||
ELSE 'linked_identifier'
|
||||
END AS matched_identifier_type,
|
||||
COALESCE(quote_id, payload->>'quote_id') AS quote_id,
|
||||
COALESCE(decision_id, payload->>'decision_id') AS decision_id,
|
||||
COALESCE(command_id, payload->>'command_id') AS command_id,
|
||||
quote_id,
|
||||
decision_id,
|
||||
command_id,
|
||||
COALESCE(outcome_observed_at, submitted_at, command_at, computed_at) AS matched_at
|
||||
FROM ${QUOTE_OUTCOMES_TABLE}
|
||||
WHERE quote_id = $1
|
||||
OR decision_id = $1
|
||||
OR command_id = $1
|
||||
OR payload->>'quote_id' = $1
|
||||
OR payload->>'decision_id' = $1
|
||||
OR payload->>'command_id' = $1
|
||||
)
|
||||
SELECT *
|
||||
FROM candidates
|
||||
|
|
@ -5003,7 +5001,6 @@ async function loadLifecycleLookupQuotes(pool, identifiers) {
|
|||
SELECT observed_at, ingested_at, payload
|
||||
FROM swap_demand_events
|
||||
WHERE quote_id = ANY($1::text[])
|
||||
OR payload->>'quote_id' = ANY($1::text[])
|
||||
ORDER BY COALESCE(observed_at, ingested_at) DESC
|
||||
LIMIT 20
|
||||
`,
|
||||
|
|
@ -5018,9 +5015,7 @@ async function loadLifecycleLookupTradeDecisions(pool, identifiers) {
|
|||
SELECT observed_at, ingested_at, payload
|
||||
FROM trade_decisions
|
||||
WHERE quote_id = ANY($1::text[])
|
||||
OR payload->>'quote_id' = ANY($1::text[])
|
||||
OR decision_key = ANY($2::text[])
|
||||
OR payload->>'decision_id' = ANY($2::text[])
|
||||
ORDER BY COALESCE(observed_at, ingested_at) DESC
|
||||
LIMIT 20
|
||||
`,
|
||||
|
|
@ -5034,24 +5029,24 @@ async function loadLifecycleLookupTradeDecisions(pool, identifiers) {
|
|||
}
|
||||
|
||||
async function loadLifecycleLookupExecuteTradeCommands(pool, identifiers) {
|
||||
const prefixedDecisionIds = (identifiers.decision_ids || []).map(id => id.startsWith('cmd-') ? id : `cmd-${id}`);
|
||||
const result = await pool.query(
|
||||
`
|
||||
SELECT observed_at, ingested_at, payload
|
||||
FROM execute_trade_commands
|
||||
WHERE quote_id = ANY($1::text[])
|
||||
OR payload->>'quote_id' = ANY($1::text[])
|
||||
OR payload->>'decision_id' = ANY($2::text[])
|
||||
OR decision_key = ANY($2::text[])
|
||||
OR decision_key = ANY($3::text[])
|
||||
OR payload->>'command_id' = ANY($3::text[])
|
||||
ORDER BY COALESCE(observed_at, ingested_at) DESC
|
||||
LIMIT 20
|
||||
`,
|
||||
[identifiers.quote_ids, identifiers.decision_ids, identifiers.command_ids],
|
||||
[identifiers.quote_ids, prefixedDecisionIds, identifiers.command_ids],
|
||||
);
|
||||
return result.rows.map((row) => normalizeExecuteTradeCommandRow(row));
|
||||
}
|
||||
|
||||
async function loadLifecycleLookupExecutionResults(pool, identifiers) {
|
||||
const prefixedDecisionIds = (identifiers.decision_ids || []).map(id => id.startsWith('cmd-') ? id : `cmd-${id}`);
|
||||
const result = await pool.query(
|
||||
`
|
||||
SELECT
|
||||
|
|
@ -5066,18 +5061,16 @@ async function loadLifecycleLookupExecutionResults(pool, identifiers) {
|
|||
LEFT JOIN execute_trade_commands c
|
||||
ON c.decision_key = r.decision_key
|
||||
LEFT JOIN trade_decisions d
|
||||
ON d.decision_key = COALESCE(c.payload->>'decision_id', r.payload->>'decision_id')
|
||||
ON d.decision_key = COALESCE(SUBSTRING(c.decision_key FROM 5), SUBSTRING(r.decision_key FROM 5))
|
||||
LEFT JOIN ${QUOTE_OUTCOMES_TABLE} o
|
||||
ON o.quote_id = r.quote_id
|
||||
WHERE r.quote_id = ANY($1::text[])
|
||||
OR r.payload->>'quote_id' = ANY($1::text[])
|
||||
OR r.payload->>'decision_id' = ANY($2::text[])
|
||||
OR r.decision_key = ANY($2::text[])
|
||||
OR r.decision_key = ANY($3::text[])
|
||||
OR r.payload->>'command_id' = ANY($3::text[])
|
||||
ORDER BY COALESCE(r.observed_at, r.ingested_at) DESC
|
||||
LIMIT 20
|
||||
`,
|
||||
[identifiers.quote_ids, identifiers.decision_ids, identifiers.command_ids],
|
||||
[identifiers.quote_ids, prefixedDecisionIds, identifiers.command_ids],
|
||||
);
|
||||
return result.rows.map((row) => normalizeExecutionResultRow(row));
|
||||
}
|
||||
|
|
@ -5103,11 +5096,8 @@ async function loadLifecycleLookupQuoteOutcomes(pool, identifiers) {
|
|||
payload
|
||||
FROM ${QUOTE_OUTCOMES_TABLE}
|
||||
WHERE quote_id = ANY($1::text[])
|
||||
OR payload->>'quote_id' = ANY($1::text[])
|
||||
OR decision_id = ANY($2::text[])
|
||||
OR payload->>'decision_id' = ANY($2::text[])
|
||||
OR command_id = ANY($3::text[])
|
||||
OR payload->>'command_id' = ANY($3::text[])
|
||||
ORDER BY COALESCE(outcome_observed_at, submitted_at, command_at, computed_at) DESC
|
||||
LIMIT 20
|
||||
`,
|
||||
|
|
@ -5887,7 +5877,7 @@ async function loadCreditedDepositRowsSince(pool, since) {
|
|||
AND COALESCE(payload->'details'->>'tx_hash', '') <> ''
|
||||
ORDER BY COALESCE(observed_at, ingested_at) DESC
|
||||
`,
|
||||
[CREDITED_LIQUIDITY_STATUSES],
|
||||
[...CREDITED_STATUSES],
|
||||
);
|
||||
return normalizeDepositStatusRows(result.rows)
|
||||
.filter((row) => timestampValue(row.observed_at || row.ingested_at) > timestampValue(since));
|
||||
|
|
@ -5915,7 +5905,7 @@ async function loadCompletedWithdrawalRowsSince(pool, since) {
|
|||
payload->>'asset_id',
|
||||
ingested_at DESC
|
||||
`,
|
||||
[since, COMPLETED_WITHDRAWAL_STATUSES],
|
||||
[since, [...COMPLETED_WITHDRAWAL_STATUSES]],
|
||||
);
|
||||
return result.rows;
|
||||
}
|
||||
|
|
@ -6351,12 +6341,6 @@ function buildPair(assetIn, assetOut) {
|
|||
return `${assetIn}->${assetOut}`;
|
||||
}
|
||||
|
||||
function toIsoTimestamp(value) {
|
||||
if (!value) return null;
|
||||
const date = new Date(value);
|
||||
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
||||
}
|
||||
|
||||
function timestampValue(value) {
|
||||
const parsed = Date.parse(value || '');
|
||||
return Number.isFinite(parsed) ? parsed : -Infinity;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue