[WEB-4533] feat: read replica functionality (#7453)
* feat: read replica functionality * fix: set use_read_replica to false * chore: add use_read_replica to external APIs * chore: remove use_read_replica on read endpoints * chore: remove md files * Updated all the necessary endpoints to use read replica --------- Co-authored-by: Dheeraj Kumar Ketireddy <dheeru0198@gmail.com>
This commit is contained in:
parent
b1162395ed
commit
84879ee3bd
34 changed files with 884 additions and 6 deletions
|
|
@ -24,6 +24,7 @@ from rest_framework.viewsets import ModelViewSet
|
|||
from plane.authentication.session import BaseSessionAuthentication
|
||||
from plane.utils.exception_logger import log_exception
|
||||
from plane.utils.paginator import BasePaginator
|
||||
from plane.utils.core.mixins import ReadReplicaControlMixin
|
||||
|
||||
|
||||
class TimezoneMixin:
|
||||
|
|
@ -40,7 +41,7 @@ class TimezoneMixin:
|
|||
timezone.deactivate()
|
||||
|
||||
|
||||
class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
|
||||
class BaseViewSet(TimezoneMixin, ReadReplicaControlMixin, ModelViewSet, BasePaginator):
|
||||
model = None
|
||||
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
|
@ -53,6 +54,8 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
|
|||
|
||||
search_fields = []
|
||||
|
||||
use_read_replica = False
|
||||
|
||||
def get_queryset(self):
|
||||
try:
|
||||
return self.model.objects.all()
|
||||
|
|
@ -149,7 +152,7 @@ class BaseViewSet(TimezoneMixin, ModelViewSet, BasePaginator):
|
|||
return expand if expand else None
|
||||
|
||||
|
||||
class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
|
||||
class BaseAPIView(TimezoneMixin, ReadReplicaControlMixin, APIView, BasePaginator):
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
filter_backends = (DjangoFilterBackend, SearchFilter)
|
||||
|
|
@ -160,6 +163,8 @@ class BaseAPIView(TimezoneMixin, APIView, BasePaginator):
|
|||
|
||||
search_fields = []
|
||||
|
||||
use_read_replica = False
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
for backend in list(self.filter_backends):
|
||||
queryset = backend().filter_queryset(self.request, queryset, self)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ from plane.db.models import IssueActivity, IssueComment, CommentReaction, Intake
|
|||
|
||||
class IssueActivityEndpoint(BaseAPIView):
|
||||
permission_classes = [ProjectEntityPermission]
|
||||
use_read_replica = True
|
||||
|
||||
@method_decorator(gzip_page)
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
|
|
|
|||
|
|
@ -232,6 +232,8 @@ class NotificationViewSet(BaseViewSet, BasePaginator):
|
|||
|
||||
|
||||
class UnreadNotificationEndpoint(BaseAPIView):
|
||||
use_read_replica = True
|
||||
|
||||
@allow_permission(
|
||||
allowed_roles=[ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST], level="WORKSPACE"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class ProjectViewSet(BaseViewSet):
|
|||
serializer_class = ProjectListSerializer
|
||||
model = Project
|
||||
webhook_event = "project"
|
||||
use_read_replica = True
|
||||
|
||||
def get_queryset(self):
|
||||
sort_order = ProjectMember.objects.filter(
|
||||
|
|
|
|||
|
|
@ -312,6 +312,7 @@ class ProjectMemberUserEndpoint(BaseAPIView):
|
|||
|
||||
class UserProjectRolesEndpoint(BaseAPIView):
|
||||
permission_classes = [WorkspaceUserPermission]
|
||||
use_read_replica = True
|
||||
|
||||
def get(self, request, slug):
|
||||
project_members = ProjectMember.objects.filter(
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ from django.views.decorators.vary import vary_on_cookie
|
|||
class UserEndpoint(BaseViewSet):
|
||||
serializer_class = UserSerializer
|
||||
model = User
|
||||
use_read_replica = True
|
||||
|
||||
def get_object(self):
|
||||
return self.request.user
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ class WorkSpaceViewSet(BaseViewSet):
|
|||
class UserWorkSpacesEndpoint(BaseAPIView):
|
||||
search_fields = ["name"]
|
||||
filterset_fields = ["owner"]
|
||||
use_read_replica = True
|
||||
|
||||
def get(self, request):
|
||||
fields = [field for field in request.GET.get("fields", "").split(",") if field]
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from plane.utils.cache import cache_response
|
|||
|
||||
class WorkspaceEstimatesEndpoint(BaseAPIView):
|
||||
permission_classes = [WorkspaceEntityPermission]
|
||||
use_read_replica = True
|
||||
|
||||
@cache_response(60 * 60 * 2)
|
||||
def get(self, request, slug):
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ from plane.app.permissions import allow_permission, ROLE
|
|||
|
||||
|
||||
class WorkspaceFavoriteEndpoint(BaseAPIView):
|
||||
use_read_replica = True
|
||||
|
||||
@allow_permission(allowed_roles=[ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
|
||||
def get(self, request, slug):
|
||||
# the second filter is to check if the user is a member of the project
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from plane.utils.cache import cache_response
|
|||
|
||||
class WorkspaceLabelsEndpoint(BaseAPIView):
|
||||
permission_classes = [WorkspaceViewerPermission]
|
||||
use_read_replica = True
|
||||
|
||||
@cache_response(60 * 60 * 2)
|
||||
def get(self, request, slug):
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
|||
model = WorkspaceMember
|
||||
|
||||
search_fields = ["member__display_name", "member__first_name"]
|
||||
use_read_replica = True
|
||||
|
||||
def get_queryset(self):
|
||||
return self.filter_queryset(
|
||||
|
|
@ -214,6 +215,8 @@ class WorkspaceMemberUserViewsEndpoint(BaseAPIView):
|
|||
|
||||
|
||||
class WorkspaceMemberUserEndpoint(BaseAPIView):
|
||||
use_read_replica = True
|
||||
|
||||
def get(self, request, slug):
|
||||
draft_issue_count = (
|
||||
DraftIssue.objects.filter(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from plane.app.permissions import allow_permission, ROLE
|
|||
|
||||
class QuickLinkViewSet(BaseViewSet):
|
||||
model = WorkspaceUserLink
|
||||
use_read_replica = True
|
||||
|
||||
def get_serializer_class(self):
|
||||
return WorkspaceUserLinkSerializer
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from plane.app.permissions import allow_permission, ROLE
|
|||
|
||||
class UserRecentVisitViewSet(BaseViewSet):
|
||||
model = UserRecentVisit
|
||||
use_read_replica = True
|
||||
|
||||
def get_serializer_class(self):
|
||||
return WorkspaceRecentVisitSerializer
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from collections import defaultdict
|
|||
|
||||
class WorkspaceStatesEndpoint(BaseAPIView):
|
||||
permission_classes = [WorkspaceEntityPermission]
|
||||
use_read_replica = True
|
||||
|
||||
@cache_response(60 * 60 * 2)
|
||||
def get(self, request, slug):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ from plane.app.serializers import StickySerializer
|
|||
class WorkspaceStickyViewSet(BaseViewSet):
|
||||
serializer_class = StickySerializer
|
||||
model = Sticky
|
||||
use_read_replica = True
|
||||
|
||||
def get_queryset(self):
|
||||
return self.filter_queryset(
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from rest_framework import status
|
|||
|
||||
class WorkspaceUserPreferenceViewSet(BaseAPIView):
|
||||
model = WorkspaceUserPreference
|
||||
use_read_replica = True
|
||||
|
||||
def get_serializer_class(self):
|
||||
return WorkspaceUserPreferenceSerializer
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue