Skip to content

Commit b4ad166

Browse files
ai: apply changes for #923 (1 review thread)
Addresses: - #3836884412 at src/databricks/sql/backend/kernel/client.py:816 Signed-off-by: peco-engineer-bot[bot] <peco-engineer-bot[bot]@users.noreply.github.com>
1 parent 14f2710 commit b4ad166

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

tests/unit/test_kernel_client.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -899,6 +899,54 @@ def test_get_execution_result_owning_handle_failure_can_retry_owning_handle():
899899
c._kernel_session.attach_async_statement.assert_not_called()
900900

901901

902+
def test_get_execution_result_construction_failure_retains_marker_and_attaches_by_id():
903+
"""If the owning handle's ``await_result()`` succeeds but result-set
904+
construction then raises, the ``_async_result_stream_started`` marker
905+
is deliberately left set (the owning stream may be partially
906+
consumed, so re-awaiting it is unsafe). A subsequent call must route
907+
through the attach-by-id fallback rather than re-awaiting the owning
908+
handle."""
909+
c = _make_client()
910+
c._kernel_session = MagicMock()
911+
owning_stream = MagicMock()
912+
# ``KernelResultSet.__init__`` calls ``arrow_schema()``; make that
913+
# raise so ``_make_result_set`` fails after a successful await.
914+
owning_stream.arrow_schema.side_effect = _FakeKernelError(code="Internal")
915+
owning_handle = MagicMock()
916+
owning_handle.await_result.return_value = owning_stream
917+
cid = CommandId.from_sea_statement_id("async-construct-fail")
918+
c._async_handles[cid.guid] = owning_handle
919+
920+
with pytest.raises(DatabaseError):
921+
c.get_execution_result(cid, cursor=MagicMock())
922+
923+
# Marker stays set even though construction failed.
924+
assert cid.guid in c._async_result_stream_started
925+
owning_handle.await_result.assert_called_once_with()
926+
c._kernel_session.attach_async_statement.assert_not_called()
927+
928+
# A retry now attaches by id (fresh stream) instead of re-awaiting
929+
# the partially-consumed owning handle.
930+
retry_stream = MagicMock()
931+
retry_stream.arrow_schema.return_value = pa.schema([("n", pa.int64())])
932+
attached_handle = MagicMock()
933+
attached_handle.await_result.return_value = retry_stream
934+
c._kernel_session.attach_async_statement.return_value = attached_handle
935+
cursor = MagicMock()
936+
cursor.arraysize = 100
937+
cursor.buffer_size_bytes = 1024
938+
939+
rs = c.get_execution_result(cid, cursor=cursor)
940+
941+
assert rs is not None
942+
c._kernel_session.attach_async_statement.assert_called_once_with(
943+
"async-construct-fail"
944+
)
945+
attached_handle.await_result.assert_called_once_with()
946+
# The owning handle was not re-awaited on the retry.
947+
owning_handle.await_result.assert_called_once_with()
948+
949+
902950
def test_get_execution_result_maps_not_found_to_programming_error():
903951
"""An unknown / aged-out id surfaces the kernel's NotFound as a
904952
mapped PEP 249 exception rather than a raw error."""

0 commit comments

Comments
 (0)