⚡️(api) add missing cache for stats endpoint
Add cache to display stats for anonymous and improve some code.
This commit is contained in:
@@ -12,6 +12,10 @@ and this project adheres to
|
|||||||
|
|
||||||
- ✨(scripts) adapts release script after moving the deployment part
|
- ✨(scripts) adapts release script after moving the deployment part
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- ⚡️(api) add missing cache for stats endpoint
|
||||||
|
|
||||||
## [1.10.0] - 2025-01-21
|
## [1.10.0] - 2025-01-21
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ from functools import reduce
|
|||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.db.models import OuterRef, Q, Subquery, Value
|
from django.db.models import OuterRef, Q, Subquery, Value
|
||||||
from django.db.models.functions import Coalesce
|
from django.db.models.functions import Coalesce
|
||||||
|
from django.utils.decorators import method_decorator
|
||||||
|
from django.views.decorators.cache import cache_page
|
||||||
|
|
||||||
from rest_framework import (
|
from rest_framework import (
|
||||||
decorators,
|
decorators,
|
||||||
@@ -28,8 +30,6 @@ from core.utils.raw_sql import gen_sql_filter_json_array
|
|||||||
|
|
||||||
from mailbox_manager import models as domains_models
|
from mailbox_manager import models as domains_models
|
||||||
|
|
||||||
SIMILARITY_THRESHOLD = 0.04
|
|
||||||
|
|
||||||
|
|
||||||
class NestedGenericViewSet(viewsets.GenericViewSet):
|
class NestedGenericViewSet(viewsets.GenericViewSet):
|
||||||
"""
|
"""
|
||||||
@@ -596,19 +596,20 @@ class StatView(views.APIView):
|
|||||||
|
|
||||||
permission_classes = [AllowAny]
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
|
@method_decorator(cache_page(3600))
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
"""
|
"""
|
||||||
GET /api/v1.0/stats/
|
GET /api/v1.0/stats/
|
||||||
Return a dictionary of public metrics.
|
Return a dictionary of public metrics.
|
||||||
"""
|
"""
|
||||||
context = {
|
context = {
|
||||||
"total_users": models.User.objects.all().count(),
|
"total_users": models.User.objects.count(),
|
||||||
"mau": models.User.objects.filter(
|
"mau": models.User.objects.filter(
|
||||||
last_login__gte=datetime.datetime.now() - datetime.timedelta(30)
|
last_login__gte=datetime.datetime.now() - datetime.timedelta(30)
|
||||||
).count(),
|
).count(),
|
||||||
"teams": models.Team.objects.all().count(),
|
"teams": models.Team.objects.count(),
|
||||||
"domains": domains_models.MailDomain.objects.all().count(),
|
"domains": domains_models.MailDomain.objects.count(),
|
||||||
"mailboxes": domains_models.Mailbox.objects.all().count(),
|
"mailboxes": domains_models.Mailbox.objects.count(),
|
||||||
}
|
}
|
||||||
return response.Response(context)
|
return response.Response(context)
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
Test stats endpoint
|
Test stats endpoint
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.test import APIClient
|
from rest_framework.test import APIClient
|
||||||
@@ -14,17 +16,34 @@ from mailbox_manager import models as domains_models
|
|||||||
pytestmark = pytest.mark.django_db
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
def test_api_stats__anonymous():
|
def test_api_stats__anonymous(django_assert_num_queries):
|
||||||
"""Stats endpoint should be available even when not connected."""
|
"""Stats endpoint should be available even when not connected."""
|
||||||
|
|
||||||
response = APIClient().get("/api/v1.0/stats/")
|
domains_factories.MailDomainFactory.create_batch(5)
|
||||||
|
core_factories.TeamFactory.create_batch(3)
|
||||||
|
|
||||||
|
# clear cache to allow stats count
|
||||||
|
cache.clear()
|
||||||
|
with django_assert_num_queries(5):
|
||||||
|
response = APIClient().get("/api/v1.0/stats/")
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
"total_users": 0,
|
"total_users": 0,
|
||||||
"mau": 0,
|
"mau": 0,
|
||||||
"domains": 0,
|
"domains": 5,
|
||||||
"mailboxes": 0,
|
"mailboxes": 0,
|
||||||
"teams": 0,
|
"teams": 3,
|
||||||
|
}
|
||||||
|
# no new request made due to caching
|
||||||
|
with django_assert_num_queries(0):
|
||||||
|
response = APIClient().get("/api/v1.0/stats/")
|
||||||
|
assert response.status_code == status.HTTP_200_OK
|
||||||
|
assert response.json() == {
|
||||||
|
"total_users": 0,
|
||||||
|
"mau": 0,
|
||||||
|
"domains": 5,
|
||||||
|
"mailboxes": 0,
|
||||||
|
"teams": 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -43,6 +62,8 @@ def test_api_stats__expected_count():
|
|||||||
10, domain=domains_models.MailDomain.objects.all()[1]
|
10, domain=domains_models.MailDomain.objects.all()[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# clear cache to allow stats count
|
||||||
|
cache.clear()
|
||||||
response = APIClient().get("/api/v1.0/stats/")
|
response = APIClient().get("/api/v1.0/stats/")
|
||||||
assert response.status_code == status.HTTP_200_OK
|
assert response.status_code == status.HTTP_200_OK
|
||||||
assert response.json() == {
|
assert response.json() == {
|
||||||
|
|||||||
Reference in New Issue
Block a user