django-cfg 1.4.61__py3-none-any.whl → 1.4.63__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.

Potentially problematic release.


This version of django-cfg might be problematic. Click here for more details.

Files changed (179) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/accounts/services/otp_service.py +3 -14
  3. django_cfg/apps/centrifugo/__init__.py +57 -0
  4. django_cfg/apps/centrifugo/admin/__init__.py +13 -0
  5. django_cfg/apps/centrifugo/admin/centrifugo_log.py +249 -0
  6. django_cfg/apps/centrifugo/admin/config.py +82 -0
  7. django_cfg/apps/centrifugo/apps.py +31 -0
  8. django_cfg/apps/centrifugo/codegen/IMPLEMENTATION_SUMMARY.md +475 -0
  9. django_cfg/apps/centrifugo/codegen/README.md +242 -0
  10. django_cfg/apps/centrifugo/codegen/USAGE.md +616 -0
  11. django_cfg/apps/centrifugo/codegen/__init__.py +19 -0
  12. django_cfg/apps/centrifugo/codegen/discovery.py +246 -0
  13. django_cfg/apps/centrifugo/codegen/generators/go_thin/__init__.py +5 -0
  14. django_cfg/apps/centrifugo/codegen/generators/go_thin/generator.py +174 -0
  15. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/README.md.j2 +182 -0
  16. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/client.go.j2 +64 -0
  17. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/go.mod.j2 +10 -0
  18. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2 +300 -0
  19. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/rpc_client.go.j2.old +267 -0
  20. django_cfg/apps/centrifugo/codegen/generators/go_thin/templates/types.go.j2 +16 -0
  21. django_cfg/apps/centrifugo/codegen/generators/python_thin/__init__.py +7 -0
  22. django_cfg/apps/centrifugo/codegen/generators/python_thin/generator.py +241 -0
  23. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/README.md.j2 +128 -0
  24. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/__init__.py.j2 +22 -0
  25. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/client.py.j2 +73 -0
  26. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/models.py.j2 +19 -0
  27. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/requirements.txt.j2 +8 -0
  28. django_cfg/apps/centrifugo/codegen/generators/python_thin/templates/rpc_client.py.j2 +193 -0
  29. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/__init__.py +5 -0
  30. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/generator.py +124 -0
  31. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/README.md.j2 +38 -0
  32. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/client.ts.j2 +25 -0
  33. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/index.ts.j2 +12 -0
  34. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/package.json.j2 +13 -0
  35. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2 +137 -0
  36. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/tsconfig.json.j2 +14 -0
  37. django_cfg/apps/centrifugo/codegen/generators/typescript_thin/templates/types.ts.j2 +9 -0
  38. django_cfg/apps/centrifugo/codegen/utils/__init__.py +37 -0
  39. django_cfg/apps/centrifugo/codegen/utils/naming.py +155 -0
  40. django_cfg/apps/centrifugo/codegen/utils/type_converter.py +349 -0
  41. django_cfg/apps/centrifugo/decorators.py +137 -0
  42. django_cfg/apps/centrifugo/management/__init__.py +1 -0
  43. django_cfg/apps/centrifugo/management/commands/__init__.py +1 -0
  44. django_cfg/apps/centrifugo/management/commands/generate_centrifugo_clients.py +254 -0
  45. django_cfg/apps/centrifugo/managers/__init__.py +12 -0
  46. django_cfg/apps/centrifugo/managers/centrifugo_log.py +264 -0
  47. django_cfg/apps/centrifugo/migrations/0001_initial.py +164 -0
  48. django_cfg/apps/centrifugo/migrations/__init__.py +3 -0
  49. django_cfg/apps/centrifugo/models/__init__.py +11 -0
  50. django_cfg/apps/centrifugo/models/centrifugo_log.py +210 -0
  51. django_cfg/apps/centrifugo/registry.py +106 -0
  52. django_cfg/apps/centrifugo/router.py +125 -0
  53. django_cfg/apps/centrifugo/serializers/__init__.py +40 -0
  54. django_cfg/apps/centrifugo/serializers/admin_api.py +264 -0
  55. django_cfg/apps/centrifugo/serializers/channels.py +26 -0
  56. django_cfg/apps/centrifugo/serializers/health.py +17 -0
  57. django_cfg/apps/centrifugo/serializers/publishes.py +16 -0
  58. django_cfg/apps/centrifugo/serializers/stats.py +21 -0
  59. django_cfg/apps/centrifugo/services/__init__.py +12 -0
  60. django_cfg/apps/centrifugo/services/client/__init__.py +29 -0
  61. django_cfg/apps/centrifugo/services/client/client.py +577 -0
  62. django_cfg/apps/centrifugo/services/client/config.py +228 -0
  63. django_cfg/apps/centrifugo/services/client/exceptions.py +212 -0
  64. django_cfg/apps/centrifugo/services/config_helper.py +63 -0
  65. django_cfg/apps/centrifugo/services/dashboard_notifier.py +157 -0
  66. django_cfg/apps/centrifugo/services/logging.py +677 -0
  67. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/css/dashboard.css +260 -0
  68. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_channels.mjs +313 -0
  69. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/live_testing.mjs +803 -0
  70. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/main.mjs +333 -0
  71. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/overview.mjs +432 -0
  72. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/testing.mjs +33 -0
  73. django_cfg/apps/centrifugo/static/django_cfg_centrifugo/js/dashboard/websocket.mjs +210 -0
  74. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/channels_content.html +46 -0
  75. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/live_channels_content.html +123 -0
  76. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/overview_content.html +45 -0
  77. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/publishes_content.html +84 -0
  78. django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/stat_cards.html +23 -20
  79. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/system_status.html +91 -0
  80. django_cfg/apps/{ipc/templates/django_cfg_ipc → centrifugo/templates/django_cfg_centrifugo}/components/tab_navigation.html +15 -15
  81. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/components/testing_tools.html +415 -0
  82. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/layout/base.html +61 -0
  83. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/pages/dashboard.html +58 -0
  84. django_cfg/apps/centrifugo/templates/django_cfg_centrifugo/tags/connection_script.html +48 -0
  85. django_cfg/apps/centrifugo/templatetags/__init__.py +1 -0
  86. django_cfg/apps/centrifugo/templatetags/centrifugo_tags.py +81 -0
  87. django_cfg/apps/centrifugo/urls.py +31 -0
  88. django_cfg/apps/{ipc → centrifugo}/urls_admin.py +4 -4
  89. django_cfg/apps/centrifugo/views/__init__.py +15 -0
  90. django_cfg/apps/centrifugo/views/admin_api.py +374 -0
  91. django_cfg/apps/centrifugo/views/dashboard.py +15 -0
  92. django_cfg/apps/centrifugo/views/monitoring.py +286 -0
  93. django_cfg/apps/centrifugo/views/testing_api.py +422 -0
  94. django_cfg/apps/support/utils/support_email_service.py +5 -18
  95. django_cfg/apps/tasks/templates/tasks/layout/base.html +0 -2
  96. django_cfg/apps/urls.py +5 -5
  97. django_cfg/core/base/config_model.py +4 -44
  98. django_cfg/core/builders/apps_builder.py +2 -2
  99. django_cfg/core/generation/integration_generators/third_party.py +8 -8
  100. django_cfg/core/utils/__init__.py +5 -0
  101. django_cfg/core/utils/url_helpers.py +73 -0
  102. django_cfg/modules/base.py +7 -7
  103. django_cfg/modules/django_client/core/__init__.py +2 -1
  104. django_cfg/modules/django_client/core/config/config.py +8 -0
  105. django_cfg/modules/django_client/core/generator/__init__.py +42 -2
  106. django_cfg/modules/django_client/core/generator/go/__init__.py +14 -0
  107. django_cfg/modules/django_client/core/generator/go/client_generator.py +124 -0
  108. django_cfg/modules/django_client/core/generator/go/files_generator.py +133 -0
  109. django_cfg/modules/django_client/core/generator/go/generator.py +203 -0
  110. django_cfg/modules/django_client/core/generator/go/models_generator.py +304 -0
  111. django_cfg/modules/django_client/core/generator/go/naming.py +193 -0
  112. django_cfg/modules/django_client/core/generator/go/operations_generator.py +134 -0
  113. django_cfg/modules/django_client/core/generator/go/templates/Makefile.j2 +38 -0
  114. django_cfg/modules/django_client/core/generator/go/templates/README.md.j2 +55 -0
  115. django_cfg/modules/django_client/core/generator/go/templates/client.go.j2 +122 -0
  116. django_cfg/modules/django_client/core/generator/go/templates/enums.go.j2 +49 -0
  117. django_cfg/modules/django_client/core/generator/go/templates/errors.go.j2 +182 -0
  118. django_cfg/modules/django_client/core/generator/go/templates/go.mod.j2 +6 -0
  119. django_cfg/modules/django_client/core/generator/go/templates/main_client.go.j2 +60 -0
  120. django_cfg/modules/django_client/core/generator/go/templates/middleware.go.j2 +388 -0
  121. django_cfg/modules/django_client/core/generator/go/templates/models.go.j2 +28 -0
  122. django_cfg/modules/django_client/core/generator/go/templates/operations_client.go.j2 +142 -0
  123. django_cfg/modules/django_client/core/generator/go/templates/validation.go.j2 +217 -0
  124. django_cfg/modules/django_client/core/generator/go/type_mapper.py +380 -0
  125. django_cfg/modules/django_client/management/commands/generate_client.py +53 -3
  126. django_cfg/modules/django_client/system/generate_mjs_clients.py +3 -1
  127. django_cfg/modules/django_client/system/schema_parser.py +5 -1
  128. django_cfg/modules/django_tailwind/templates/django_tailwind/base.html +1 -0
  129. django_cfg/modules/django_twilio/sendgrid_service.py +7 -4
  130. django_cfg/modules/django_unfold/dashboard.py +25 -19
  131. django_cfg/pyproject.toml +1 -1
  132. django_cfg/registry/core.py +2 -0
  133. django_cfg/registry/modules.py +2 -2
  134. django_cfg/static/js/api/centrifugo/client.mjs +164 -0
  135. django_cfg/static/js/api/centrifugo/index.mjs +13 -0
  136. django_cfg/static/js/api/index.mjs +5 -5
  137. django_cfg/static/js/api/types.mjs +89 -26
  138. {django_cfg-1.4.61.dist-info → django_cfg-1.4.63.dist-info}/METADATA +1 -1
  139. {django_cfg-1.4.61.dist-info → django_cfg-1.4.63.dist-info}/RECORD +142 -68
  140. django_cfg/apps/ipc/README.md +0 -346
  141. django_cfg/apps/ipc/RPC_LOGGING.md +0 -321
  142. django_cfg/apps/ipc/TESTING.md +0 -539
  143. django_cfg/apps/ipc/__init__.py +0 -60
  144. django_cfg/apps/ipc/admin.py +0 -212
  145. django_cfg/apps/ipc/apps.py +0 -28
  146. django_cfg/apps/ipc/migrations/0001_initial.py +0 -137
  147. django_cfg/apps/ipc/migrations/__init__.py +0 -0
  148. django_cfg/apps/ipc/models.py +0 -221
  149. django_cfg/apps/ipc/serializers/__init__.py +0 -29
  150. django_cfg/apps/ipc/serializers/serializers.py +0 -343
  151. django_cfg/apps/ipc/services/__init__.py +0 -7
  152. django_cfg/apps/ipc/services/client/__init__.py +0 -23
  153. django_cfg/apps/ipc/services/client/client.py +0 -621
  154. django_cfg/apps/ipc/services/client/config.py +0 -214
  155. django_cfg/apps/ipc/services/client/exceptions.py +0 -201
  156. django_cfg/apps/ipc/services/logging.py +0 -239
  157. django_cfg/apps/ipc/services/monitor.py +0 -466
  158. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/main.mjs +0 -269
  159. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/overview.mjs +0 -259
  160. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard/testing.mjs +0 -375
  161. django_cfg/apps/ipc/static/django_cfg_ipc/js/dashboard.mjs.old +0 -441
  162. django_cfg/apps/ipc/templates/django_cfg_ipc/components/methods_content.html +0 -22
  163. django_cfg/apps/ipc/templates/django_cfg_ipc/components/notifications_content.html +0 -9
  164. django_cfg/apps/ipc/templates/django_cfg_ipc/components/overview_content.html +0 -9
  165. django_cfg/apps/ipc/templates/django_cfg_ipc/components/requests_content.html +0 -23
  166. django_cfg/apps/ipc/templates/django_cfg_ipc/components/system_status.html +0 -47
  167. django_cfg/apps/ipc/templates/django_cfg_ipc/components/testing_tools.html +0 -184
  168. django_cfg/apps/ipc/templates/django_cfg_ipc/layout/base.html +0 -71
  169. django_cfg/apps/ipc/templates/django_cfg_ipc/pages/dashboard.html +0 -56
  170. django_cfg/apps/ipc/urls.py +0 -23
  171. django_cfg/apps/ipc/views/__init__.py +0 -13
  172. django_cfg/apps/ipc/views/dashboard.py +0 -15
  173. django_cfg/apps/ipc/views/monitoring.py +0 -251
  174. django_cfg/apps/ipc/views/testing.py +0 -285
  175. django_cfg/static/js/api/ipc/client.mjs +0 -114
  176. django_cfg/static/js/api/ipc/index.mjs +0 -13
  177. {django_cfg-1.4.61.dist-info → django_cfg-1.4.63.dist-info}/WHEEL +0 -0
  178. {django_cfg-1.4.61.dist-info → django_cfg-1.4.63.dist-info}/entry_points.txt +0 -0
  179. {django_cfg-1.4.61.dist-info → django_cfg-1.4.63.dist-info}/licenses/LICENSE +0 -0
@@ -1,212 +0,0 @@
1
- """
2
- Django Admin for IPC/RPC models.
3
-
4
- Uses PydanticAdmin with declarative configuration.
5
- """
6
-
7
- import json
8
-
9
- from django.contrib import admin
10
- from django_cfg.modules.django_admin import (
11
- AdminConfig,
12
- BadgeField,
13
- DateTimeField,
14
- Icons,
15
- UserField,
16
- computed_field,
17
- )
18
- from django_cfg.modules.django_admin.base import PydanticAdmin
19
-
20
- from .models import RPCLog
21
-
22
-
23
- # Declarative configuration for RPCLog
24
- rpclog_config = AdminConfig(
25
- model=RPCLog,
26
-
27
- # Performance optimization
28
- select_related=["user"],
29
-
30
- # List display
31
- list_display=[
32
- "method",
33
- "status",
34
- "user",
35
- "duration_ms",
36
- "created_at",
37
- "completed_at"
38
- ],
39
-
40
- # Auto-generated display methods
41
- display_fields=[
42
- BadgeField(
43
- name="method",
44
- title="RPC Method",
45
- variant="info",
46
- icon=Icons.API
47
- ),
48
- BadgeField(
49
- name="status",
50
- title="Status",
51
- label_map={
52
- "pending": "warning",
53
- "success": "success",
54
- "failed": "danger",
55
- "timeout": "danger"
56
- }
57
- ),
58
- UserField(
59
- name="user",
60
- title="User",
61
- header=True # Show with avatar
62
- ),
63
- DateTimeField(
64
- name="created_at",
65
- title="Created",
66
- ordering="created_at"
67
- ),
68
- DateTimeField(
69
- name="completed_at",
70
- title="Completed",
71
- ordering="completed_at"
72
- ),
73
- ],
74
-
75
- # Filters
76
- list_filter=["status", "method", "created_at"],
77
- search_fields=["method", "correlation_id", "user__username", "user__email", "error_message"],
78
-
79
- # Readonly fields (custom methods below)
80
- readonly_fields=[
81
- "id",
82
- "correlation_id",
83
- "created_at",
84
- "completed_at",
85
- "params_display",
86
- "response_display",
87
- "error_details_display"
88
- ],
89
-
90
- # Date hierarchy
91
- date_hierarchy="created_at",
92
-
93
- # Per page
94
- list_per_page=50,
95
- )
96
-
97
-
98
- @admin.register(RPCLog)
99
- class RPCLogAdmin(PydanticAdmin):
100
- """
101
- RPC log admin with analytics and filtering.
102
-
103
- Features:
104
- - Color-coded status badges
105
- - Duration display with performance indicators
106
- - Formatted JSON for params/response
107
- - Error details with highlighted display
108
- """
109
- config = rpclog_config
110
-
111
- @computed_field("Duration", ordering="duration_ms")
112
- def duration_display(self, obj):
113
- """Display duration with color coding based on speed."""
114
- if obj.duration_ms is None:
115
- return self.html.empty()
116
-
117
- # Color code based on duration
118
- if obj.duration_ms < 100:
119
- variant = "success" # Fast
120
- icon = Icons.SPEED
121
- elif obj.duration_ms < 500:
122
- variant = "warning" # Moderate
123
- icon = Icons.TIMER
124
- else:
125
- variant = "danger" # Slow
126
- icon = Icons.ERROR
127
-
128
- return self.html.badge(
129
- f"{obj.duration_ms}ms",
130
- variant=variant,
131
- icon=icon
132
- )
133
-
134
- def params_display(self, obj):
135
- """Display formatted JSON params."""
136
- if not obj.params:
137
- return self.html.empty("No parameters")
138
-
139
- try:
140
- formatted = json.dumps(obj.params, indent=2)
141
- return f'<pre style="background: #f5f5f5; padding: 10px; border-radius: 4px; max-height: 400px; overflow: auto; font-size: 12px; line-height: 1.5;">{formatted}</pre>'
142
- except Exception:
143
- return str(obj.params)
144
-
145
- params_display.short_description = "Request Parameters"
146
-
147
- def response_display(self, obj):
148
- """Display formatted JSON response."""
149
- if not obj.response:
150
- return self.html.empty("No response")
151
-
152
- try:
153
- formatted = json.dumps(obj.response, indent=2)
154
- return f'<pre style="background: #f5f5f5; padding: 10px; border-radius: 4px; max-height: 400px; overflow: auto; font-size: 12px; line-height: 1.5;">{formatted}</pre>'
155
- except Exception:
156
- return str(obj.response)
157
-
158
- response_display.short_description = "Response Data"
159
-
160
- def error_details_display(self, obj):
161
- """Display error information if call failed."""
162
- if not obj.is_failed:
163
- return self.html.inline([
164
- self.html.icon(Icons.CHECK_CIRCLE, size="sm"),
165
- self.html.span("No errors", "text-green-600")
166
- ])
167
-
168
- details = []
169
-
170
- if obj.error_code:
171
- details.append(self.html.inline([
172
- self.html.span("Error Code:", "font-semibold"),
173
- self.html.badge(obj.error_code, variant="danger", icon=Icons.ERROR)
174
- ], separator=" "))
175
-
176
- if obj.error_message:
177
- details.append(self.html.inline([
178
- self.html.span("Message:", "font-semibold"),
179
- self.html.span(obj.error_message, "text-red-600")
180
- ], separator=" "))
181
-
182
- return "<br>".join(details) if details else self.html.empty()
183
-
184
- error_details_display.short_description = "Error Details"
185
-
186
- # Fieldsets for detail view
187
- def get_fieldsets(self, request, obj=None):
188
- """Dynamic fieldsets based on object state."""
189
- fieldsets = [
190
- ("RPC Call Information", {
191
- 'fields': ('id', 'correlation_id', 'method', 'user', 'status')
192
- }),
193
- ("Request & Response", {
194
- 'fields': ('params_display', 'response_display'),
195
- 'classes': ('collapse',)
196
- }),
197
- ("Performance", {
198
- 'fields': ('duration_ms', 'created_at', 'completed_at')
199
- }),
200
- ("Metadata", {
201
- 'fields': ('caller_ip', 'user_agent'),
202
- 'classes': ('collapse',)
203
- }),
204
- ]
205
-
206
- # Add error section only if failed
207
- if obj and obj.is_failed:
208
- fieldsets.insert(2, ("Error Details", {
209
- 'fields': ('error_details_display', 'error_code', 'error_message')
210
- }))
211
-
212
- return fieldsets
@@ -1,28 +0,0 @@
1
- """
2
- Django app configuration for IPC/RPC module.
3
-
4
- Provides RPC client and monitoring dashboard.
5
- """
6
-
7
- from django.apps import AppConfig
8
-
9
-
10
- class IPCConfig(AppConfig):
11
- """
12
- IPC/RPC application configuration.
13
-
14
- Provides:
15
- - RPC client for inter-service communication
16
- - Monitoring dashboard with real-time stats
17
- - DRF API endpoints for dashboard
18
- """
19
-
20
- default_auto_field = 'django.db.models.BigAutoField'
21
- name = 'django_cfg.apps.ipc'
22
- label = 'django_cfg_ipc'
23
- verbose_name = 'IPC/RPC System'
24
-
25
- def ready(self):
26
- """Initialize app when Django starts."""
27
- # Import monitor to ensure Redis connection is initialized
28
- from .services import monitor # noqa: F401
@@ -1,137 +0,0 @@
1
- # Generated by Django 5.2.7 on 2025-10-23 12:12
2
-
3
- import django.db.models.deletion
4
- import django.utils.timezone
5
- import uuid
6
- from django.conf import settings
7
- from django.db import migrations, models
8
-
9
-
10
- class Migration(migrations.Migration):
11
- initial = True
12
-
13
- dependencies = [
14
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15
- ]
16
-
17
- operations = [
18
- migrations.CreateModel(
19
- name="RPCLog",
20
- fields=[
21
- (
22
- "id",
23
- models.UUIDField(
24
- default=uuid.uuid4, editable=False, primary_key=True, serialize=False
25
- ),
26
- ),
27
- (
28
- "correlation_id",
29
- models.CharField(
30
- db_index=True,
31
- help_text="UUID from RPC request",
32
- max_length=100,
33
- verbose_name="Correlation ID",
34
- ),
35
- ),
36
- (
37
- "method",
38
- models.CharField(
39
- db_index=True,
40
- help_text="e.g., send_notification, workspace.file_changed",
41
- max_length=100,
42
- verbose_name="RPC Method",
43
- ),
44
- ),
45
- (
46
- "params",
47
- models.JSONField(
48
- help_text="Parameters sent to RPC method", verbose_name="Request Params"
49
- ),
50
- ),
51
- (
52
- "response",
53
- models.JSONField(
54
- blank=True,
55
- help_text="Result from RPC call",
56
- null=True,
57
- verbose_name="Response Data",
58
- ),
59
- ),
60
- (
61
- "status",
62
- models.CharField(
63
- choices=[
64
- ("pending", "Pending"),
65
- ("success", "Success"),
66
- ("failed", "Failed"),
67
- ("timeout", "Timeout"),
68
- ],
69
- db_index=True,
70
- default="pending",
71
- max_length=20,
72
- verbose_name="Status",
73
- ),
74
- ),
75
- (
76
- "error_code",
77
- models.CharField(
78
- blank=True, max_length=50, null=True, verbose_name="Error Code"
79
- ),
80
- ),
81
- (
82
- "error_message",
83
- models.TextField(blank=True, null=True, verbose_name="Error Message"),
84
- ),
85
- (
86
- "duration_ms",
87
- models.IntegerField(
88
- blank=True,
89
- help_text="Time taken for RPC call in milliseconds",
90
- null=True,
91
- verbose_name="Duration (ms)",
92
- ),
93
- ),
94
- (
95
- "caller_ip",
96
- models.GenericIPAddressField(blank=True, null=True, verbose_name="Caller IP"),
97
- ),
98
- ("user_agent", models.TextField(blank=True, null=True, verbose_name="User Agent")),
99
- (
100
- "created_at",
101
- models.DateTimeField(
102
- db_index=True, default=django.utils.timezone.now, verbose_name="Created At"
103
- ),
104
- ),
105
- (
106
- "completed_at",
107
- models.DateTimeField(blank=True, null=True, verbose_name="Completed At"),
108
- ),
109
- (
110
- "user",
111
- models.ForeignKey(
112
- blank=True,
113
- null=True,
114
- on_delete=django.db.models.deletion.SET_NULL,
115
- related_name="rpc_logs",
116
- to=settings.AUTH_USER_MODEL,
117
- verbose_name="User",
118
- ),
119
- ),
120
- ],
121
- options={
122
- "verbose_name": "RPC Log",
123
- "verbose_name_plural": "RPC Logs",
124
- "ordering": ["-created_at"],
125
- "indexes": [
126
- models.Index(fields=["method", "status"], name="django_cfg__method_916fd9_idx"),
127
- models.Index(
128
- fields=["status", "created_at"], name="django_cfg__status_ee629e_idx"
129
- ),
130
- models.Index(fields=["correlation_id"], name="django_cfg__correla_fc7bcf_idx"),
131
- models.Index(
132
- fields=["user", "created_at"], name="django_cfg__user_id_c33866_idx"
133
- ),
134
- ],
135
- },
136
- ),
137
- ]
File without changes
@@ -1,221 +0,0 @@
1
- """
2
- IPC/RPC Models for logging and monitoring.
3
-
4
- Models:
5
- - RPCLog: Log of all RPC calls for debugging and analytics
6
- """
7
-
8
- import uuid
9
- from django.conf import settings
10
- from django.db import models
11
- from django.utils import timezone
12
-
13
-
14
- class RPCLogManager(models.Manager):
15
- """Custom manager for RPCLog model."""
16
-
17
- def recent(self, hours=24):
18
- """Get logs from last N hours."""
19
- since = timezone.now() - timezone.timedelta(hours=hours)
20
- return self.filter(created_at__gte=since)
21
-
22
- def failed(self):
23
- """Get failed RPC calls."""
24
- return self.filter(status=RPCLog.StatusChoices.FAILED)
25
-
26
- def by_method(self, method):
27
- """Get logs for specific RPC method."""
28
- return self.filter(method=method)
29
-
30
- def stats_by_method(self):
31
- """
32
- Get statistics grouped by method.
33
-
34
- Returns:
35
- QuerySet with aggregated data per method
36
- """
37
- from django.db.models import Count, Avg, Max, Min
38
-
39
- return self.values('method').annotate(
40
- total_calls=Count('id'),
41
- avg_duration_ms=Avg('duration_ms'),
42
- max_duration_ms=Max('duration_ms'),
43
- min_duration_ms=Min('duration_ms'),
44
- success_count=Count('id', filter=models.Q(status='success')),
45
- failed_count=Count('id', filter=models.Q(status='failed')),
46
- ).order_by('-total_calls')
47
-
48
-
49
- class RPCLog(models.Model):
50
- """
51
- Log of RPC calls between Django and WebSocket server.
52
-
53
- Used for:
54
- - Debugging RPC communication
55
- - Performance monitoring
56
- - Analytics (most used methods, success rate)
57
- - Audit trail (who called what and when)
58
- """
59
-
60
- class StatusChoices(models.TextChoices):
61
- PENDING = 'pending', 'Pending'
62
- SUCCESS = 'success', 'Success'
63
- FAILED = 'failed', 'Failed'
64
- TIMEOUT = 'timeout', 'Timeout'
65
-
66
- # Primary key
67
- id = models.UUIDField(
68
- primary_key=True,
69
- default=uuid.uuid4,
70
- editable=False
71
- )
72
-
73
- # Correlation ID (matches RPC correlation_id)
74
- correlation_id = models.CharField(
75
- max_length=100,
76
- db_index=True,
77
- verbose_name="Correlation ID",
78
- help_text="UUID from RPC request"
79
- )
80
-
81
- # User who initiated the call (optional)
82
- user = models.ForeignKey(
83
- settings.AUTH_USER_MODEL,
84
- on_delete=models.SET_NULL,
85
- null=True,
86
- blank=True,
87
- related_name='rpc_logs',
88
- verbose_name="User"
89
- )
90
-
91
- # RPC method name
92
- method = models.CharField(
93
- max_length=100,
94
- db_index=True,
95
- verbose_name="RPC Method",
96
- help_text="e.g., send_notification, workspace.file_changed"
97
- )
98
-
99
- # Request parameters (JSON)
100
- params = models.JSONField(
101
- verbose_name="Request Params",
102
- help_text="Parameters sent to RPC method"
103
- )
104
-
105
- # Response data (JSON, nullable if failed)
106
- response = models.JSONField(
107
- null=True,
108
- blank=True,
109
- verbose_name="Response Data",
110
- help_text="Result from RPC call"
111
- )
112
-
113
- # Status
114
- status = models.CharField(
115
- max_length=20,
116
- choices=StatusChoices.choices,
117
- default=StatusChoices.PENDING,
118
- db_index=True,
119
- verbose_name="Status"
120
- )
121
-
122
- # Error details (if failed)
123
- error_code = models.CharField(
124
- max_length=50,
125
- null=True,
126
- blank=True,
127
- verbose_name="Error Code"
128
- )
129
- error_message = models.TextField(
130
- null=True,
131
- blank=True,
132
- verbose_name="Error Message"
133
- )
134
-
135
- # Performance metrics
136
- duration_ms = models.IntegerField(
137
- null=True,
138
- blank=True,
139
- verbose_name="Duration (ms)",
140
- help_text="Time taken for RPC call in milliseconds"
141
- )
142
-
143
- # Metadata
144
- caller_ip = models.GenericIPAddressField(
145
- null=True,
146
- blank=True,
147
- verbose_name="Caller IP"
148
- )
149
- user_agent = models.TextField(
150
- null=True,
151
- blank=True,
152
- verbose_name="User Agent"
153
- )
154
-
155
- # Timestamps
156
- created_at = models.DateTimeField(
157
- default=timezone.now,
158
- db_index=True,
159
- verbose_name="Created At"
160
- )
161
- completed_at = models.DateTimeField(
162
- null=True,
163
- blank=True,
164
- verbose_name="Completed At"
165
- )
166
-
167
- # Custom manager
168
- objects = RPCLogManager()
169
-
170
- class Meta:
171
- app_label = 'django_cfg_ipc'
172
- verbose_name = "RPC Log"
173
- verbose_name_plural = "RPC Logs"
174
- ordering = ['-created_at']
175
- indexes = [
176
- models.Index(fields=['method', 'status']),
177
- models.Index(fields=['status', 'created_at']),
178
- models.Index(fields=['correlation_id']),
179
- models.Index(fields=['user', 'created_at']),
180
- ]
181
-
182
- def __str__(self):
183
- return f"{self.method} ({self.status}) - {self.created_at.strftime('%Y-%m-%d %H:%M:%S')}"
184
-
185
- @property
186
- def is_successful(self):
187
- """Check if RPC call was successful."""
188
- return self.status == self.StatusChoices.SUCCESS
189
-
190
- @property
191
- def is_failed(self):
192
- """Check if RPC call failed."""
193
- return self.status in [self.StatusChoices.FAILED, self.StatusChoices.TIMEOUT]
194
-
195
- def mark_success(self, response_data, duration_ms=None):
196
- """Mark RPC call as successful."""
197
- self.status = self.StatusChoices.SUCCESS
198
- self.response = response_data
199
- self.completed_at = timezone.now()
200
- if duration_ms is not None:
201
- self.duration_ms = duration_ms
202
- self.save()
203
-
204
- def mark_failed(self, error_code, error_message, duration_ms=None):
205
- """Mark RPC call as failed."""
206
- self.status = self.StatusChoices.FAILED
207
- self.error_code = error_code
208
- self.error_message = error_message
209
- self.completed_at = timezone.now()
210
- if duration_ms is not None:
211
- self.duration_ms = duration_ms
212
- self.save()
213
-
214
- def mark_timeout(self, timeout_seconds):
215
- """Mark RPC call as timed out."""
216
- self.status = self.StatusChoices.TIMEOUT
217
- self.error_code = 'timeout'
218
- self.error_message = f'RPC call timed out after {timeout_seconds}s'
219
- self.completed_at = timezone.now()
220
- self.duration_ms = timeout_seconds * 1000
221
- self.save()
@@ -1,29 +0,0 @@
1
- """
2
- Serializers for IPC/RPC module.
3
- """
4
-
5
- from .serializers import (
6
- HealthCheckSerializer,
7
- LoadTestRequestSerializer,
8
- LoadTestResponseSerializer,
9
- LoadTestStatusSerializer,
10
- MethodStatsSerializer,
11
- NotificationStatsSerializer,
12
- OverviewStatsSerializer,
13
- RecentRequestsSerializer,
14
- TestRPCRequestSerializer,
15
- TestRPCResponseSerializer,
16
- )
17
-
18
- __all__ = [
19
- 'HealthCheckSerializer',
20
- 'OverviewStatsSerializer',
21
- 'RecentRequestsSerializer',
22
- 'NotificationStatsSerializer',
23
- 'MethodStatsSerializer',
24
- 'TestRPCRequestSerializer',
25
- 'TestRPCResponseSerializer',
26
- 'LoadTestRequestSerializer',
27
- 'LoadTestResponseSerializer',
28
- 'LoadTestStatusSerializer',
29
- ]