basic healthcheck and status
This commit is contained in:
parent
03ca49fbe3
commit
8f7f56f3df
4 changed files with 88 additions and 5 deletions
|
|
@ -1,10 +1,48 @@
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from django.utils import timezone
|
||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.views.generic import TemplateView
|
from django.views.generic import TemplateView
|
||||||
|
from oauth2_provider.contrib.rest_framework import IsAuthenticatedOrTokenHasScope
|
||||||
|
from rest_framework import generics
|
||||||
|
from rest_framework.exceptions import APIException, ErrorDetail
|
||||||
|
from rest_framework.permissions import AllowAny
|
||||||
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.views import APIView
|
||||||
|
|
||||||
|
from utils.exceptions import StatusError
|
||||||
|
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
@method_decorator(login_required, name='dispatch')
|
@method_decorator(login_required, name='dispatch')
|
||||||
class HomeView(TemplateView):
|
class HomeView(TemplateView):
|
||||||
template_name = 'core/home.html'
|
template_name = 'core/home.html'
|
||||||
|
|
||||||
|
|
||||||
|
class StatusView(APIView):
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
|
||||||
|
def get(self, request, format=None):
|
||||||
|
if self.request.GET.get('raise_error'):
|
||||||
|
raise StatusError(
|
||||||
|
# code='service_unavailable_at_now',
|
||||||
|
detail={
|
||||||
|
# "code": 'service_unavailable_at_now',
|
||||||
|
"timestamp": timezone.now().isoformat(),
|
||||||
|
"message": "برخی سرویسهای خارجی در دسترس نیستند لطفا بعدا تلاش کنید"
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"status": "ok",
|
||||||
|
}
|
||||||
|
return Response(data)
|
||||||
|
|
||||||
|
|
||||||
|
class HealthcheckView(APIView):
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
def get(self, request, format=None):
|
||||||
|
data = {
|
||||||
|
"is_healthy": True
|
||||||
|
}
|
||||||
|
return Response(data)
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@ class GatewayChoise(TextChoices):
|
||||||
SEP = 'sep', _('sep')
|
SEP = 'sep', _('sep')
|
||||||
|
|
||||||
|
|
||||||
|
class GatewayPolicy(BasePGModel):
|
||||||
|
application = models.ForeignKey(oauth2_settings.APPLICATION_MODEL, on_delete=models.PROTECT,
|
||||||
|
related_name='+', null=True, blank=True, unique=True)
|
||||||
|
preference_gateway = models.JSONField(default=list, blank=True)
|
||||||
|
|
||||||
|
|
||||||
# TODO: use generic relation
|
# TODO: use generic relation
|
||||||
class PaymentRequest(models.Model):
|
class PaymentRequest(models.Model):
|
||||||
id = None
|
id = None
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from .views import PaymentRequestView, PaymentRequestCreateApiView, PaymentConfirmView, \
|
from .views import PaymentRequestView, PaymentRequestCreateApiView, PaymentConfirmView, \
|
||||||
ApplicationPaymentRequestCreateApiView, CalculateCommissionView
|
ApplicationPaymentRequestCreateApiView, CalculateCommissionView
|
||||||
|
from ..core.views import HealthcheckView, StatusView
|
||||||
|
|
||||||
app_name = "pg"
|
app_name = "pg"
|
||||||
|
|
||||||
|
|
@ -10,4 +11,8 @@ urlpatterns = [
|
||||||
path('api/charge_create/', PaymentRequestCreateApiView.as_view(), name='charge-request-create-api-view'),
|
path('api/charge_create/', PaymentRequestCreateApiView.as_view(), name='charge-request-create-api-view'),
|
||||||
path('api/application/charge_create/<uuid>', ApplicationPaymentRequestCreateApiView.as_view(), name='application-user-charge-request-create-api-view'),
|
path('api/application/charge_create/<uuid>', ApplicationPaymentRequestCreateApiView.as_view(), name='application-user-charge-request-create-api-view'),
|
||||||
path('api/calculate_commission/', CalculateCommissionView.as_view(), name='calculate-commission-view'),
|
path('api/calculate_commission/', CalculateCommissionView.as_view(), name='calculate-commission-view'),
|
||||||
|
path('api/healthcheck', HealthcheckView.as_view(), name='healthcheck-view'),
|
||||||
|
path('api/status', StatusView.as_view(), name='status-view'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,34 @@ def exception_handler(exc, context):
|
||||||
response = drf_exception_handler(exc, context)
|
response = drf_exception_handler(exc, context)
|
||||||
|
|
||||||
if response is not None:
|
if response is not None:
|
||||||
# ساختار دلخواه خود را تعریف میکنیم
|
try:
|
||||||
|
if isinstance(exc.detail, dict):
|
||||||
|
if 'code' in exc.detail:
|
||||||
|
error_code = exc.detail['code']
|
||||||
|
else:
|
||||||
|
attr = next(iter(exc.detail))
|
||||||
|
error_code = exc.detail[attr].code
|
||||||
|
else:
|
||||||
|
error_code = exc.detail.code or exc.code
|
||||||
|
except:
|
||||||
|
error_code = ''
|
||||||
response_data = {
|
response_data = {
|
||||||
'success': False,
|
'success': False,
|
||||||
'status_code': response.status_code,
|
'status_code': response.status_code,
|
||||||
'message': 'An error occurred',
|
'error_code': error_code,
|
||||||
'details': {}
|
'message': str(exc),
|
||||||
|
'details': exc.detail,
|
||||||
}
|
}
|
||||||
|
|
||||||
if isinstance(exc, APIException):
|
if isinstance(exc, APIException):
|
||||||
response_data['message'] = exc.detail if isinstance(exc.detail, str) else "Validation error"
|
if isinstance(exc.detail, str):
|
||||||
|
message = exc.detail
|
||||||
|
elif isinstance(exc.detail, dict) and ('message' in exc.detail or 'string' in exc.detail):
|
||||||
|
message = exc.detail.get('message') or exc.detail.get('string')
|
||||||
|
else:
|
||||||
|
message = error_code
|
||||||
|
|
||||||
|
response_data['message'] = message
|
||||||
response_data['details'] = exc.detail if isinstance(exc.detail, dict) else {}
|
response_data['details'] = exc.detail if isinstance(exc.detail, dict) else {}
|
||||||
|
|
||||||
response.data = response_data
|
response.data = response_data
|
||||||
|
|
@ -44,8 +62,24 @@ class ErrorMiddleware:
|
||||||
{
|
{
|
||||||
"success": False,
|
"success": False,
|
||||||
"status_code": 500,
|
"status_code": 500,
|
||||||
|
'error_code': 500,
|
||||||
"message": "Internal server error",
|
"message": "Internal server error",
|
||||||
"details": str(exception) # فقط در حالت توسعه! در تولید بهتر است لاگ شود.
|
"details": str(exception) # فقط در حالت توسعه! در تولید بهتر است لاگ شود.
|
||||||
},
|
},
|
||||||
status=500
|
status=500
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from rest_framework.exceptions import APIException
|
||||||
|
from rest_framework import status
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class UnprocessableEntity(APIException):
|
||||||
|
status_code = 422
|
||||||
|
default_detail = 'The request was well-formed but cannot be processed due to semantic errors.'
|
||||||
|
default_code = 'unprocessable_entity'
|
||||||
|
|
||||||
|
class StatusError(APIException):
|
||||||
|
status_code = status.HTTP_503_SERVICE_UNAVAILABLE
|
||||||
|
default_ = _('SERVICE_UNAVAILABLE')
|
||||||
|
default_code = 'service_unavailable'
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue