|
24 | 24 | BackendType, |
25 | 25 | ExecuteResponse, |
26 | 26 | ) |
27 | | -from databricks.sql.exc import ServerOperationError |
| 27 | +from databricks.sql.exc import DatabaseError, ServerOperationError |
28 | 28 | from databricks.sql.backend.sea.utils.http_client import SeaHttpClient |
29 | 29 | from databricks.sql.types import SSLOptions |
30 | 30 |
|
@@ -85,9 +85,6 @@ class SeaDatabricksClient(DatabricksClient): |
85 | 85 | STATEMENT_PATH_WITH_ID = STATEMENT_PATH + "/{}" |
86 | 86 | CANCEL_STATEMENT_PATH_WITH_ID = STATEMENT_PATH + "/{}/cancel" |
87 | 87 |
|
88 | | - # SEA API constants |
89 | | - POLLING_INTERVAL_SECONDS = 0.5 |
90 | | - |
91 | 88 | def __init__( |
92 | 89 | self, |
93 | 90 | server_hostname: str, |
@@ -356,6 +353,41 @@ def _results_message_to_execute_response( |
356 | 353 |
|
357 | 354 | return execute_response |
358 | 355 |
|
| 356 | + def _check_command_not_in_failed_or_closed_state( |
| 357 | + self, state: CommandState, command_id: CommandId |
| 358 | + ) -> None: |
| 359 | + if state == CommandState.CLOSED: |
| 360 | + raise DatabaseError( |
| 361 | + "Command {} unexpectedly closed server side".format(command_id), |
| 362 | + { |
| 363 | + "operation-id": command_id, |
| 364 | + }, |
| 365 | + ) |
| 366 | + if state == CommandState.FAILED: |
| 367 | + raise ServerOperationError( |
| 368 | + "Command {} failed".format(command_id), |
| 369 | + { |
| 370 | + "operation-id": command_id, |
| 371 | + }, |
| 372 | + ) |
| 373 | + |
| 374 | + def _wait_until_command_done( |
| 375 | + self, response: ExecuteStatementResponse |
| 376 | + ) -> CommandState: |
| 377 | + """ |
| 378 | + Wait until a command is done. |
| 379 | + """ |
| 380 | + |
| 381 | + state = response.status.state |
| 382 | + command_id = CommandId.from_sea_statement_id(response.statement_id) |
| 383 | + |
| 384 | + while state in [CommandState.PENDING, CommandState.RUNNING]: |
| 385 | + state = self.get_query_state(command_id) |
| 386 | + |
| 387 | + self._check_command_not_in_failed_or_closed_state(state, command_id) |
| 388 | + |
| 389 | + return state |
| 390 | + |
359 | 391 | def execute_command( |
360 | 392 | self, |
361 | 393 | operation: str, |
@@ -453,24 +485,7 @@ def execute_command( |
453 | 485 | if async_op: |
454 | 486 | return None |
455 | 487 |
|
456 | | - # For synchronous operation, wait for the statement to complete |
457 | | - status = response.status |
458 | | - state = status.state |
459 | | - |
460 | | - # Keep polling until we reach a terminal state |
461 | | - while state in [CommandState.PENDING, CommandState.RUNNING]: |
462 | | - time.sleep(self.POLLING_INTERVAL_SECONDS) |
463 | | - state = self.get_query_state(command_id) |
464 | | - |
465 | | - if state != CommandState.SUCCEEDED: |
466 | | - raise ServerOperationError( |
467 | | - f"Statement execution did not succeed: {status.error.message if status.error else 'Unknown error'}", |
468 | | - { |
469 | | - "operation-id": command_id.to_sea_statement_id(), |
470 | | - "diagnostic-info": None, |
471 | | - }, |
472 | | - ) |
473 | | - |
| 488 | + self._wait_until_command_done(response) |
474 | 489 | return self.get_execution_result(command_id, cursor) |
475 | 490 |
|
476 | 491 | def cancel_command(self, command_id: CommandId) -> None: |
|
0 commit comments