import test from 'node:test'; import assert from 'node:assert/strict'; import { loadQuoteLifecycleStatistics, refreshQuoteLifecycleStatistics, } from '../src/lib/postgres.mjs'; test('postgres quote lifecycle statistics refresh idempotently upserts state buckets by original quote window', async () => { const upserts = []; const subjects = new Map(); let includeFailure = false; const pool = { async query(sql, params = []) { if (sql.includes('FROM swap_demand_events') && sql.includes('ORDER BY COALESCE')) { return { rows: [{ observed_at: '2026-06-12T17:31:01.000Z', ingested_at: '2026-06-12T17:31:01.000Z', payload: { quote_id: 'quote-stat', pair: 'btc->eure', asset_in: 'btc', asset_out: 'eure', amount_in: '1', amount_out: '2', }, }], }; } if (sql.includes('FROM trade_decisions') && sql.includes('ORDER BY COALESCE')) { return { rows: [{ observed_at: '2026-06-12T17:31:02.000Z', ingested_at: '2026-06-12T17:31:02.000Z', payload: { quote_id: 'quote-stat', decision_id: 'decision-stat', pair: 'btc->eure', decision: 'approved', decision_reason: 'strategy_approved', }, }], }; } if (sql.includes('FROM execute_trade_commands') && sql.includes('ORDER BY COALESCE')) { return { rows: [{ observed_at: '2026-06-12T17:31:03.000Z', ingested_at: '2026-06-12T17:31:03.000Z', payload: { quote_id: 'quote-stat', decision_id: 'decision-stat', command_id: 'cmd-stat', pair: 'btc->eure', }, }], }; } if (sql.includes('FROM trade_execution_results r')) { return { rows: includeFailure ? [{ result_observed_at: '2026-06-12T17:36:10.000Z', result_ingested_at: '2026-06-12T17:36:10.000Z', result_payload: { quote_id: 'quote-stat', decision_id: 'decision-stat', command_id: 'cmd-stat', status: 'failed', result_code: 'submission_failed', failure_category: 'quote_not_found_or_finished', }, command_ingested_at: '2026-06-12T17:31:03.000Z', command_payload: { quote_id: 'quote-stat', decision_id: 'decision-stat', command_id: 'cmd-stat', }, decision_payload: { quote_id: 'quote-stat', decision_id: 'decision-stat', decision: 'approved', }, outcome_payload: null, }] : [], }; } if (sql.includes('FROM quote_outcome_attributions') && sql.includes('ORDER BY COALESCE')) { return { rows: [] }; } if (sql.includes('INSERT INTO quote_lifecycle_stat_subjects')) { const existing = subjects.get(params[0]); subjects.set(params[0], { quote_id: params[0], first_activity_at: existing?.first_activity_at || params[1], latest_stage_at: params[2] || existing?.latest_stage_at || null, bucket: params[3], lifecycle_state: params[4], reason_code: params[5], updated_at: params[6], payload: JSON.parse(params[7]), }); return { rows: [], rowCount: 1 }; } if (sql.includes('FROM quote_lifecycle_stat_subjects')) { return { rows: [...subjects.values()] }; } if (sql.includes('INSERT INTO quote_lifecycle_statistics')) { upserts.push({ sql, params }); return { rows: [], rowCount: 1 }; } throw new Error(`unexpected query: ${sql}`); }, }; await refreshQuoteLifecycleStatistics(pool, { now: '2026-06-12T17:32:00.000Z', }); includeFailure = true; await refreshQuoteLifecycleStatistics(pool, { now: '2026-06-12T17:37:00.000Z', }); const fiveMinuteUpserts = upserts.filter((query) => ( query.params[1] === 'five_minute' && query.params[2] === '2026-06-12T17:30:00.000Z' )); assert.equal(fiveMinuteUpserts.length, 2); assert.equal(fiveMinuteUpserts.at(-1).params[4], 1); const latestBuckets = JSON.parse(fiveMinuteUpserts.at(-1).params[7]); assert.equal(latestBuckets.submission_failed, 1); assert.equal(latestBuckets.awaiting_executor, 0); assert.equal( upserts.some((query) => ( query.params[1] === 'five_minute' && query.params[2] === '2026-06-12T17:35:00.000Z' )), false, ); }); test('postgres quote lifecycle statistics retain per-quote buckets after detail pruning', async () => { const subjects = new Map(); const allTimeUpserts = []; let sourceAvailable = true; const pool = { async query(sql, params = []) { if (sql.includes('FROM swap_demand_events') && sql.includes('ORDER BY COALESCE')) { return { rows: sourceAvailable ? [{ observed_at: '2026-06-12T14:11:01.000Z', ingested_at: '2026-06-12T14:11:01.000Z', payload: { quote_id: 'quote-completed', pair: 'btc->usdc', asset_in: 'btc', asset_out: 'usdc', amount_in: '1', amount_out: '2', }, }] : [], }; } if (sql.includes('FROM trade_decisions') && sql.includes('ORDER BY COALESCE')) { return { rows: sourceAvailable ? [{ observed_at: '2026-06-12T14:11:02.000Z', ingested_at: '2026-06-12T14:11:02.000Z', payload: { quote_id: 'quote-completed', decision_id: 'decision-completed', pair: 'btc->usdc', decision: 'approved', decision_reason: 'strategy_approved', }, }] : [], }; } if (sql.includes('FROM execute_trade_commands') && sql.includes('ORDER BY COALESCE')) { return { rows: sourceAvailable ? [{ observed_at: '2026-06-12T14:11:03.000Z', ingested_at: '2026-06-12T14:11:03.000Z', payload: { quote_id: 'quote-completed', decision_id: 'decision-completed', command_id: 'cmd-completed', pair: 'btc->usdc', }, }] : [], }; } if (sql.includes('FROM trade_execution_results r')) { return { rows: sourceAvailable ? [{ result_observed_at: '2026-06-12T14:11:10.000Z', result_ingested_at: '2026-06-12T14:11:10.000Z', result_payload: { quote_id: 'quote-completed', decision_id: 'decision-completed', command_id: 'cmd-completed', status: 'submitted', result_code: 'quote_response_ok', outcome_status: 'completed', }, command_payload: { quote_id: 'quote-completed', decision_id: 'decision-completed', command_id: 'cmd-completed', }, decision_payload: { quote_id: 'quote-completed', decision_id: 'decision-completed', decision: 'approved', }, outcome_payload: null, }] : [], }; } if (sql.includes('FROM quote_outcome_attributions') && sql.includes('ORDER BY COALESCE')) { return { rows: [] }; } if (sql.includes('INSERT INTO quote_lifecycle_stat_subjects')) { const existing = subjects.get(params[0]); subjects.set(params[0], { quote_id: params[0], first_activity_at: existing?.first_activity_at || params[1], latest_stage_at: params[2] || existing?.latest_stage_at || null, bucket: params[3], lifecycle_state: params[4], reason_code: params[5], updated_at: params[6], payload: JSON.parse(params[7]), }); return { rows: [], rowCount: 1 }; } if (sql.includes('FROM quote_lifecycle_stat_subjects')) { return { rows: [...subjects.values()] }; } if (sql.includes('INSERT INTO quote_lifecycle_statistics')) { if (params[1] === 'all_time') allTimeUpserts.push({ params }); return { rows: [], rowCount: 1 }; } throw new Error(`unexpected query: ${sql}`); }, }; await refreshQuoteLifecycleStatistics(pool, { now: '2026-06-12T14:12:00.000Z', }); sourceAvailable = false; await refreshQuoteLifecycleStatistics(pool, { now: '2026-06-12T15:12:00.000Z', }); assert.equal(allTimeUpserts.length, 2); assert.equal(allTimeUpserts[0].params[4], 1); assert.equal(JSON.parse(allTimeUpserts[0].params[7]).success, 1); assert.equal(allTimeUpserts[1].params[4], 1); assert.equal(JSON.parse(allTimeUpserts[1].params[7]).success, 1); }); test('postgres quote lifecycle statistics loader returns all-time and clamped grain rows', async () => { const pool = { async query(sql, params = []) { assert.match(sql, /FROM quote_lifecycle_statistics/); assert.deepEqual(params, [['all_time', 'five_minute'], 2]); return { rows: [{ stat_id: 'quote-lifecycle-stat:all_time:all', grain: 'all_time', window_start: null, window_end: null, quote_count: 3, missing_identifier_count: 1, missing_timestamp_count: 0, bucket_counts: { success: 1, submission_failed: 2 }, computed_at: '2026-06-12T17:40:00.000Z', }], }; }, }; const rows = await loadQuoteLifecycleStatistics(pool, { grains: ['all_time', 'five_minute'], limit: 2, }); assert.equal(rows.length, 1); assert.equal(rows[0].quote_count, 3); assert.equal(rows[0].bucket_counts.success, 1); assert.equal(rows[0].bucket_counts.submitted_no_reply, 0); });