@@ -56,6 +56,12 @@ class IbmWatsonxConnectionConfig(ConnectionConfig):
5656 object_storage_endpoint : str = Field (description = "Cloud Object Storage public endpoint" )
5757 object_storage_region : str = Field (description = "Cloud Object Storage region" )
5858 catalog : str = Field (description = "Catalog name" )
59+ max_retries_connection : int = Field (
60+ default = 10 ,
61+ description = "Maximum number of retries in case of a connection error (RESTError)" ,
62+ ge = 2 ,
63+ le = 100 ,
64+ )
5965
6066 _bearer_token : Optional [dict [str , Any ]] = None
6167
@@ -145,10 +151,29 @@ def get_catalog_config(self) -> dict[str, Any]:
145151 @contextmanager
146152 def get_catalog (self ) -> Generator ["RestCatalog" , None , None ]:
147153 from pyiceberg .catalog import load_catalog
154+ from pyiceberg .exceptions import RESTError
155+ from tenacity import (
156+ before_log ,
157+ retry ,
158+ retry_if_exception_type ,
159+ stop_after_attempt ,
160+ wait_exponential ,
161+ )
162+
163+ # Retry connection in case of a connection error
164+ @retry (
165+ stop = stop_after_attempt (self .max_retries_connection ),
166+ wait = wait_exponential (exp_base = 2 , multiplier = 1 , min = 2 , max = 10 ),
167+ retry = retry_if_exception_type (RESTError ),
168+ before = before_log (logger , logging .DEBUG ),
169+ reraise = True ,
170+ )
171+ def _get_catalog (catalog_config : dict [str , Any ]) -> "RestCatalog" :
172+ return load_catalog (** catalog_config )
148173
149174 try :
150175 catalog_config = self .get_catalog_config ()
151- catalog = load_catalog ( ** catalog_config )
176+ catalog = _get_catalog ( catalog_config )
152177 except Exception as e :
153178 logger .error (f"Failed to connect to catalog '{ self .catalog } ': { e } " , exc_info = True )
154179 raise ProviderError (f"Failed to connect to catalog '{ self .catalog } ': { e } " )
@@ -172,7 +197,10 @@ class IbmWatsonxUploaderConfig(UploaderConfig):
172197 namespace : str = Field (description = "Namespace name" )
173198 table : str = Field (description = "Table name" )
174199 max_retries : int = Field (
175- default = 5 , description = "Maximum number of retries to upload data" , ge = 2 , le = 500
200+ default = 5 ,
201+ description = "Maximum number of retries to upload data (CommitFailedException)" ,
202+ ge = 2 ,
203+ le = 500 ,
176204 )
177205 record_id_key : str = Field (
178206 default = RECORD_ID_LABEL ,
@@ -287,15 +315,15 @@ def upload_dataframe(self, df: "DataFrame", file_data: FileData) -> None:
287315 retry ,
288316 retry_if_exception_type ,
289317 stop_after_attempt ,
290- wait_random ,
318+ wait_exponential ,
291319 )
292320
293321 data_table = self ._df_to_arrow_table (df )
294322
295- # Retry connection in case of connection error
323+ # Retry connection in case of a connection error or token expiration
296324 @retry (
297- stop = stop_after_attempt (2 ),
298- wait = wait_random ( ),
325+ stop = stop_after_attempt (self . connection_config . max_retries_connection ),
326+ wait = wait_exponential ( exp_base = 2 , multiplier = 1 , min = 2 , max = 10 ),
299327 retry = retry_if_exception_type (RESTError ),
300328 before = before_log (logger , logging .DEBUG ),
301329 reraise = True ,
0 commit comments