1
0
Fork 0

Fix 500 error of stats page when cache isn't ready

Signed-off-by: Alfredos-Panagiotis Damkalis <fredy@fredy.gr>
spacecruft
Alfredos-Panagiotis Damkalis 2022-05-19 14:00:37 +03:00
parent 13e045164e
commit 6d5f0d1ba8
4 changed files with 54 additions and 13 deletions

View File

@ -10,6 +10,7 @@ from celery import shared_task
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.core.cache import cache
from django.core.exceptions import ValidationError
from django.core.files import File
from django.core.mail import send_mail
@ -30,6 +31,12 @@ LOGGER = logging.getLogger('db')
CONTEXT = zmq.Context()
def delay_task_with_lock(task, lock_id, lock_expiration, *args):
"""Ensure unique run of a task by aquiring lock"""
if cache.add('{0}-{1}'.format(task.name, lock_id), '', lock_expiration):
task.delay(*args)
@shared_task
def check_celery():
"""Dummy celery task to check that everything runs smoothly."""

View File

@ -279,7 +279,7 @@ class PopulatedDBTest(TestCase):
# refresh statistics first
refresh = self.client.get('/statistics/')
response = self.client.get('/stats/')
assertContains(response, 'Total Satellites')
assertContains(response, 'calculation')
def test_robots(client):

View File

@ -11,7 +11,6 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.core.paginator import Paginator
from django.db import OperationalError
from django.db.models import Count, Max, Prefetch, Q
from django.http import HttpResponse, HttpResponseServerError, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
@ -24,8 +23,9 @@ from db.base.forms import MergeSatellitesForm, SatelliteCreateForm, SatelliteUpd
from db.base.helpers import get_api_token
from db.base.models import DemodData, Satellite, SatelliteEntry, SatelliteIdentifier, \
SatelliteSuggestion, Transmitter, TransmitterEntry, TransmitterSuggestion
from db.base.tasks import export_frames, notify_suggestion
from db.base.utils import cache_statistics, millify, read_influx
from db.base.tasks import background_cache_statistics, delay_task_with_lock, export_frames, \
notify_suggestion
from db.base.utils import millify, read_influx
LOGGER = logging.getLogger('db')
@ -334,18 +334,15 @@ def search(request):
def stats(request):
"""View to render stats page.
:returns: base/stats.html
:returns: base/stats.html or base/calc-stats.html
"""
cached_satellites = []
ids = cache.get('satellites_ids')
observers = cache.get('stats_observers')
if not ids or not observers:
try:
cache_statistics()
ids = cache.get('satellites_ids')
observers = cache.get('stats_observers')
except OperationalError:
pass
delay_task_with_lock(background_cache_statistics, 1, 3600)
return render(request, 'base/calc-stats.html')
for sid in ids:
stat = cache.get(sid)
cached_satellites.append(stat)
@ -359,13 +356,12 @@ def stats(request):
def statistics(request):
"""Triggers a refresh of cached statistics if the cache does not exist
"""Return transmitter cached statistics if the cache exist
:returns: JsonResponse of statistics
"""
cached_stats = cache.get('stats_transmitters')
if not cached_stats:
cache_statistics()
cached_stats = []
return JsonResponse(cached_stats, safe=False)

View File

@ -0,0 +1,38 @@
{% extends "base.html" %}
{% load tags %}
{% load static %}
{% block title %} - Stats{% endblock %}
{% block top-menu-left %}
<span class="h4 mb-0 mr-3 text-truncate d-none d-md-block">Statistics</span>
{% endblock %}
{% block top %}
<span class="h4 mb-0">Statistics</span>
{% endblock %}
{% block content %}
<!-- SatNOGS DB Calculating Stats -->
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-md-9">
<div class="card card-info first-card">
<div class="card-header card-satnogs-header">
Statistics
</div>
<div class="card-body">
<p>
Statistics calculation is in progress and it may take several minutes to complete.
</p>
<p>
Please come back later!
</p>
</div>
</div>
</div>
</div>
</div>
{% endblock %}