@@ -16,6 +16,11 @@ class OneDriveClientException(Exception):
1616 pass
1717
1818
19+ class OneDriveTransientException (OneDriveClientException ):
20+ """Raised for transient HTTP errors (429, 5xx) that are safe to retry."""
21+ pass
22+
23+
1924class OneDriveClient (HttpClient ):
2025 """
2126 The OneDriveClient class manages the interaction with OneDrive API. It handles tasks such as
@@ -138,19 +143,34 @@ def refresh_token(self):
138143 return self ._refresh_token
139144
140145 def get_request (self , url : str , is_absolute_path : bool , stream : bool = False ):
141- response = self .get_raw (url , is_absolute_path = is_absolute_path , stream = stream )
142- if response .status_code == 200 :
143- return response
144- elif response .status_code == 401 :
145- self ._get_request_tokens ()
146- return self .get_request (url , is_absolute_path , stream )
147- elif response .status_code == 404 :
148- logging .error (f"Url { url } returned 404." )
149- return None
150- else :
151- raise OneDriveClientException (f"Cannot fetch { url } , "
152- f"response: { response .text } , "
153- f"status_code: { response .status_code } " )
146+ for attempt in range (2 ):
147+ response = self .get_raw (url , is_absolute_path = is_absolute_path , stream = stream )
148+ if response .status_code == 200 :
149+ return response
150+ elif response .status_code == 404 :
151+ logging .error (f"Url { url } returned 404." )
152+ return None
153+ elif response .status_code == 401 :
154+ if attempt == 0 :
155+ logging .warning (f"Got 401 fetching { url } , refreshing token and retrying..." )
156+ self ._get_request_tokens ()
157+ continue
158+ error_body = response .json ()
159+ error_code = error_body .get ("error" , "unknown" )
160+ error_desc = error_body .get ("error_description" , "no description" )
161+ raise OneDriveClientException (
162+ f"Authentication failed after token refresh (HTTP 401): "
163+ f"{ error_code } - { error_desc } "
164+ )
165+ elif response .status_code in (429 , 500 , 502 , 503 , 504 ):
166+ raise OneDriveTransientException (
167+ f"Transient error fetching { url } : HTTP { response .status_code } - { response .text } "
168+ )
169+ else :
170+ raise OneDriveClientException (
171+ f"Cannot fetch { url } , response: { response .text } , "
172+ f"status_code: { response .status_code } "
173+ )
154174
155175 def _resolve_folder_id (self , drive_type : str , folder_path : str ):
156176 if folder_path is None or folder_path == '/' :
@@ -302,7 +322,7 @@ def _get_sharepoint_document_libraries(self):
302322 raise OneDriveClientException (f"Error occurred when getting SharePoint document libraries:"
303323 f" { response .status_code } , { response .text } " )
304324
305- @backoff .on_exception (backoff .expo , Exception , max_tries = MAX_RETRIES )
325+ @backoff .on_exception (backoff .expo , OneDriveTransientException , max_tries = MAX_RETRIES )
306326 def _download_file_from_onedrive_url (self , url , output_path , filename ):
307327 """
308328 Downloads a file from OneDrive using the provided download URL and saves it to the specified output path.
0 commit comments