Skip to content

Commit 374e2c7

Browse files
Introducing fallback mechanism for all exception in Files API download
1 parent 1592c4e commit 374e2c7

File tree

2 files changed

+12
-20
lines changed

2 files changed

+12
-20
lines changed

databricks/sdk/mixins/files.py

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,8 @@ def _parallel_download_presigned_url(self, remote_path: str, destination: str, p
964964

965965
cloud_session = self._create_cloud_provider_session()
966966
url_distributor = _PresignedUrlDistributor(lambda: self._create_download_url(remote_path))
967+
# An event to indicate if any download chunk has succeeded. If any chunk succeeds, we do not fall back to Files API.
968+
any_success = Event()
967969

968970
def download_chunk(additional_headers: dict[str, str]) -> BinaryIO:
969971
retry_count = 0
@@ -982,10 +984,14 @@ def get_content() -> requests.Response:
982984
url_distributor.invalidate_url(version)
983985
retry_count += 1
984986
continue
985-
elif raw_resp.status_code == 403:
987+
elif raw_resp.status_code == 403 and not any_success.is_set():
986988
raise FallbackToDownloadUsingFilesApi("Received 403 Forbidden from presigned URL")
989+
elif not any_success.is_set():
990+
# For other errors, we raise a retryable exception to trigger retry logic.
991+
raise FallbackToDownloadUsingFilesApi(f"Received {raw_resp.status_code} from presigned URL")
987992

988993
raw_resp.raise_for_status()
994+
any_success.set()
989995
return BytesIO(raw_resp.content)
990996
raise ValueError("Exceeded maximum retries for downloading with presigned URL: URL expired too many times")
991997

@@ -2404,16 +2410,8 @@ def _create_download_url(self, file_path: str) -> CreateDownloadUrlResponse:
24042410
)
24052411

24062412
return CreateDownloadUrlResponse.from_dict(raw_response)
2407-
except PermissionDenied as e:
2408-
if self._is_presigned_urls_disabled_error(e):
2409-
raise FallbackToDownloadUsingFilesApi(f"Presigned URLs are disabled")
2410-
else:
2411-
raise e from None
2412-
except InternalError as e:
2413-
if self._is_presigned_urls_network_zone_error(e):
2414-
raise FallbackToDownloadUsingFilesApi("Presigned URLs are not supported in the current network zone")
2415-
else:
2416-
raise e from None
2413+
except Exception as e:
2414+
raise FallbackToDownloadUsingFilesApi(f"Failed to create download URL: {e}") from e
24172415

24182416
def _init_download_response_presigned_api(self, file_path: str, added_headers: dict[str, str]) -> DownloadResponse:
24192417
"""
@@ -2456,17 +2454,11 @@ def perform() -> requests.Response:
24562454
contents=_StreamingResponse(csp_response, self._config.files_ext_client_download_streaming_chunk_size),
24572455
)
24582456
return resp
2459-
elif csp_response.status_code == 403:
2460-
# We got 403 failure when downloading the file. This might happen due to Azure firewall enabled for the customer bucket.
2461-
# Let's fallback to using Files API which might be allowlisted to download.
2462-
raise FallbackToDownloadUsingFilesApi(f"Direct download forbidden: {csp_response.content}")
24632457
else:
24642458
message = (
24652459
f"Unsuccessful download. Response status: {csp_response.status_code}, body: {csp_response.content}"
24662460
)
2467-
_LOG.warning(message)
2468-
mapped_error = _error_mapper(csp_response, {})
2469-
raise mapped_error or ValueError(message)
2461+
raise FallbackToDownloadUsingFilesApi(message)
24702462

24712463
def _init_download_response_mode_csp_with_fallback(
24722464
self, file_path: str, headers: dict[str, str], response_headers: list[str]

tests/test_files.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1066,14 +1066,14 @@ def run(self, config: Config, monkeypatch) -> None:
10661066
PresignedUrlDownloadTestCase(
10671067
name="Presigned URL download fails with 403",
10681068
file_size=100 * 1024 * 1024,
1069-
expected_exception_type=PermissionDenied,
10701069
custom_response_create_presigned_url=CustomResponse(code=403, only_invocation=1),
1070+
expected_download_api="files_api",
10711071
),
10721072
PresignedUrlDownloadTestCase(
10731073
name="Presigned URL download fails with 500 when creating presigned URL",
10741074
file_size=100 * 1024 * 1024,
1075-
expected_exception_type=InternalError,
10761075
custom_response_create_presigned_url=CustomResponse(code=500, only_invocation=1),
1076+
expected_download_api="files_api",
10771077
),
10781078
PresignedUrlDownloadTestCase(
10791079
name="Presigned URL download fails with 500 when downloading from URL",

0 commit comments

Comments
 (0)