1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-06-05 18:03:17 +03:00

CAPI: Begin taking auth retries out of CAPI queries

* Only set/use retrying as companion.session.retrying (untested).
* Don't call Session.login() from CAPI query code, raise
  CredentialsError instead.
* Also don't Session.close() in CAPI query code.
This commit is contained in:
Athanasius 2021-08-26 14:44:43 +01:00
parent 303df05f2c
commit 816384f16f
No known key found for this signature in database
GPG Key ID: AE3E527847057C7D
2 changed files with 30 additions and 34 deletions

View File

@ -891,12 +891,14 @@ class AppWindow(object):
return True return True
def capi_request_data(self, event=None, retrying: bool = False): def capi_request_data(self, event=None) -> None:
""" """
Perform CAPI data retrieval and associated actions. Perform CAPI data retrieval and associated actions.
This can be triggered by hitting the main UI 'Update' button, This can be triggered by hitting the main UI 'Update' button,
automatically on docking, or due to a retry. automatically on docking, or due to a retry.
:param event: Tk generated event details.
""" """
auto_update = not event auto_update = not event
play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL) and not config.get_int('hotkey_mute') play_sound = (auto_update or int(event.type) == self.EVENT_VIRTUAL) and not config.get_int('hotkey_mute')
@ -916,7 +918,7 @@ class AppWindow(object):
self.login() self.login()
return return
if not retrying: if not companion.session.retrying:
if time() < self.capi_query_holdoff_time: # Was invoked by key while in cooldown if time() < self.capi_query_holdoff_time: # Was invoked by key while in cooldown
if play_sound and (self.capi_query_holdoff_time - time()) < companion.capi_query_cooldown * 0.75: if play_sound and (self.capi_query_holdoff_time - time()) < companion.capi_query_cooldown * 0.75:
self.status['text'] = '' self.status['text'] = ''
@ -937,7 +939,7 @@ class AppWindow(object):
config.set('querytime', query_time) config.set('querytime', query_time)
companion.session.station( companion.session.station(
query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME, query_time=query_time, tk_response_event=self._CAPI_RESPONSE_TK_EVENT_NAME,
retrying=retrying, play_sound=play_sound play_sound=play_sound
) )
def capi_handle_response(self, event=None): # noqa: C901, CCR001 def capi_handle_response(self, event=None): # noqa: C901, CCR001
@ -1112,13 +1114,14 @@ class AppWindow(object):
# Companion API problem # Companion API problem
except companion.ServerLagging as e: except companion.ServerLagging as e:
err = str(e) err = str(e)
if capi_response.retrying: if companion.session.retrying:
self.status['text'] = err self.status['text'] = err
play_bad = True play_bad = True
else: else:
# Retry once if Companion server is unresponsive # Retry once if Companion server is unresponsive
self.w.after(int(SERVER_RETRY * 1000), lambda: self.capi_request_data(event, True)) companion.session.retrying = True
self.w.after(int(SERVER_RETRY * 1000), lambda: self.capi_request_data(event))
return # early exit to avoid starting cooldown count return # early exit to avoid starting cooldown count
except companion.CmdrError as e: # Companion API return doesn't match Journal except companion.CmdrError as e: # Companion API return doesn't match Journal

View File

