Merge branch 'main' of github.com:decompals/frogress
This commit is contained in:
commit
2c6c86ecfb
|
@ -0,0 +1,45 @@
|
||||||
|
from typing import Optional
|
||||||
|
from django.core.cache import cache
|
||||||
|
from rest_framework.utils.serializer_helpers import ReturnDict
|
||||||
|
|
||||||
|
ENTRIES_CACHE_TIMEOUT = 7200 # 2 hours
|
||||||
|
|
||||||
|
|
||||||
|
def _entries_cache_key(project_slug: str, version_slug: str, category_slug: str) -> str:
|
||||||
|
return f"entries_{project_slug}_{version_slug}_{category_slug}"
|
||||||
|
|
||||||
|
|
||||||
|
def get_entries_cache(
|
||||||
|
project_slug: str, version_slug: str, category_slug: str
|
||||||
|
) -> Optional[ReturnDict]:
|
||||||
|
"""
|
||||||
|
Fetches cached entries data.
|
||||||
|
"""
|
||||||
|
return cache.get(_entries_cache_key(project_slug, version_slug, category_slug))
|
||||||
|
|
||||||
|
|
||||||
|
def set_entries_cache(
|
||||||
|
project_slug: str, version_slug: str, category_slug: str, data: ReturnDict
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Updates cached entries data.
|
||||||
|
"""
|
||||||
|
cache.set(
|
||||||
|
_entries_cache_key(project_slug, version_slug, category_slug),
|
||||||
|
data,
|
||||||
|
ENTRIES_CACHE_TIMEOUT,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def invalidate_entries_cache(
|
||||||
|
project_slug: str, version_slug: str, data: ReturnDict
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Invalidates all affected entries caches.
|
||||||
|
"""
|
||||||
|
all_categories = set()
|
||||||
|
for entry in data["entries"]:
|
||||||
|
for category in entry["categories"]:
|
||||||
|
all_categories.add(category)
|
||||||
|
for category_slug in all_categories:
|
||||||
|
cache.delete(_entries_cache_key(project_slug, version_slug, category_slug))
|
|
@ -3,6 +3,11 @@ from typing import Any
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.template.defaultfilters import title
|
from django.template.defaultfilters import title
|
||||||
|
|
||||||
|
from frog_api.cache import (
|
||||||
|
invalidate_entries_cache,
|
||||||
|
set_entries_cache,
|
||||||
|
get_entries_cache,
|
||||||
|
)
|
||||||
from frog_api.exceptions import (
|
from frog_api.exceptions import (
|
||||||
InvalidDataException,
|
InvalidDataException,
|
||||||
NoEntriesException,
|
NoEntriesException,
|
||||||
|
@ -43,13 +48,19 @@ def get_latest_entry(
|
||||||
def get_all_entries(
|
def get_all_entries(
|
||||||
project_slug: str, version_slug: str, category_slug: str
|
project_slug: str, version_slug: str, category_slug: str
|
||||||
) -> list[dict[str, Any]]:
|
) -> list[dict[str, Any]]:
|
||||||
|
data = get_entries_cache(project_slug, version_slug, category_slug)
|
||||||
|
if data:
|
||||||
|
return data # type: ignore
|
||||||
|
|
||||||
project = get_project(project_slug)
|
project = get_project(project_slug)
|
||||||
version = get_version(version_slug, project)
|
version = get_version(version_slug, project)
|
||||||
category = get_category(category_slug, version)
|
category = get_category(category_slug, version)
|
||||||
|
|
||||||
entries = Entry.objects.filter(category=category)
|
entries = Entry.objects.filter(category=category).prefetch_related("measures")
|
||||||
|
|
||||||
return EntrySerializer(entries, many=True).data # type: ignore
|
data = EntrySerializer(entries, many=True).data
|
||||||
|
set_entries_cache(project_slug, version_slug, category_slug, data)
|
||||||
|
return data # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def get_versions_digest_for_project(project: Project) -> dict[Any, Any]:
|
def get_versions_digest_for_project(project: Project) -> dict[Any, Any]:
|
||||||
|
@ -191,6 +202,8 @@ class VersionDataView(APIView):
|
||||||
for s in to_save:
|
for s in to_save:
|
||||||
s.save()
|
s.save()
|
||||||
|
|
||||||
|
invalidate_entries_cache(project_slug, version_slug, data)
|
||||||
|
|
||||||
return len(to_save)
|
return len(to_save)
|
||||||
|
|
||||||
def get(self, request: Request, project_slug: str, version_slug: str) -> Response:
|
def get(self, request: Request, project_slug: str, version_slug: str) -> Response:
|
||||||
|
|
|
@ -42,6 +42,7 @@ class ProjectStructureView(APIView):
|
||||||
Create a new project.
|
Create a new project.
|
||||||
"""
|
"""
|
||||||
request_ser = CreateProjectSerializer(data=request.data)
|
request_ser = CreateProjectSerializer(data=request.data)
|
||||||
|
request_ser.is_valid(raise_exception=True)
|
||||||
|
|
||||||
validate_ultimate_api_key(request_ser.data["api_key"])
|
validate_ultimate_api_key(request_ser.data["api_key"])
|
||||||
|
|
||||||
|
@ -58,12 +59,10 @@ class VersionStructureView(APIView):
|
||||||
|
|
||||||
def post(self, request: Request, project_slug: str, version_slug: str) -> Response:
|
def post(self, request: Request, project_slug: str, version_slug: str) -> Response:
|
||||||
request_ser = CreateVersionSerializer(data=request.data)
|
request_ser = CreateVersionSerializer(data=request.data)
|
||||||
|
request_ser.is_valid(raise_exception=True)
|
||||||
|
|
||||||
project = get_project(project_slug)
|
project = get_project(project_slug)
|
||||||
|
|
||||||
if not request_ser.is_valid():
|
|
||||||
return Response(request_ser.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
||||||
|
|
||||||
validate_api_key(request_ser.data["api_key"], project)
|
validate_api_key(request_ser.data["api_key"], project)
|
||||||
|
|
||||||
if Version.objects.filter(slug=version_slug, project=project).exists():
|
if Version.objects.filter(slug=version_slug, project=project).exists():
|
||||||
|
|
Loading…
Reference in New Issue