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 = []; 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_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 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); });