1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-14 08:17:13 +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
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.
This can be triggered by hitting the main UI 'Update' button,
automatically on docking, or due to a retry.
:param event: Tk generated event details.
"""
auto_update = not event
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()
return
if not retrying:
if not companion.session.retrying:
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:
self.status['text'] = ''
@ -937,7 +939,7 @@ class AppWindow(object):
config.set('querytime', query_time)
companion.session.station(
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
@ -1112,13 +1114,14 @@ class AppWindow(object):
# Companion API problem
except companion.ServerLagging as e:
err = str(e)
if capi_response.retrying:
if companion.session.retrying:
self.status['text'] = err
play_bad = True
else:
# 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
except companion.CmdrError as e: # Companion API return doesn't match Journal

View File

@ -533,11 +533,10 @@ class EDMCCAPIReturn:
def __init__(
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.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.auto_update: bool = auto_update # Whether this was automatically triggered.
@ -549,11 +548,11 @@ class EDMCCAPIRequest(EDMCCAPIReturn):
def __init__(
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
):
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
)
self.endpoint: str = endpoint # The CAPI query to perform.
@ -564,9 +563,9 @@ class EDMCCAPIResponse(EDMCCAPIReturn):
def __init__(
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)
@ -575,10 +574,10 @@ class EDMCCAPIFailedRequest(EDMCCAPIReturn):
def __init__(
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
):
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.exception: int = exception # Exception that recipient should raise.
@ -759,21 +758,16 @@ class Session(object):
logger.warning(f'Request {capi_endpoint}: {e}')
raise ServerConnectionError(f'Unable to connect to endpoint: {capi_endpoint}') from e
except (requests.HTTPError, ValueError) as e:
logger.exception('Frontier CAPI Auth: GET ')
except requests.HTTPError as e: # In response to raise_for_status()
logger.exception(f'Frontier CAPI Auth: GET {capi_endpoint}')
self.dump(r)
# TODO: Does this *necessarily* mean we need to call close() ?
# Maybe the **CAPI** had a transitory issue and auth is fine.
self.close()
if r.status_code == 401: # CAPI doesn't think we're Auth'd
# 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
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
# 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
# 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')
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:
logger.debug('Attempting GET', exc_info=e)
# LANG: Frontier CAPI data retrieval failed
@ -906,7 +905,6 @@ class Session(object):
break
logger.trace_if('capi.worker', f'Processing query: {query.endpoint}')
self.retrying = query.retrying
capi_data: CAPIData
if query.endpoint == self._CAPI_PATH_STATION:
try:
@ -976,7 +974,7 @@ class Session(object):
def query(
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
) -> None:
"""
@ -985,7 +983,6 @@ class Session(object):
:param endpoint: The CAPI endpoint to query.
:param tk_response_event: Name of tk event to generate when response queued.
: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 auto_update: Whether this request was triggered automatically.
"""
@ -1010,7 +1007,6 @@ class Session(object):
EDMCCAPIRequest(
endpoint=endpoint,
tk_response_event=tk_response_event,
retrying=retrying,
query_time=query_time,
play_sound=play_sound,
auto_update=auto_update
@ -1020,7 +1016,7 @@ class Session(object):
def profile(
self,
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
) -> None:
"""
@ -1028,7 +1024,6 @@ class Session(object):
:param query_time: When this query was initiated.
: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 auto_update: Whether this request was triggered automatically.
"""
@ -1037,20 +1032,19 @@ class Session(object):
self.query(
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
)
def station(
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:
"""
Perform CAPI quer(y|ies) for station data.
:param query_time: When this query was initiated.
: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 auto_update: Whether this request was triggered automatically.
"""
@ -1060,7 +1054,6 @@ class Session(object):
endpoint=self._CAPI_PATH_STATION,
tk_response_event=tk_response_event,
query_time=query_time,
retrying=retrying,
play_sound=play_sound,
auto_update=auto_update
)