django-cfg 1.3.9__py3-none-any.whl → 1.3.11__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/payments/admin/networks_admin.py +12 -1
  3. django_cfg/apps/payments/admin/payments_admin.py +13 -0
  4. django_cfg/apps/payments/admin_interface/serializers/payment_serializers.py +62 -14
  5. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_card.html +121 -0
  6. django_cfg/apps/payments/admin_interface/templates/payments/components/payment_qr_code.html +95 -0
  7. django_cfg/apps/payments/admin_interface/templates/payments/components/progress_bar.html +37 -0
  8. django_cfg/apps/payments/admin_interface/templates/payments/components/provider_stats.html +60 -0
  9. django_cfg/apps/payments/admin_interface/templates/payments/components/status_badge.html +41 -0
  10. django_cfg/apps/payments/admin_interface/templates/payments/components/status_overview.html +83 -0
  11. django_cfg/apps/payments/admin_interface/templates/payments/payment_detail.html +363 -0
  12. django_cfg/apps/payments/admin_interface/templates/payments/payment_form.html +33 -3
  13. django_cfg/apps/payments/admin_interface/views/api/payments.py +102 -0
  14. django_cfg/apps/payments/admin_interface/views/api/webhook_admin.py +96 -45
  15. django_cfg/apps/payments/admin_interface/views/forms.py +5 -1
  16. django_cfg/apps/payments/config/__init__.py +14 -15
  17. django_cfg/apps/payments/config/django_cfg_integration.py +59 -1
  18. django_cfg/apps/payments/config/helpers.py +8 -13
  19. django_cfg/apps/payments/migrations/0001_initial.py +33 -46
  20. django_cfg/apps/payments/migrations/0002_rename_payments_un_user_id_7f6e79_idx_payments_un_user_id_8ce187_idx_and_more.py +46 -0
  21. django_cfg/apps/payments/migrations/0003_universalpayment_status_changed_at.py +25 -0
  22. django_cfg/apps/payments/models/managers/payment_managers.py +142 -25
  23. django_cfg/apps/payments/models/payments.py +94 -0
  24. django_cfg/apps/payments/services/core/base.py +4 -4
  25. django_cfg/apps/payments/services/core/payment_service.py +265 -38
  26. django_cfg/apps/payments/services/providers/base.py +209 -3
  27. django_cfg/apps/payments/services/providers/models/__init__.py +2 -0
  28. django_cfg/apps/payments/services/providers/models/base.py +25 -2
  29. django_cfg/apps/payments/services/providers/nowpayments/models.py +2 -2
  30. django_cfg/apps/payments/services/providers/nowpayments/provider.py +57 -9
  31. django_cfg/apps/payments/services/providers/registry.py +5 -5
  32. django_cfg/apps/payments/services/types/requests.py +19 -7
  33. django_cfg/apps/payments/signals/payment_signals.py +31 -2
  34. django_cfg/apps/payments/static/payments/js/api-client.js +6 -1
  35. django_cfg/apps/payments/static/payments/js/payment-detail.js +167 -0
  36. django_cfg/apps/payments/static/payments/js/payment-form.js +35 -26
  37. django_cfg/apps/payments/templatetags/payment_tags.py +8 -0
  38. django_cfg/apps/payments/urls.py +3 -2
  39. django_cfg/apps/payments/views/api/currencies.py +3 -0
  40. django_cfg/apps/payments/views/serializers/currencies.py +18 -5
  41. django_cfg/apps/tasks/admin/tasks_admin.py +2 -2
  42. django_cfg/apps/tasks/static/tasks/css/dashboard.css +68 -217
  43. django_cfg/apps/tasks/static/tasks/js/api.js +40 -84
  44. django_cfg/apps/tasks/static/tasks/js/components/DataManager.js +24 -0
  45. django_cfg/apps/tasks/static/tasks/js/components/TabManager.js +85 -0
  46. django_cfg/apps/tasks/static/tasks/js/components/TaskRenderer.js +216 -0
  47. django_cfg/apps/tasks/static/tasks/js/dashboard/main.mjs +245 -0
  48. django_cfg/apps/tasks/static/tasks/js/dashboard/overview.mjs +123 -0
  49. django_cfg/apps/tasks/static/tasks/js/dashboard/queues.mjs +120 -0
  50. django_cfg/apps/tasks/static/tasks/js/dashboard/tasks.mjs +350 -0
  51. django_cfg/apps/tasks/static/tasks/js/dashboard/workers.mjs +169 -0
  52. django_cfg/apps/tasks/tasks/__init__.py +10 -0
  53. django_cfg/apps/tasks/tasks/demo_tasks.py +133 -0
  54. django_cfg/apps/tasks/templates/tasks/components/management_actions.html +42 -45
  55. django_cfg/apps/tasks/templates/tasks/components/{status_cards.html → overview_content.html} +30 -11
  56. django_cfg/apps/tasks/templates/tasks/components/queues_content.html +19 -0
  57. django_cfg/apps/tasks/templates/tasks/components/tab_navigation.html +16 -10
  58. django_cfg/apps/tasks/templates/tasks/components/tasks_content.html +51 -0
  59. django_cfg/apps/tasks/templates/tasks/components/workers_content.html +30 -0
  60. django_cfg/apps/tasks/templates/tasks/layout/base.html +117 -0
  61. django_cfg/apps/tasks/templates/tasks/pages/dashboard.html +82 -0
  62. django_cfg/apps/tasks/templates/tasks/partials/task_row_template.html +40 -0
  63. django_cfg/apps/tasks/templates/tasks/widgets/task_filters.html +37 -0
  64. django_cfg/apps/tasks/templates/tasks/widgets/task_footer.html +41 -0
  65. django_cfg/apps/tasks/templates/tasks/widgets/task_table.html +50 -0
  66. django_cfg/apps/tasks/urls.py +2 -2
  67. django_cfg/apps/tasks/urls_admin.py +2 -2
  68. django_cfg/apps/tasks/utils/__init__.py +1 -0
  69. django_cfg/apps/tasks/utils/simulator.py +356 -0
  70. django_cfg/apps/tasks/views/__init__.py +16 -0
  71. django_cfg/apps/tasks/views/api.py +569 -0
  72. django_cfg/apps/tasks/views/dashboard.py +58 -0
  73. django_cfg/core/integration/__init__.py +21 -0
  74. django_cfg/management/commands/rundramatiq_simulator.py +430 -0
  75. django_cfg/models/constance.py +0 -11
  76. django_cfg/models/payments.py +137 -3
  77. django_cfg/modules/django_tasks.py +54 -21
  78. django_cfg/registry/core.py +4 -9
  79. django_cfg/template_archive/django_sample.zip +0 -0
  80. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/METADATA +2 -2
  81. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/RECORD +84 -152
  82. django_cfg/apps/payments/config/constance/__init__.py +0 -22
  83. django_cfg/apps/payments/config/constance/config_service.py +0 -123
  84. django_cfg/apps/payments/config/constance/fields.py +0 -69
  85. django_cfg/apps/payments/config/constance/settings.py +0 -160
  86. django_cfg/apps/payments/migrations/0002_currency_usd_rate_currency_usd_rate_updated_at.py +0 -26
  87. django_cfg/apps/payments/migrations/0003_remove_provider_currency_fields.py +0 -28
  88. django_cfg/apps/payments/migrations/0004_add_reserved_usd_field.py +0 -30
  89. django_cfg/apps/tasks/static/tasks/js/dashboard.js +0 -614
  90. django_cfg/apps/tasks/static/tasks/js/modals.js +0 -452
  91. django_cfg/apps/tasks/static/tasks/js/notifications.js +0 -144
  92. django_cfg/apps/tasks/static/tasks/js/task-monitor.js +0 -454
  93. django_cfg/apps/tasks/static/tasks/js/theme.js +0 -77
  94. django_cfg/apps/tasks/templates/tasks/base.html +0 -96
  95. django_cfg/apps/tasks/templates/tasks/components/info_cards.html +0 -85
  96. django_cfg/apps/tasks/templates/tasks/components/overview_tab.html +0 -22
  97. django_cfg/apps/tasks/templates/tasks/components/queues_tab.html +0 -19
  98. django_cfg/apps/tasks/templates/tasks/components/task_details_modal.html +0 -103
  99. django_cfg/apps/tasks/templates/tasks/components/tasks_tab.html +0 -32
  100. django_cfg/apps/tasks/templates/tasks/components/workers_tab.html +0 -29
  101. django_cfg/apps/tasks/templates/tasks/dashboard.html +0 -29
  102. django_cfg/apps/tasks/views.py +0 -461
  103. django_cfg/management/commands/app_agent_diagnose.py +0 -470
  104. django_cfg/management/commands/app_agent_generate.py +0 -342
  105. django_cfg/management/commands/app_agent_info.py +0 -308
  106. django_cfg/management/commands/auto_generate.py +0 -486
  107. django_cfg/modules/django_app_agent/__init__.py +0 -87
  108. django_cfg/modules/django_app_agent/agents/__init__.py +0 -40
  109. django_cfg/modules/django_app_agent/agents/base/__init__.py +0 -24
  110. django_cfg/modules/django_app_agent/agents/base/agent.py +0 -354
  111. django_cfg/modules/django_app_agent/agents/base/context.py +0 -236
  112. django_cfg/modules/django_app_agent/agents/base/executor.py +0 -430
  113. django_cfg/modules/django_app_agent/agents/generation/__init__.py +0 -12
  114. django_cfg/modules/django_app_agent/agents/generation/app_generator/__init__.py +0 -15
  115. django_cfg/modules/django_app_agent/agents/generation/app_generator/config_validator.py +0 -147
  116. django_cfg/modules/django_app_agent/agents/generation/app_generator/main.py +0 -99
  117. django_cfg/modules/django_app_agent/agents/generation/app_generator/models.py +0 -32
  118. django_cfg/modules/django_app_agent/agents/generation/app_generator/prompt_manager.py +0 -290
  119. django_cfg/modules/django_app_agent/agents/interfaces.py +0 -376
  120. django_cfg/modules/django_app_agent/core/__init__.py +0 -33
  121. django_cfg/modules/django_app_agent/core/config.py +0 -300
  122. django_cfg/modules/django_app_agent/core/exceptions.py +0 -359
  123. django_cfg/modules/django_app_agent/models/__init__.py +0 -71
  124. django_cfg/modules/django_app_agent/models/base.py +0 -283
  125. django_cfg/modules/django_app_agent/models/context.py +0 -496
  126. django_cfg/modules/django_app_agent/models/enums.py +0 -481
  127. django_cfg/modules/django_app_agent/models/requests.py +0 -500
  128. django_cfg/modules/django_app_agent/models/responses.py +0 -585
  129. django_cfg/modules/django_app_agent/pytest.ini +0 -6
  130. django_cfg/modules/django_app_agent/services/__init__.py +0 -42
  131. django_cfg/modules/django_app_agent/services/app_generator/__init__.py +0 -30
  132. django_cfg/modules/django_app_agent/services/app_generator/ai_integration.py +0 -133
  133. django_cfg/modules/django_app_agent/services/app_generator/context.py +0 -40
  134. django_cfg/modules/django_app_agent/services/app_generator/main.py +0 -202
  135. django_cfg/modules/django_app_agent/services/app_generator/structure.py +0 -316
  136. django_cfg/modules/django_app_agent/services/app_generator/validation.py +0 -125
  137. django_cfg/modules/django_app_agent/services/base.py +0 -437
  138. django_cfg/modules/django_app_agent/services/context_builder/__init__.py +0 -34
  139. django_cfg/modules/django_app_agent/services/context_builder/code_extractor.py +0 -141
  140. django_cfg/modules/django_app_agent/services/context_builder/context_generator.py +0 -276
  141. django_cfg/modules/django_app_agent/services/context_builder/main.py +0 -272
  142. django_cfg/modules/django_app_agent/services/context_builder/models.py +0 -40
  143. django_cfg/modules/django_app_agent/services/context_builder/pattern_analyzer.py +0 -85
  144. django_cfg/modules/django_app_agent/services/project_scanner/__init__.py +0 -31
  145. django_cfg/modules/django_app_agent/services/project_scanner/app_discovery.py +0 -311
  146. django_cfg/modules/django_app_agent/services/project_scanner/main.py +0 -221
  147. django_cfg/modules/django_app_agent/services/project_scanner/models.py +0 -59
  148. django_cfg/modules/django_app_agent/services/project_scanner/pattern_detection.py +0 -94
  149. django_cfg/modules/django_app_agent/services/questioning_service/__init__.py +0 -28
  150. django_cfg/modules/django_app_agent/services/questioning_service/main.py +0 -273
  151. django_cfg/modules/django_app_agent/services/questioning_service/models.py +0 -111
  152. django_cfg/modules/django_app_agent/services/questioning_service/question_generator.py +0 -251
  153. django_cfg/modules/django_app_agent/services/questioning_service/response_processor.py +0 -347
  154. django_cfg/modules/django_app_agent/services/questioning_service/session_manager.py +0 -356
  155. django_cfg/modules/django_app_agent/services/report_service.py +0 -332
  156. django_cfg/modules/django_app_agent/services/template_manager/__init__.py +0 -18
  157. django_cfg/modules/django_app_agent/services/template_manager/jinja_engine.py +0 -236
  158. django_cfg/modules/django_app_agent/services/template_manager/main.py +0 -159
  159. django_cfg/modules/django_app_agent/services/template_manager/models.py +0 -36
  160. django_cfg/modules/django_app_agent/services/template_manager/template_loader.py +0 -100
  161. django_cfg/modules/django_app_agent/services/template_manager/templates/admin.py.j2 +0 -105
  162. django_cfg/modules/django_app_agent/services/template_manager/templates/apps.py.j2 +0 -31
  163. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_config.py.j2 +0 -44
  164. django_cfg/modules/django_app_agent/services/template_manager/templates/cfg_module.py.j2 +0 -81
  165. django_cfg/modules/django_app_agent/services/template_manager/templates/forms.py.j2 +0 -107
  166. django_cfg/modules/django_app_agent/services/template_manager/templates/models.py.j2 +0 -139
  167. django_cfg/modules/django_app_agent/services/template_manager/templates/serializers.py.j2 +0 -91
  168. django_cfg/modules/django_app_agent/services/template_manager/templates/tests.py.j2 +0 -195
  169. django_cfg/modules/django_app_agent/services/template_manager/templates/urls.py.j2 +0 -35
  170. django_cfg/modules/django_app_agent/services/template_manager/templates/views.py.j2 +0 -211
  171. django_cfg/modules/django_app_agent/services/template_manager/variable_processor.py +0 -200
  172. django_cfg/modules/django_app_agent/services/validation_service/__init__.py +0 -25
  173. django_cfg/modules/django_app_agent/services/validation_service/django_validator.py +0 -333
  174. django_cfg/modules/django_app_agent/services/validation_service/main.py +0 -242
  175. django_cfg/modules/django_app_agent/services/validation_service/models.py +0 -66
  176. django_cfg/modules/django_app_agent/services/validation_service/quality_validator.py +0 -352
  177. django_cfg/modules/django_app_agent/services/validation_service/security_validator.py +0 -272
  178. django_cfg/modules/django_app_agent/services/validation_service/syntax_validator.py +0 -203
  179. django_cfg/modules/django_app_agent/ui/__init__.py +0 -25
  180. django_cfg/modules/django_app_agent/ui/cli.py +0 -419
  181. django_cfg/modules/django_app_agent/ui/rich_components.py +0 -622
  182. django_cfg/modules/django_app_agent/utils/__init__.py +0 -38
  183. django_cfg/modules/django_app_agent/utils/logging.py +0 -360
  184. django_cfg/modules/django_app_agent/utils/validation.py +0 -417
  185. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/WHEEL +0 -0
  186. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/entry_points.txt +0 -0
  187. {django_cfg-1.3.9.dist-info → django_cfg-1.3.11.dist-info}/licenses/LICENSE +0 -0
@@ -1,461 +0,0 @@
1
- """
2
- Views for Django CFG Tasks app.
3
-
4
- Provides DRF ViewSets for task management with nested router structure.
5
- """
6
-
7
- import logging
8
- from typing import Dict, Any
9
-
10
- from django.shortcuts import render
11
- from rest_framework import viewsets, status
12
- from rest_framework.response import Response
13
- from rest_framework.permissions import IsAdminUser
14
- from rest_framework.authentication import SessionAuthentication, BasicAuthentication
15
- from rest_framework.decorators import action
16
- from drf_spectacular.utils import extend_schema, OpenApiResponse, OpenApiParameter
17
-
18
- from ...modules.django_tasks import DjangoTasks
19
- from .serializers import (
20
- QueueStatusSerializer,
21
- TaskStatisticsSerializer,
22
- WorkerActionSerializer,
23
- QueueActionSerializer,
24
- APIResponseSerializer
25
- )
26
-
27
- logger = logging.getLogger(__name__)
28
-
29
-
30
- class TaskManagementViewSet(viewsets.GenericViewSet):
31
- """
32
- Main ViewSet for comprehensive task management.
33
-
34
- Provides all task-related operations in a single ViewSet with nested actions.
35
- """
36
-
37
- authentication_classes = [SessionAuthentication, BasicAuthentication]
38
- permission_classes = [IsAdminUser]
39
- serializer_class = APIResponseSerializer # Default serializer for the viewset
40
-
41
- def get_serializer_class(self):
42
- """Return the appropriate serializer class based on the action."""
43
- if self.action == 'queue_status':
44
- return QueueStatusSerializer
45
- elif self.action == 'queue_manage':
46
- return QueueActionSerializer
47
- elif self.action == 'worker_manage':
48
- return WorkerActionSerializer
49
- elif self.action == 'task_statistics':
50
- return TaskStatisticsSerializer
51
- return super().get_serializer_class()
52
-
53
- def get_tasks_service(self):
54
- """Get DjangoTasks service instance."""
55
- return DjangoTasks()
56
-
57
- @action(detail=False, methods=['get'], url_path='queues/status')
58
- @extend_schema(
59
- summary="Get queue status",
60
- description="Retrieve current status of all task queues including pending and failed counts",
61
- responses={
62
- 200: OpenApiResponse(response=QueueStatusSerializer, description="Queue status retrieved successfully"),
63
- 500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
64
- },
65
- tags=["Task Management"]
66
- )
67
- def queue_status(self, request):
68
- """Get current queue status."""
69
- try:
70
- tasks_service = self.get_tasks_service()
71
- status_data = self._get_queue_status(tasks_service)
72
-
73
- return Response({
74
- 'success': True,
75
- 'data': status_data
76
- })
77
-
78
- except Exception as e:
79
- logger.error(f"Queue status API error: {e}")
80
- return Response({
81
- 'success': False,
82
- 'error': str(e)
83
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
84
-
85
- @action(detail=False, methods=['post'], url_path='queues/manage')
86
- @extend_schema(
87
- summary="Manage queues",
88
- description="Clear, purge, or flush task queues",
89
- request=QueueActionSerializer,
90
- responses={
91
- 200: OpenApiResponse(response=APIResponseSerializer, description="Queue action completed successfully"),
92
- 400: OpenApiResponse(response=APIResponseSerializer, description="Invalid request data"),
93
- 500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
94
- },
95
- tags=["Task Management"]
96
- )
97
- def queue_manage(self, request):
98
- """Manage task queues."""
99
- serializer = QueueActionSerializer(data=request.data)
100
- serializer.is_valid(raise_exception=True)
101
-
102
- try:
103
- action = serializer.validated_data['action']
104
- queue_names = serializer.validated_data.get('queue_names', [])
105
-
106
- # TODO: Implement actual queue management
107
- target = f"queues: {', '.join(queue_names)}" if queue_names else "all queues"
108
- message = f"Queue {action} command sent for {target}"
109
-
110
- return Response({
111
- 'success': True,
112
- 'message': message
113
- })
114
-
115
- except Exception as e:
116
- logger.error(f"Queue management API error: {e}")
117
- return Response({
118
- 'success': False,
119
- 'error': str(e)
120
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
121
-
122
- @action(detail=False, methods=['post'], url_path='workers/manage')
123
- @extend_schema(
124
- summary="Manage workers",
125
- description="Start, stop, or restart Dramatiq workers",
126
- request=WorkerActionSerializer,
127
- responses={
128
- 200: OpenApiResponse(response=APIResponseSerializer, description="Worker action completed successfully"),
129
- 400: OpenApiResponse(response=APIResponseSerializer, description="Invalid request data"),
130
- 500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
131
- },
132
- tags=["Task Management"]
133
- )
134
- def worker_manage(self, request):
135
- """Manage worker processes."""
136
- serializer = WorkerActionSerializer(data=request.data)
137
- serializer.is_valid(raise_exception=True)
138
-
139
- try:
140
- action = serializer.validated_data['action']
141
- processes = serializer.validated_data.get('processes', 1)
142
- threads = serializer.validated_data.get('threads', 2)
143
-
144
- # TODO: Implement actual worker management
145
- message = f"Worker {action} command sent (processes: {processes}, threads: {threads})"
146
-
147
- return Response({
148
- 'success': True,
149
- 'message': message
150
- })
151
-
152
- except Exception as e:
153
- logger.error(f"Worker management API error: {e}")
154
- return Response({
155
- 'success': False,
156
- 'error': str(e)
157
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
158
-
159
- @action(detail=False, methods=['get'], url_path='tasks/stats')
160
- @extend_schema(
161
- summary="Get task statistics",
162
- description="Retrieve task execution statistics and recent task history",
163
- responses={
164
- 200: OpenApiResponse(response=TaskStatisticsSerializer, description="Task statistics retrieved successfully"),
165
- 500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
166
- },
167
- tags=["Task Management"]
168
- )
169
- def task_stats(self, request):
170
- """Get task execution statistics."""
171
- try:
172
- tasks_service = self.get_tasks_service()
173
- stats_data = self._get_task_statistics(tasks_service)
174
-
175
- return Response({
176
- 'success': True,
177
- 'data': stats_data
178
- })
179
-
180
- except Exception as e:
181
- logger.error(f"Task stats API error: {e}")
182
- return Response({
183
- 'success': False,
184
- 'error': str(e)
185
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
186
-
187
- @action(detail=False, methods=['get'], url_path='tasks/list')
188
- @extend_schema(
189
- summary="Get detailed task list",
190
- description="Get detailed list of all tasks with filtering options",
191
- parameters=[
192
- OpenApiParameter(name='status', description='Filter by task status', required=False, type=str),
193
- OpenApiParameter(name='queue', description='Filter by queue name', required=False, type=str),
194
- OpenApiParameter(name='search', description='Search in task names', required=False, type=str),
195
- OpenApiParameter(name='limit', description='Limit number of results', required=False, type=int),
196
- OpenApiParameter(name='offset', description='Offset for pagination', required=False, type=int),
197
- ],
198
- responses={
199
- 200: OpenApiResponse(response=APIResponseSerializer, description="Task list retrieved successfully"),
200
- 500: OpenApiResponse(response=APIResponseSerializer, description="Internal server error")
201
- },
202
- tags=["Task Management"]
203
- )
204
- def task_list(self, request):
205
- """Get detailed task list with filtering."""
206
- try:
207
- tasks_service = self.get_tasks_service()
208
- data = self._get_detailed_task_list(tasks_service, request.query_params)
209
-
210
- return Response({
211
- 'success': True,
212
- 'data': data
213
- })
214
-
215
- except Exception as e:
216
- logger.error(f"Task list API error: {e}")
217
- return Response({
218
- 'success': False,
219
- 'error': str(e)
220
- }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
221
-
222
- def _get_queue_status(self, tasks_service: DjangoTasks) -> Dict[str, Any]:
223
- """Get current queue status."""
224
- try:
225
- redis_client = tasks_service.get_redis_client()
226
-
227
- if not redis_client:
228
- return {
229
- 'error': 'Redis connection not available',
230
- 'queues': {},
231
- 'workers': 0,
232
- 'redis_connected': False,
233
- 'timestamp': tasks_service._get_current_timestamp()
234
- }
235
-
236
- # Get queue information
237
- queues_info = {}
238
- config = tasks_service.config
239
-
240
- if config and config.dramatiq and config.dramatiq.queues:
241
- for queue_name in config.dramatiq.queues:
242
- # Try different queue key patterns
243
- queue_keys = [
244
- f"dramatiq:queue:{queue_name}",
245
- f"dramatiq:default.DQ.{queue_name}",
246
- f"dramatiq:{queue_name}"
247
- ]
248
-
249
- queue_length = 0
250
- failed_length = 0
251
-
252
- # Check for pending tasks
253
- for queue_key in queue_keys:
254
- length = redis_client.llen(queue_key)
255
- if length > 0:
256
- queue_length = length
257
- break
258
-
259
- # Check for failed tasks
260
- failed_keys = [
261
- f"dramatiq:queue:{queue_name}.failed",
262
- f"dramatiq:default.DQ.{queue_name}.failed",
263
- f"dramatiq:{queue_name}.failed"
264
- ]
265
-
266
- for failed_key in failed_keys:
267
- length = redis_client.llen(failed_key)
268
- if length > 0:
269
- failed_length = length
270
- break
271
-
272
- queues_info[queue_name] = {
273
- 'pending': queue_length,
274
- 'failed': failed_length,
275
- 'total': queue_length + failed_length
276
- }
277
-
278
- # Get worker information
279
- worker_keys = redis_client.keys("dramatiq:worker:*")
280
- active_workers = len(worker_keys) if worker_keys else 0
281
-
282
- return {
283
- 'queues': queues_info,
284
- 'workers': active_workers,
285
- 'redis_connected': True,
286
- 'timestamp': tasks_service._get_current_timestamp()
287
- }
288
-
289
- except Exception as e:
290
- logger.error(f"Queue status error: {e}")
291
- return {
292
- 'error': str(e),
293
- 'queues': {},
294
- 'workers': 0,
295
- 'redis_connected': False,
296
- 'timestamp': tasks_service._get_current_timestamp()
297
- }
298
-
299
- def _get_task_statistics(self, tasks_service: DjangoTasks) -> Dict[str, Any]:
300
- """Get task execution statistics."""
301
- try:
302
- # Try to import django_dramatiq models
303
- try:
304
- from django_dramatiq.models import Task
305
- from django.db.models import Count
306
-
307
- # Check if Task model has tasks manager (django_dramatiq uses 'tasks' not 'objects')
308
- if not hasattr(Task, 'tasks'):
309
- logger.warning("Task model does not have tasks manager")
310
- return {
311
- 'statistics': {'total': 0},
312
- 'recent_tasks': [],
313
- 'error': 'Task model not properly initialized',
314
- 'timestamp': tasks_service._get_current_timestamp()
315
- }
316
-
317
- # Get task counts by status
318
- stats = Task.tasks.aggregate(
319
- total=Count('id'),
320
- )
321
-
322
- # Get recent tasks
323
- recent_tasks = list(
324
- Task.tasks.order_by('-created_at')[:10]
325
- .values('actor_name', 'status', 'created_at', 'updated_at')
326
- )
327
-
328
- return {
329
- 'statistics': stats,
330
- 'recent_tasks': recent_tasks,
331
- 'timestamp': tasks_service._get_current_timestamp()
332
- }
333
-
334
- except ImportError:
335
- return {
336
- 'error': 'django_dramatiq not available',
337
- 'statistics': {'total': 0},
338
- 'recent_tasks': [],
339
- 'timestamp': tasks_service._get_current_timestamp()
340
- }
341
-
342
- except Exception as e:
343
- logger.error(f"Task statistics error: {e}")
344
- return {
345
- 'error': str(e),
346
- 'statistics': {'total': 0},
347
- 'recent_tasks': [],
348
- 'timestamp': tasks_service._get_current_timestamp()
349
- }
350
-
351
- def _get_detailed_task_list(self, tasks_service: DjangoTasks, query_params) -> Dict[str, Any]:
352
- """Get detailed task list with filtering."""
353
- try:
354
- # Import django_dramatiq models if available
355
- try:
356
- from django_dramatiq.models import Task
357
- from django.db.models import Q
358
-
359
- # Check if Task model has tasks manager
360
- if not hasattr(Task, 'tasks'):
361
- logger.warning("Task model does not have tasks manager")
362
- return {
363
- 'tasks': [],
364
- 'total': 0,
365
- 'error': 'Task model not properly initialized',
366
- 'timestamp': tasks_service._get_current_timestamp()
367
- }
368
-
369
- # Build query
370
- queryset = Task.tasks.all()
371
-
372
- # Apply filters
373
- status_filter = query_params.get('status')
374
- if status_filter:
375
- queryset = queryset.filter(status=status_filter)
376
-
377
- queue_filter = query_params.get('queue')
378
- if queue_filter:
379
- queryset = queryset.filter(queue_name=queue_filter)
380
-
381
- search_filter = query_params.get('search')
382
- if search_filter:
383
- queryset = queryset.filter(
384
- Q(actor_name__icontains=search_filter) |
385
- Q(id__icontains=search_filter)
386
- )
387
-
388
- # Get total count before pagination
389
- total_count = queryset.count()
390
-
391
- # Apply pagination
392
- limit = int(query_params.get('limit', 50))
393
- offset = int(query_params.get('offset', 0))
394
- queryset = queryset.order_by('-created_at')[offset:offset + limit]
395
-
396
- # Convert to list of dictionaries
397
- tasks = []
398
- for task in queryset:
399
- task_data = {
400
- 'id': str(task.id),
401
- 'actor_name': task.actor_name,
402
- 'status': task.status,
403
- 'queue': getattr(task, 'queue_name', 'default'),
404
- 'created_at': task.created_at.isoformat() if task.created_at else None,
405
- 'updated_at': task.updated_at.isoformat() if task.updated_at else None,
406
- 'args': task.args if hasattr(task, 'args') else None,
407
- 'kwargs': task.kwargs if hasattr(task, 'kwargs') else None,
408
- 'result': task.result if hasattr(task, 'result') else None,
409
- 'traceback': task.traceback if hasattr(task, 'traceback') else None,
410
- 'progress': getattr(task, 'progress', None),
411
- }
412
- tasks.append(task_data)
413
-
414
- return {
415
- 'tasks': tasks,
416
- 'total': total_count,
417
- 'limit': limit,
418
- 'offset': offset,
419
- 'timestamp': tasks_service._get_current_timestamp()
420
- }
421
-
422
- except ImportError:
423
- return {
424
- 'error': 'django_dramatiq not available',
425
- 'tasks': [],
426
- 'total': 0,
427
- 'timestamp': tasks_service._get_current_timestamp()
428
- }
429
-
430
- except Exception as e:
431
- logger.error(f"Task list error: {e}")
432
- return {
433
- 'error': str(e),
434
- 'tasks': [],
435
- 'total': 0,
436
- 'timestamp': tasks_service._get_current_timestamp()
437
- }
438
-
439
-
440
-
441
-
442
- def dashboard_view(request):
443
- """Dashboard view for task management."""
444
- try:
445
- # Use main ViewSet to get data
446
- main_viewset = TaskManagementViewSet()
447
- tasks_service = main_viewset.get_tasks_service()
448
-
449
- context = {
450
- 'queue_status': main_viewset._get_queue_status(tasks_service),
451
- 'task_stats': main_viewset._get_task_statistics(tasks_service),
452
- }
453
-
454
- return render(request, 'tasks/dashboard.html', context)
455
-
456
- except Exception as e:
457
- logger.error(f"Dashboard view error: {e}")
458
- context = {
459
- 'error': str(e)
460
- }
461
- return render(request, 'tasks/dashboard.html', context)