@@ -4,8 +4,9 @@ import type {
44 ExecuteStatementRequest ,
55 StatementResult ,
66 StatementState ,
7+ QueryMetrics ,
78} from '../types.js'
8- import { postStatement , getStatement , cancelStatement } from '../databricks-api.js'
9+ import { postStatement , getStatement , cancelStatement , getQueryMetrics } from '../databricks-api.js'
910import { extractWarehouseId , throwIfAborted , delay } from '../util.js'
1011import {
1112 DatabricksSqlError ,
@@ -19,8 +20,21 @@ const TERMINAL_STATES = new Set<StatementState>([
1920 'CANCELED' ,
2021 'CLOSED' ,
2122] )
22- const POLL_INTERVAL_MS = 500
23- const MAX_POLL_INTERVAL_MS = 5000
23+ const POLL_INTERVAL_MS = 5000
24+
25+ async function fetchMetrics (
26+ auth : AuthInfo ,
27+ statementId : string ,
28+ signal ?: AbortSignal
29+ ) : Promise < QueryMetrics | undefined > {
30+ try {
31+ const queryInfo = await getQueryMetrics ( auth , statementId , signal )
32+ return queryInfo . metrics
33+ } catch {
34+ // Ignore metrics fetch errors - non-critical
35+ return undefined
36+ }
37+ }
2438
2539/**
2640 * Execute SQL statement and poll until completion
@@ -31,13 +45,17 @@ export async function executeStatement(
3145 options : ExecuteStatementOptions = { }
3246) : Promise < StatementResult > {
3347 const warehouseId = options . warehouse_id ?? extractWarehouseId ( auth . httpPath )
34- const { signal, onProgress } = options
48+ const { signal, onProgress, enableMetrics } = options
3549
3650 // Check if already aborted
3751 throwIfAborted ( signal , 'executeStatement' )
3852
53+ // Helper to call onProgress with optional metrics
54+ const emitProgress = onProgress
55+ ? async ( statementId : string ) => onProgress ( result . status , enableMetrics ? await fetchMetrics ( auth , statementId , signal ) : undefined )
56+ : undefined
57+
3958 // 1. Build request (filter out undefined values)
40- // Keep payload small and aligned with the REST API contract.
4159 const request = Object . fromEntries (
4260 Object . entries ( {
4361 warehouse_id : warehouseId ,
@@ -58,31 +76,19 @@ export async function executeStatement(
5876 let result = await postStatement ( auth , request , signal )
5977
6078 // 3. Poll until terminal state
61- let pollInterval = POLL_INTERVAL_MS
62-
6379 while ( ! TERMINAL_STATES . has ( result . status . state ) ) {
64- // Check abort signal
6580 if ( signal ?. aborted ) {
66- // Try to cancel on server
67- await cancelStatement ( auth , result . statement_id ) . catch ( ( ) => {
68- // Ignore cancel errors
69- } )
81+ await cancelStatement ( auth , result . statement_id ) . catch ( ( ) => { } )
7082 throw new AbortError ( 'Aborted during polling' )
7183 }
7284
73- // Call progress callback
74- onProgress ?.( result . status )
75-
76- // Wait before next poll (exponential backoff)
77- await delay ( pollInterval , signal )
78- pollInterval = Math . min ( pollInterval * 1.5 , MAX_POLL_INTERVAL_MS )
79-
80- // Get current status
85+ await emitProgress ?.( result . statement_id )
86+ await delay ( POLL_INTERVAL_MS , signal )
8187 result = await getStatement ( auth , result . statement_id , signal )
8288 }
8389
8490 // 4. Final progress callback
85- onProgress ?.( result . status )
91+ await emitProgress ?.( result . statement_id )
8692
8793 // 5. Handle terminal states
8894 if ( result . status . state === 'SUCCEEDED' )
0 commit comments