diagnostics: Handle TypeError when copying results

Display and log an error, including contents of current_results.

Clear the contents of current_results.

Tests:

- View the diagnostics results as normal.

- Introduce a TypeError before the results are copied. See the error message
  shown in the interface. (The error details are cleared when the page is
  refreshed.)

Helps: #2410

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
[sunil: Fix a mypy error]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
James Valleroy 2024-03-05 07:36:55 -05:00 committed by Sunil Mohan Adapa
parent dfaeadee6b
commit d512e4268c
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2
2 changed files with 20 additions and 4 deletions

View File

@ -103,7 +103,8 @@ def _run_on_all_enabled_modules():
current_results = {
'apps': [],
'results': collections.OrderedDict(),
'progress_percentage': 0
'progress_percentage': 0,
'exception': None,
}
for app in app_module.App.list():
@ -335,15 +336,26 @@ def are_results_available():
return bool(results)
def get_results():
def get_results() -> dict:
"""Return the latest results of full diagnostics."""
global current_results
with results_lock:
results = deepcopy(current_results)
try:
results = deepcopy(current_results)
except TypeError as error:
# See #2410: cannot pickle 'dict_values' object
logger.error('Cannot get diagnostic results: %s - %s', error,
current_results)
exception = str(error) + ' - ' + str(current_results)
# Clear the results that can't be used.
current_results = {}
return {'exception': exception}
# If no results are available in memory, then load from database.
if not results:
results = kvstore.get_default('diagnostics_results', '{}')
results = json.loads(results, cls=CheckJSONDecoder)
results = json.loads(str(results), cls=CheckJSONDecoder)
results = {'results': results, 'progress_percentage': 100}
# Add a translated name for each app

View File

@ -75,6 +75,10 @@ class DiagnosticsFullView(TemplateView):
context['is_task_running'] = is_task_running
context['results'] = diagnostics.get_results()
context['refresh_page_sec'] = 3 if is_task_running else None
exception = context['results'].pop('exception', None)
if exception:
messages.error(self.request, exception)
return context