from celery.result import AsyncResult from drf_spectacular.utils import ( OpenApiExample, OpenApiResponse, extend_schema, inline_serializer, ) from rest_framework import status from rest_framework import serializers as drf_serializers from rest_framework.response import Response from rest_framework.views import APIView from .celery_tasks import sample_task class TaskTriggerView(APIView): """ ثبت و اجرای تسک. POST با بدنه اختیاری: {"duration": 3} - مدت زمان تسک به ثانیه. """ @extend_schema( tags=["Tasks"], summary="ثبت و اجرای تسک", description="یک تسک نمونه را در صف Celery قرار می‌دهد.", request=inline_serializer( name="TaskTriggerRequest", fields={ "duration": drf_serializers.IntegerField( required=False, default=1, help_text="مدت زمان تسک به ثانیه (۱–۶۰)" ), }, ), responses={ 200: inline_serializer( name="TaskTriggerResponse", fields={ "code": drf_serializers.IntegerField(), "msg": drf_serializers.CharField(), "data": inline_serializer( name="TaskTriggerData", fields={ "task_id": drf_serializers.CharField(), }, ), }, ), }, examples=[ OpenApiExample( "نمونه درخواست", value={"duration": 3}, request_only=True, ), OpenApiExample( "نمونه پاسخ", value={"code": 200, "msg": "success", "data": {"task_id": "abc123-def456"}}, response_only=True, ), ], ) def post(self, request): duration = request.data.get("duration", 1) try: duration = int(duration) duration = max(1, min(duration, 60)) except (TypeError, ValueError): duration = 1 result = sample_task.delay(duration) return Response( {"code": 200, "msg": "success", "data": {"task_id": result.id}}, status=status.HTTP_200_OK, ) class TaskStatusView(APIView): """ وضعیت تسک بر اساس task_id. GET /api/tasks//status/ """ @extend_schema( tags=["Tasks"], summary="وضعیت تسک", description="وضعیت یک تسک Celery را بر اساس task_id برمی‌گرداند.", responses={ 200: inline_serializer( name="TaskStatusResponse", fields={ "code": drf_serializers.IntegerField(), "msg": drf_serializers.CharField(), "data": inline_serializer( name="TaskStatusData", fields={ "task_id": drf_serializers.CharField(), "status": drf_serializers.CharField(), "message": drf_serializers.CharField(required=False), "progress": drf_serializers.DictField(required=False), "result": drf_serializers.JSONField(required=False), "error": drf_serializers.CharField(required=False), }, ), }, ), }, examples=[ OpenApiExample( "تسک موفق", value={"code": 200, "msg": "success", "data": {"task_id": "abc123", "status": "SUCCESS", "result": "done"}}, response_only=True, ), ], ) def get(self, request, task_id): result = AsyncResult(task_id) state = result.state data = {"task_id": task_id, "status": state} if state == "PENDING": data["message"] = "تسک در صف یا یافت نشد." elif state == "PROGRESS": data["progress"] = result.info elif state == "SUCCESS": data["result"] = result.result elif state == "FAILURE": data["error"] = str(result.result) return Response( {"code": 200, "msg": "success", "data": data}, status=status.HTTP_200_OK, )