@ -533,11 +533,10 @@ class EDMCCAPIReturn:
def __init__( def __init__(
self, query_time: int, tk_response_event: Optional[str] = None, self, query_time: int, tk_response_event: Optional[str] = None,
retrying: bool = False, play_sound: bool = False, auto_update: bool = False play_sound: bool = False, auto_update: bool = False
): ):
self.tk_response_event = tk_response_event # Name of tk event to generate when response queued. self.tk_response_event = tk_response_event # Name of tk event to generate when response queued.
self.query_time: int = query_time # When this query is considered to have started (time_t). self.query_time: int = query_time # When this query is considered to have started (time_t).
self.retrying: bool = retrying # Whether this is already a retry.
self.play_sound: bool = play_sound # Whether to play good/bad sounds for success/failure. self.play_sound: bool = play_sound # Whether to play good/bad sounds for success/failure.
self.auto_update: bool = auto_update # Whether this was automatically triggered. self.auto_update: bool = auto_update # Whether this was automatically triggered.
@ -549,11 +548,11 @@ class EDMCCAPIRequest(EDMCCAPIReturn):
def __init__( def __init__(
self, endpoint: str, query_time: int, self, endpoint: str, query_time: int,
tk_response_event: Optional[str] = None, retrying: bool = False, tk_response_event: Optional[str] = None,
play_sound: bool = False, auto_update: bool = False play_sound: bool = False, auto_update: bool = False
): ):
super().__init__( super().__init__(
query_time=query_time, tk_response_event=tk_response_event, retrying=retrying, query_time=query_time, tk_response_event=tk_response_event,
play_sound=play_sound, auto_update=auto_update play_sound=play_sound, auto_update=auto_update
) )
self.endpoint: str = endpoint # The CAPI query to perform. self.endpoint: str = endpoint # The CAPI query to perform.
@ -564,9 +563,9 @@ class EDMCCAPIResponse(EDMCCAPIReturn):
def __init__( def __init__(
self, capi_data: CAPIData, self, capi_data: CAPIData,
query_time: int, retrying: bool = False, play_sound: bool = False, auto_update: bool = False query_time: int, play_sound: bool = False, auto_update: bool = False
): ):
super().__init__(query_time=query_time, retrying=retrying, play_sound=play_sound, auto_update=auto_update) super().__init__(query_time=query_time, play_sound=play_sound, auto_update=auto_update)
self.capi_data: CAPIData = capi_data # Frontier CAPI response, possibly augmented (station query) self.capi_data: CAPIData = capi_data # Frontier CAPI response, possibly augmented (station query)
@ -575,10 +574,10 @@ class EDMCCAPIFailedRequest(EDMCCAPIReturn):
def __init__( def __init__(
self, message: str, self, message: str,
query_time: int, retrying: bool = False, play_sound: bool = False, auto_update: bool = False, query_time: int, play_sound: bool = False, auto_update: bool = False,
exception=None exception=None
): ):
super().__init__(query_time=query_time, retrying=retrying, play_sound=play_sound, auto_update=auto_update) super().__init__(query_time=query_time, play_sound=play_sound, auto_update=auto_update)
self.message: str = message # User-friendly reason for failure. self.message: str = message # User-friendly reason for failure.
self.exception: int = exception # Exception that recipient should raise. self.exception: int = exception # Exception that recipient should raise.
@ -759,21 +758,16 @@ class Session(object):
logger.warning(f'Request {capi_endpoint}: {e}') logger.warning(f'Request {capi_endpoint}: {e}')
raise ServerConnectionError(f'Unable to connect to endpoint: {capi_endpoint}') from e raise ServerConnectionError(f'Unable to connect to endpoint: {capi_endpoint}') from e
except (requests.HTTPError, ValueError) as e: except requests.HTTPError as e: # In response to raise_for_status()
logger.exception('Frontier CAPI Auth: GET ') logger.exception(f'Frontier CAPI Auth: GET {capi_endpoint}')
self.dump(r) self.dump(r)
# TODO: Does this *necessarily* mean we need to call close() ?
# Maybe the **CAPI** had a transitory issue and auth is fine. if r.status_code == 401: # CAPI doesn't think we're Auth'd
self.close() # TODO: Translation ?
raise CredentialsError('Frontier CAPI said Auth required') from e
if self.retrying: # Refresh just succeeded but this query failed! Force full re-authentication if self.retrying: # Refresh just succeeded but this query failed! Force full re-authentication
logger.error('Frontier CAPI Auth: query failed after refresh')
# TODO: Again, this might be an auth issue, but maybe not.
self.invalidate()
self.retrying = False self.retrying = False
# TODO: This must NOT happen here, we need to signal back to the requesting
# code that it needs to sort out auth.
self.login()
raise CredentialsError('query failed after refresh') from e raise CredentialsError('query failed after refresh') from e
# TODO: Better to return error and have upstream re-try auth ? # TODO: Better to return error and have upstream re-try auth ?
@ -788,6 +782,11 @@ class Session(object):
logger.error('Frontier CAPI Auth: HTTP error or invalid JSON') logger.error('Frontier CAPI Auth: HTTP error or invalid JSON')
raise CredentialsError('HTTP error or invalid JSON') from e raise CredentialsError('HTTP error or invalid JSON') from e
except ValueError as e:
logger.exception(f'decoding CAPI response content:\n{r.content.decode(encoding="utf-8")}\n')
# TODO: What now ?
raise ServerError("Couldn't JSON decode CAPI response") from e
except Exception as e: except Exception as e:
logger.debug('Attempting GET', exc_info=e) logger.debug('Attempting GET', exc_info=e)
# LANG: Frontier CAPI data retrieval failed # LANG: Frontier CAPI data retrieval failed
@ -906,7 +905,6 @@ class Session(object):
break break
logger.trace_if('capi.worker', f'Processing query: {query.endpoint}') logger.trace_if('capi.worker', f'Processing query: {query.endpoint}')
self.retrying = query.retrying
capi_data: CAPIData capi_data: CAPIData
if query.endpoint == self._CAPI_PATH_STATION: if query.endpoint == self._CAPI_PATH_STATION:
try: try:
@ -976,7 +974,7 @@ class Session(object):
def query( def query(
self, endpoint: str, query_time: int, self, endpoint: str, query_time: int,
tk_response_event: Optional[str] = None, retrying: bool = False, tk_response_event: Optional[str] = None,
play_sound: bool = False, auto_update: bool = False play_sound: bool = False, auto_update: bool = False
) -> None: ) -> None:
""" """
@ -985,7 +983,6 @@ class Session(object):
:param endpoint: The CAPI endpoint to query. :param endpoint: The CAPI endpoint to query.
:param tk_response_event: Name of tk event to generate when response queued. :param tk_response_event: Name of tk event to generate when response queued.
:param query_time: When this query was initiated. :param query_time: When this query was initiated.
:param retrying: Whether this is a retry.
:param play_sound: Whether the app should play a sound on error. :param play_sound: Whether the app should play a sound on error.
:param auto_update: Whether this request was triggered automatically. :param auto_update: Whether this request was triggered automatically.
""" """
@ -1010,7 +1007,6 @@ class Session(object):
EDMCCAPIRequest( EDMCCAPIRequest(
endpoint=endpoint, endpoint=endpoint,
tk_response_event=tk_response_event, tk_response_event=tk_response_event,
retrying=retrying,
query_time=query_time, query_time=query_time,
play_sound=play_sound, play_sound=play_sound,
auto_update=auto_update auto_update=auto_update
@ -1020,7 +1016,7 @@ class Session(object):
def profile( def profile(
self, self,
query_time: int = 0, query_time: int = 0,
tk_response_event: Optional[str] = None, retrying: bool = False, tk_response_event: Optional[str] = None,
play_sound: bool = False, auto_update: bool = False play_sound: bool = False, auto_update: bool = False
) -> None: ) -> None:
""" """
@ -1028,7 +1024,6 @@ class Session(object):
:param query_time: When this query was initiated. :param query_time: When this query was initiated.
:param tk_response_event: Name of tk event to generate when response queued. :param tk_response_event: Name of tk event to generate when response queued.
:param retrying: Whether this is a retry.
:param play_sound: Whether the app should play a sound on error. :param play_sound: Whether the app should play a sound on error.
:param auto_update: Whether this request was triggered automatically. :param auto_update: Whether this request was triggered automatically.
""" """
@ -1037,20 +1032,19 @@ class Session(object):
self.query( self.query(
self.FRONTIER_CAPI_PATH_PROFILE, query_time=query_time, self.FRONTIER_CAPI_PATH_PROFILE, query_time=query_time,
tk_response_event=tk_response_event, retrying=retrying, tk_response_event=tk_response_event,
play_sound=play_sound, auto_update=auto_update play_sound=play_sound, auto_update=auto_update
) )
def station( def station(
self, query_time: int, tk_response_event: Optional[str] = None, self, query_time: int, tk_response_event: Optional[str] = None,
retrying: bool = False, play_sound: bool = False, auto_update: bool = False play_sound: bool = False, auto_update: bool = False
) -> None: ) -> None:
""" """
Perform CAPI quer(y|ies) for station data. Perform CAPI quer(y|ies) for station data.
:param query_time: When this query was initiated. :param query_time: When this query was initiated.
:param tk_response_event: Name of tk event to generate when response queued. :param tk_response_event: Name of tk event to generate when response queued.
:param retrying: Whether this is a retry.
:param play_sound: Whether the app should play a sound on error. :param play_sound: Whether the app should play a sound on error.
:param auto_update: Whether this request was triggered automatically. :param auto_update: Whether this request was triggered automatically.
""" """
@ -1060,7 +1054,6 @@ class Session(object):
endpoint=self._CAPI_PATH_STATION, endpoint=self._CAPI_PATH_STATION,
tk_response_event=tk_response_event, tk_response_event=tk_response_event,
query_time=query_time, query_time=query_time,
retrying=retrying,
play_sound=play_sound, play_sound=play_sound,
auto_update=auto_update auto_update=auto_update
) )