11__all__ = ["Client" , "AuthenticatedClient" , "NeptuneAuthenticator" ]
22
3+ import logging
34import ssl
45import threading
56import typing
1213 Union ,
1314)
1415
16+ import backoff
1517import httpx
1618from attrs import (
1719 define ,
2325from neptune_api .errors import UnableToRefreshTokenError
2426from neptune_api .types import OAuthToken
2527
28+ # Disable httpx logging, httpx logs requests at INFO level
29+ logging .getLogger ("httpx" ).setLevel (logging .WARN )
30+
2631
2732@define
2833class Client :
@@ -349,12 +354,9 @@ def __init__(
349354 self ._client = client
350355 self ._token : Optional [OAuthToken ] = None
351356
352- def _refresh_existing_token (self ) -> None :
357+ def _refresh_existing_token (self ) -> OAuthToken :
353358 if self ._token is None :
354- # This should never happen, but just in case
355- self ._token = self ._api_key_exchange_factory (self ._client , self ._credentials )
356- return
357-
359+ raise ValueError ("Cannot refresh an empty token" )
358360 try :
359361 response = self ._client .get_httpx_client ().post (
360362 url = self ._token_refreshing_endpoint ,
@@ -366,21 +368,26 @@ def _refresh_existing_token(self) -> None:
366368 },
367369 )
368370 data = response .json ()
371+ return OAuthToken .from_tokens (access = data ["access_token" ], refresh = data ["refresh_token" ])
369372 except Exception as e :
370373 raise UnableToRefreshTokenError ("Unable to refresh token" ) from e
371374
372- self ._token = OAuthToken .from_tokens (access = data ["access_token" ], refresh = data ["refresh_token" ])
373-
375+ @backoff .on_exception (backoff .expo , Exception , max_time = 30 , max_tries = 3 )
374376 def _refresh_token (self ) -> None :
375377 with self .__LOCK :
376378 if self ._token is not None :
377- self ._refresh_existing_token ()
379+ self ._token = self . _refresh_existing_token ()
378380
379381 if self ._token is None :
380382 self ._token = self ._api_key_exchange_factory (self ._client , self ._credentials )
381383
382384 def _refresh_token_if_expired (self ) -> None :
383- if self ._token is None or self ._token .is_expired :
385+ try :
386+ if self ._token is None or self ._token .is_expired :
387+ self ._refresh_token ()
388+ except Exception :
389+ # Reset the token to None to force a new token retrieval
390+ self ._token = None
384391 self ._refresh_token ()
385392
386393 def sync_auth_flow (self , request : httpx .Request ) -> Generator [httpx .Request , httpx .Response , None ]:
0 commit comments