django-cfg 1.5.14__py3-none-any.whl → 1.5.29__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 (118) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/apps/business/accounts/serializers/profile.py +42 -0
  3. django_cfg/apps/business/support/serializers.py +3 -2
  4. django_cfg/apps/integrations/centrifugo/__init__.py +2 -0
  5. django_cfg/apps/integrations/centrifugo/apps.py +2 -1
  6. django_cfg/apps/integrations/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2 +151 -12
  7. django_cfg/apps/integrations/centrifugo/management/commands/generate_centrifugo_clients.py +2 -2
  8. django_cfg/apps/integrations/centrifugo/services/__init__.py +6 -0
  9. django_cfg/apps/integrations/centrifugo/services/client/__init__.py +6 -1
  10. django_cfg/apps/integrations/centrifugo/services/client/client.py +1 -1
  11. django_cfg/apps/integrations/centrifugo/services/client/direct_client.py +282 -0
  12. django_cfg/apps/integrations/centrifugo/services/logging.py +47 -0
  13. django_cfg/apps/integrations/centrifugo/services/publisher.py +371 -0
  14. django_cfg/apps/integrations/centrifugo/services/token_generator.py +122 -0
  15. django_cfg/apps/integrations/centrifugo/urls.py +8 -0
  16. django_cfg/apps/integrations/centrifugo/views/__init__.py +2 -0
  17. django_cfg/apps/integrations/centrifugo/views/admin_api.py +29 -32
  18. django_cfg/apps/integrations/centrifugo/views/testing_api.py +31 -116
  19. django_cfg/apps/integrations/centrifugo/views/token_api.py +101 -0
  20. django_cfg/apps/integrations/centrifugo/views/wrapper.py +259 -0
  21. django_cfg/apps/integrations/grpc/auth/api_key_auth.py +11 -10
  22. django_cfg/apps/integrations/grpc/management/commands/compile_proto.py +105 -0
  23. django_cfg/apps/integrations/grpc/management/commands/generate_protos.py +56 -1
  24. django_cfg/apps/integrations/grpc/management/commands/rungrpc.py +315 -26
  25. django_cfg/apps/integrations/grpc/management/proto/__init__.py +3 -0
  26. django_cfg/apps/integrations/grpc/management/proto/compiler.py +194 -0
  27. django_cfg/apps/integrations/grpc/managers/grpc_request_log.py +84 -0
  28. django_cfg/apps/integrations/grpc/managers/grpc_server_status.py +126 -3
  29. django_cfg/apps/integrations/grpc/models/grpc_api_key.py +7 -1
  30. django_cfg/apps/integrations/grpc/models/grpc_server_status.py +22 -3
  31. django_cfg/apps/integrations/grpc/services/__init__.py +102 -17
  32. django_cfg/apps/integrations/grpc/services/centrifugo/__init__.py +29 -0
  33. django_cfg/apps/integrations/grpc/services/centrifugo/bridge.py +469 -0
  34. django_cfg/apps/integrations/grpc/services/centrifugo/config.py +167 -0
  35. django_cfg/apps/integrations/grpc/services/centrifugo/demo.py +626 -0
  36. django_cfg/apps/integrations/grpc/services/centrifugo/test_publish.py +229 -0
  37. django_cfg/apps/integrations/grpc/services/centrifugo/transformers.py +89 -0
  38. django_cfg/apps/integrations/grpc/services/client/__init__.py +26 -0
  39. django_cfg/apps/integrations/grpc/services/commands/IMPLEMENTATION.md +456 -0
  40. django_cfg/apps/integrations/grpc/services/commands/README.md +252 -0
  41. django_cfg/apps/integrations/grpc/services/commands/__init__.py +93 -0
  42. django_cfg/apps/integrations/grpc/services/commands/base.py +243 -0
  43. django_cfg/apps/integrations/grpc/services/commands/examples/__init__.py +22 -0
  44. django_cfg/apps/integrations/grpc/services/commands/examples/base_client.py +228 -0
  45. django_cfg/apps/integrations/grpc/services/commands/examples/client.py +272 -0
  46. django_cfg/apps/integrations/grpc/services/commands/examples/config.py +177 -0
  47. django_cfg/apps/integrations/grpc/services/commands/examples/start.py +125 -0
  48. django_cfg/apps/integrations/grpc/services/commands/examples/stop.py +101 -0
  49. django_cfg/apps/integrations/grpc/services/commands/registry.py +170 -0
  50. django_cfg/apps/integrations/grpc/services/discovery/__init__.py +39 -0
  51. django_cfg/apps/integrations/grpc/services/{discovery.py → discovery/discovery.py} +67 -54
  52. django_cfg/apps/integrations/grpc/services/{service_registry.py → discovery/registry.py} +215 -5
  53. django_cfg/apps/integrations/grpc/{interceptors → services/interceptors}/__init__.py +3 -1
  54. django_cfg/apps/integrations/grpc/services/interceptors/centrifugo.py +541 -0
  55. django_cfg/apps/integrations/grpc/{interceptors → services/interceptors}/metrics.py +3 -3
  56. django_cfg/apps/integrations/grpc/{interceptors → services/interceptors}/request_logger.py +10 -13
  57. django_cfg/apps/integrations/grpc/services/management/__init__.py +37 -0
  58. django_cfg/apps/integrations/grpc/services/monitoring/__init__.py +38 -0
  59. django_cfg/apps/integrations/grpc/services/{monitoring_service.py → monitoring/monitoring.py} +2 -2
  60. django_cfg/apps/integrations/grpc/services/{testing_service.py → monitoring/testing.py} +5 -5
  61. django_cfg/apps/integrations/grpc/services/rendering/__init__.py +27 -0
  62. django_cfg/apps/integrations/grpc/services/{chart_generator.py → rendering/charts.py} +1 -1
  63. django_cfg/apps/integrations/grpc/services/routing/__init__.py +59 -0
  64. django_cfg/apps/integrations/grpc/services/routing/config.py +76 -0
  65. django_cfg/apps/integrations/grpc/services/routing/router.py +430 -0
  66. django_cfg/apps/integrations/grpc/services/streaming/__init__.py +117 -0
  67. django_cfg/apps/integrations/grpc/services/streaming/config.py +451 -0
  68. django_cfg/apps/integrations/grpc/services/streaming/service.py +651 -0
  69. django_cfg/apps/integrations/grpc/services/streaming/types.py +367 -0
  70. django_cfg/apps/integrations/grpc/utils/SERVER_LOGGING.md +164 -0
  71. django_cfg/apps/integrations/grpc/utils/__init__.py +58 -1
  72. django_cfg/apps/integrations/grpc/utils/converters.py +565 -0
  73. django_cfg/apps/integrations/grpc/utils/handlers.py +242 -0
  74. django_cfg/apps/integrations/grpc/utils/proto_gen.py +1 -1
  75. django_cfg/apps/integrations/grpc/utils/streaming_logger.py +261 -13
  76. django_cfg/apps/integrations/grpc/views/charts.py +1 -1
  77. django_cfg/apps/integrations/grpc/views/config.py +1 -1
  78. django_cfg/apps/system/dashboard/serializers/config.py +95 -9
  79. django_cfg/apps/system/dashboard/serializers/statistics.py +9 -4
  80. django_cfg/apps/system/frontend/views.py +87 -6
  81. django_cfg/core/base/config_model.py +11 -0
  82. django_cfg/core/builders/middleware_builder.py +5 -0
  83. django_cfg/core/builders/security_builder.py +1 -0
  84. django_cfg/core/generation/integration_generators/api.py +2 -0
  85. django_cfg/management/commands/pool_status.py +153 -0
  86. django_cfg/middleware/pool_cleanup.py +261 -0
  87. django_cfg/models/api/grpc/config.py +2 -2
  88. django_cfg/models/infrastructure/database/config.py +16 -0
  89. django_cfg/models/infrastructure/database/converters.py +2 -0
  90. django_cfg/modules/django_admin/utils/html/composition.py +57 -13
  91. django_cfg/modules/django_admin/utils/html_builder.py +1 -0
  92. django_cfg/modules/django_client/core/generator/typescript/generator.py +26 -0
  93. django_cfg/modules/django_client/core/generator/typescript/hooks_generator.py +7 -1
  94. django_cfg/modules/django_client/core/generator/typescript/models_generator.py +5 -0
  95. django_cfg/modules/django_client/core/generator/typescript/schemas_generator.py +11 -0
  96. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/fetchers.ts.jinja +1 -0
  97. django_cfg/modules/django_client/core/generator/typescript/templates/fetchers/function.ts.jinja +29 -1
  98. django_cfg/modules/django_client/core/generator/typescript/templates/hooks/hooks.ts.jinja +4 -0
  99. django_cfg/modules/django_client/core/groups/manager.py +25 -18
  100. django_cfg/modules/django_client/core/ir/schema.py +15 -1
  101. django_cfg/modules/django_client/core/parser/base.py +12 -0
  102. django_cfg/modules/django_client/management/commands/generate_client.py +9 -5
  103. django_cfg/modules/django_logging/django_logger.py +58 -19
  104. django_cfg/pyproject.toml +3 -3
  105. django_cfg/static/frontend/admin.zip +0 -0
  106. django_cfg/templates/admin/index.html +0 -39
  107. django_cfg/utils/pool_monitor.py +320 -0
  108. django_cfg/utils/smart_defaults.py +233 -7
  109. {django_cfg-1.5.14.dist-info → django_cfg-1.5.29.dist-info}/METADATA +75 -5
  110. {django_cfg-1.5.14.dist-info → django_cfg-1.5.29.dist-info}/RECORD +118 -74
  111. /django_cfg/apps/integrations/grpc/services/{grpc_client.py → client/client.py} +0 -0
  112. /django_cfg/apps/integrations/grpc/{interceptors → services/interceptors}/errors.py +0 -0
  113. /django_cfg/apps/integrations/grpc/{interceptors → services/interceptors}/logging.py +0 -0
  114. /django_cfg/apps/integrations/grpc/services/{config_helper.py → management/config_helper.py} +0 -0
  115. /django_cfg/apps/integrations/grpc/services/{proto_files_manager.py → management/proto_manager.py} +0 -0
  116. {django_cfg-1.5.14.dist-info → django_cfg-1.5.29.dist-info}/WHEEL +0 -0
  117. {django_cfg-1.5.14.dist-info → django_cfg-1.5.29.dist-info}/entry_points.txt +0 -0
  118. {django_cfg-1.5.14.dist-info → django_cfg-1.5.29.dist-info}/licenses/LICENSE +0 -0
@@ -7,6 +7,8 @@ Following KISS principle:
7
7
  - Logging handled by django_logger module
8
8
  """
9
9
 
10
+ import os
11
+ import sys
10
12
  from pathlib import Path
11
13
  from typing import Any, Dict, List, Optional
12
14
 
@@ -14,9 +16,9 @@ from typing import Any, Dict, List, Optional
14
16
  def get_log_filename() -> str:
15
17
  """
16
18
  Determine the correct log filename based on project type.
17
-
19
+
18
20
  Returns:
19
- - 'django-cfg.log' for django-cfg projects
21
+ - 'django-cfg.log' for django-cfg projects
20
22
  - 'django.log' for regular Django projects
21
23
  """
22
24
  try:
@@ -35,6 +37,188 @@ def get_log_filename() -> str:
35
37
  return 'django-cfg.log'
36
38
 
37
39
 
40
+ def _detect_asgi_mode() -> bool:
41
+ """
42
+ Detect if Django is running in ASGI or WSGI mode.
43
+
44
+ Detection priority:
45
+ 1. DJANGO_ASGI environment variable (explicit override)
46
+ 2. ASGI_APPLICATION setting (if Django is configured)
47
+ 3. Command-line arguments (uvicorn, daphne, hypercorn)
48
+ 4. Default: False (WSGI mode)
49
+
50
+ Returns:
51
+ True if ASGI mode, False if WSGI mode
52
+
53
+ Examples:
54
+ >>> os.environ['DJANGO_ASGI'] = 'true'
55
+ >>> _detect_asgi_mode()
56
+ True
57
+
58
+ >>> 'uvicorn' in sys.argv[0]
59
+ >>> _detect_asgi_mode()
60
+ True
61
+ """
62
+ # 1. Check explicit env var override
63
+ asgi_env = os.environ.get('DJANGO_ASGI', '').lower()
64
+ if asgi_env in ('true', '1', 'yes'):
65
+ return True
66
+ elif asgi_env in ('false', '0', 'no'):
67
+ return False
68
+
69
+ # 2. Check Django settings for ASGI_APPLICATION
70
+ try:
71
+ from django.conf import settings
72
+ if hasattr(settings, 'ASGI_APPLICATION') and settings.ASGI_APPLICATION:
73
+ return True
74
+ except (ImportError, Exception):
75
+ pass
76
+
77
+ # 3. Check command-line arguments for ASGI servers
78
+ command_line = ' '.join(sys.argv).lower()
79
+ asgi_servers = ['uvicorn', 'daphne', 'hypercorn']
80
+ for server in asgi_servers:
81
+ if server in command_line:
82
+ return True
83
+
84
+ # Default: WSGI mode
85
+ return False
86
+
87
+
88
+ def get_pool_config(environment: str = "development", is_asgi: Optional[bool] = None) -> Dict[str, Any]:
89
+ """
90
+ Get connection pool configuration.
91
+
92
+ By default, uses simple environment-based configuration. Set AUTO_POOL_SIZE=true
93
+ to enable automatic ASGI/WSGI detection and optimization.
94
+
95
+ Args:
96
+ environment: Environment name ('development', 'testing', 'staging', 'production')
97
+ is_asgi: Deployment mode. If None and AUTO_POOL_SIZE=true, auto-detects mode
98
+
99
+ Returns:
100
+ Dict with pool configuration:
101
+ {
102
+ 'min_size': int, # Minimum pool size
103
+ 'max_size': int, # Maximum pool size
104
+ 'timeout': int, # Connection timeout (seconds)
105
+ 'max_lifetime': int, # Max connection lifetime (seconds)
106
+ 'max_idle': int, # Max idle time before closing (seconds)
107
+ }
108
+
109
+ Environment Variables:
110
+ DB_POOL_MIN_SIZE: Minimum pool size (default: 10)
111
+ DB_POOL_MAX_SIZE: Maximum pool size (default: 50)
112
+ DB_POOL_TIMEOUT: Connection timeout in seconds (default: 30)
113
+ AUTO_POOL_SIZE: Enable automatic ASGI/WSGI detection (default: false)
114
+
115
+ Examples:
116
+ # Simple static config (default):
117
+ >>> get_pool_config('production')
118
+ {'min_size': 10, 'max_size': 50, ...}
119
+
120
+ # With auto-detection:
121
+ >>> os.environ['AUTO_POOL_SIZE'] = 'true'
122
+ >>> get_pool_config('production', is_asgi=True)
123
+ {'min_size': 5, 'max_size': 20, ...} # Optimized for ASGI
124
+ """
125
+ # Check if auto-detection is enabled
126
+ auto_detect = os.environ.get('AUTO_POOL_SIZE', 'false').lower() in ('true', '1', 'yes')
127
+
128
+ # Simple static configuration (default)
129
+ if not auto_detect and is_asgi is None:
130
+ # Use simple env var based config
131
+ try:
132
+ min_size = int(os.environ.get('DB_POOL_MIN_SIZE', 10))
133
+ except ValueError:
134
+ min_size = 10
135
+
136
+ try:
137
+ max_size = int(os.environ.get('DB_POOL_MAX_SIZE', 50))
138
+ except ValueError:
139
+ max_size = 50
140
+
141
+ try:
142
+ timeout = int(os.environ.get('DB_POOL_TIMEOUT', 30))
143
+ except ValueError:
144
+ timeout = 30
145
+
146
+ # Validate
147
+ if min_size >= max_size:
148
+ min_size = max(1, max_size - 1)
149
+
150
+ return {
151
+ 'min_size': min_size,
152
+ 'max_size': max_size,
153
+ 'timeout': timeout,
154
+ 'max_lifetime': 3600, # 1 hour
155
+ 'max_idle': 600, # 10 minutes
156
+ }
157
+
158
+ # Auto-detect ASGI mode if enabled and not specified
159
+ if is_asgi is None:
160
+ is_asgi = _detect_asgi_mode()
161
+
162
+ # Pool configuration matrix
163
+ # Format: (min_size, max_size, timeout)
164
+ pool_configs = {
165
+ 'development': {
166
+ 'asgi': (2, 10, 10),
167
+ 'wsgi': (3, 15, 20),
168
+ },
169
+ 'testing': {
170
+ 'asgi': (1, 5, 5),
171
+ 'wsgi': (2, 10, 10),
172
+ },
173
+ 'staging': {
174
+ 'asgi': (3, 15, 10),
175
+ 'wsgi': (5, 30, 20),
176
+ },
177
+ 'production': {
178
+ 'asgi': (5, 20, 10),
179
+ 'wsgi': (10, 50, 30),
180
+ },
181
+ }
182
+
183
+ # Get base configuration
184
+ env_key = environment.lower()
185
+ if env_key not in pool_configs:
186
+ # Fallback to development for unknown environments
187
+ env_key = 'development'
188
+
189
+ mode_key = 'asgi' if is_asgi else 'wsgi'
190
+ min_size, max_size, timeout = pool_configs[env_key][mode_key]
191
+
192
+ # Allow environment variable overrides
193
+ try:
194
+ min_size = int(os.environ.get('DB_POOL_MIN_SIZE', min_size))
195
+ except ValueError:
196
+ pass # Keep default if invalid
197
+
198
+ try:
199
+ max_size = int(os.environ.get('DB_POOL_MAX_SIZE', max_size))
200
+ except ValueError:
201
+ pass
202
+
203
+ try:
204
+ timeout = int(os.environ.get('DB_POOL_TIMEOUT', timeout))
205
+ except ValueError:
206
+ pass
207
+
208
+ # Validate: min_size must be < max_size
209
+ if min_size >= max_size:
210
+ min_size = max(1, max_size - 1)
211
+
212
+ # Build and return pool configuration
213
+ return {
214
+ 'min_size': min_size,
215
+ 'max_size': max_size,
216
+ 'timeout': timeout,
217
+ 'max_lifetime': 3600, # 1 hour
218
+ 'max_idle': 600, # 10 minutes
219
+ }
220
+
221
+
38
222
  class SmartDefaults:
39
223
  """
40
224
  Environment-aware smart defaults for Django configuration.
@@ -45,18 +229,50 @@ class SmartDefaults:
45
229
 
46
230
  @staticmethod
47
231
  def get_database_defaults(environment: str = "development", debug: bool = False, engine: str = "sqlite3") -> Dict[str, Any]:
48
- """Get database configuration defaults."""
232
+ """
233
+ Get database configuration defaults.
234
+
235
+ For PostgreSQL with Django 5.1+:
236
+ - Uses native connection pooling (recommended for ASGI/async apps)
237
+ - CONN_MAX_AGE = 0 (required with native pooling)
238
+ - ATOMIC_REQUESTS = True (default - safe and works with pooling)
239
+ - Pool sizes: Auto-configured based on environment and ASGI/WSGI mode
240
+ - Health checks: Handled automatically by psycopg3 pool
241
+
242
+ Note on Transaction Safety:
243
+ ATOMIC_REQUESTS=True is enabled by default, which wraps each request
244
+ in a database transaction. This adds ~5-10ms overhead but ensures data
245
+ integrity without manual transaction management.
246
+
247
+ This works perfectly fine with connection pooling. If you need to optimize
248
+ for read-heavy workloads, you can disable ATOMIC_REQUESTS and use selective
249
+ transactions via Django's @transaction.atomic decorator on write views.
250
+
251
+ References:
252
+ - Django 5.1+ native pooling: https://docs.djangoproject.com/en/5.2/ref/databases/#connection-pooling
253
+ - ASGI best practices: persistent connections should be disabled with ASGI
254
+ """
49
255
  defaults = {
50
256
  'ENGINE': 'django.db.backends.sqlite3',
51
257
  'NAME': Path('db') / 'db.sqlite3',
52
- 'ATOMIC_REQUESTS': True,
53
- 'CONN_MAX_AGE': 60,
258
+ 'ATOMIC_REQUESTS': True, # Safe default - ~5-10ms overhead acceptable for data integrity
259
+ 'CONN_MAX_AGE': 0, # Set to 0 for native pooling (Django 5.1+)
260
+ 'CONN_HEALTH_CHECKS': True, # Enable health checks to prevent stale connections
54
261
  'OPTIONS': {}
55
262
  }
56
263
 
57
264
  # Add engine-specific options
58
265
  if engine == "django.db.backends.postgresql":
59
- defaults['OPTIONS']['connect_timeout'] = 20
266
+ # Native connection pooling for Django 5.1+ with psycopg >= 3.1
267
+ # See: https://docs.djangoproject.com/en/5.2/ref/databases/#postgresql-connection-pooling
268
+
269
+ # Get dynamic pool configuration based on environment and deployment mode
270
+ pool_config = get_pool_config(environment=environment, is_asgi=None)
271
+
272
+ defaults['OPTIONS'] = {
273
+ 'connect_timeout': 20,
274
+ 'pool': pool_config, # Dynamic pool config (ASGI/WSGI aware)
275
+ }
60
276
  elif engine == "django.db.backends.sqlite3":
61
277
  defaults['OPTIONS']['timeout'] = 20 # SQLite uses 'timeout'
62
278
 
@@ -139,7 +355,16 @@ class SmartDefaults:
139
355
 
140
356
  @staticmethod
141
357
  def get_middleware_defaults() -> List[str]:
142
- """Get middleware configuration defaults."""
358
+ """
359
+ Get middleware configuration defaults.
360
+
361
+ Note:
362
+ ConnectionPoolCleanupMiddleware is automatically added LAST if
363
+ enable_pool_cleanup=True in DjangoConfig (default).
364
+
365
+ This middleware prevents connection leaks when using native
366
+ connection pooling with ATOMIC_REQUESTS=False.
367
+ """
143
368
  return [
144
369
  'corsheaders.middleware.CorsMiddleware',
145
370
  'django.middleware.security.SecurityMiddleware',
@@ -149,6 +374,7 @@ class SmartDefaults:
149
374
  'django.contrib.auth.middleware.AuthenticationMiddleware',
150
375
  'django.contrib.messages.middleware.MessageMiddleware',
151
376
  'django.middleware.clickjacking.XFrameOptionsMiddleware',
377
+ # ConnectionPoolCleanupMiddleware added in DjangoConfig.get_middleware()
152
378
  ]
153
379
 
154
380
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-cfg
3
- Version: 1.5.14
3
+ Version: 1.5.29
4
4
  Summary: Modern Django framework with type-safe Pydantic v2 configuration, Next.js admin integration, real-time WebSockets, and 8 enterprise apps. Replace settings.py with validated models, 90% less code. Production-ready with AI agents, auto-generated TypeScript clients, and zero-config features.
5
5
  Project-URL: Homepage, https://djangocfg.com
6
6
  Project-URL: Documentation, https://djangocfg.com
@@ -116,6 +116,7 @@ Requires-Dist: mkdocs>=1.5; extra == 'docs'
116
116
  Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
117
117
  Requires-Dist: pymdown-extensions>=10.0; extra == 'docs'
118
118
  Provides-Extra: full
119
+ Requires-Dist: aiobreaker<2.0,>=1.2.0; extra == 'full'
119
120
  Requires-Dist: black>=23.0; extra == 'full'
120
121
  Requires-Dist: build>=1.0; extra == 'full'
121
122
  Requires-Dist: cent<6.0,>=5.0.0; extra == 'full'
@@ -150,6 +151,7 @@ Requires-Dist: tomlkit>=0.11; extra == 'full'
150
151
  Requires-Dist: twine>=4.0; extra == 'full'
151
152
  Requires-Dist: websockets<15.0,>=13.0; extra == 'full'
152
153
  Provides-Extra: grpc
154
+ Requires-Dist: aiobreaker<2.0,>=1.2.0; extra == 'grpc'
153
155
  Requires-Dist: grpcio-health-checking<2.0,>=1.50.0; extra == 'grpc'
154
156
  Requires-Dist: grpcio-reflection<2.0,>=1.50.0; extra == 'grpc'
155
157
  Requires-Dist: grpcio-tools<2.0,>=1.50.0; extra == 'grpc'
@@ -194,7 +196,7 @@ Description-Content-Type: text/markdown
194
196
 
195
197
  ### 🚀 The Modern Django Framework for Enterprise Applications
196
198
 
197
- **Type-safe configuration** • **Next.js Admin** • **AI Agents** • **Real-time WebSockets** • **8 Enterprise Apps**
199
+ **Type-safe configuration** • **Next.js Admin** • **gRPC Streaming** • **Real-time WebSockets** • **AI Agents** • **8 Enterprise Apps**
198
200
 
199
201
  **[🎯 Live Demo](http://demo.djangocfg.com)** • **[📚 Documentation](https://djangocfg.com/docs/getting-started/intro)** • **[🐙 GitHub](https://github.com/markolofsen/django-cfg)**
200
202
 
@@ -394,6 +396,72 @@ class MyConfig(DjangoConfig):
394
396
 
395
397
  ---
396
398
 
399
+ ### 🌐 gRPC Microservices & Streaming
400
+
401
+ **Production-ready gRPC integration** - bidirectional streaming, WebSocket bridge, and type-safe Protobuf.
402
+
403
+ ```python
404
+ from django_cfg.apps.integrations.grpc.services.centrifugo import (
405
+ CentrifugoBridgeMixin,
406
+ CentrifugoChannels,
407
+ ChannelConfig,
408
+ )
409
+
410
+ # Define type-safe channel mappings
411
+ class BotChannels(CentrifugoChannels):
412
+ heartbeat: ChannelConfig = ChannelConfig(
413
+ template='bot#{bot_id}#heartbeat',
414
+ rate_limit=5.0, # Max once per 5 seconds
415
+ )
416
+ status: ChannelConfig = ChannelConfig(
417
+ template='bot#{bot_id}#status',
418
+ critical=True, # Bypass rate limiting
419
+ )
420
+
421
+ # gRPC service with automatic WebSocket publishing
422
+ class BotStreamingService(
423
+ pb2_grpc.BotStreamingServiceServicer,
424
+ CentrifugoBridgeMixin # ← One-line WebSocket integration
425
+ ):
426
+ centrifugo_channels = BotChannels()
427
+
428
+ async def ConnectBot(self, request_iterator, context):
429
+ async for message in request_iterator:
430
+ # Your business logic
431
+ await process_message(message)
432
+
433
+ # Auto-publish to WebSocket (1 line!)
434
+ await self._notify_centrifugo(message, bot_id=bot_id)
435
+ ```
436
+
437
+ **Built-in features:**
438
+ - 🔄 **Bidirectional Streaming** - Full-duplex gRPC communication
439
+ - 🌉 **Centrifugo Bridge** - Auto-publish gRPC events to WebSocket
440
+ - 🛡️ **Circuit Breaker** - Graceful degradation if Centrifugo unavailable
441
+ - 🔁 **Auto Retry** - Exponential backoff for critical events
442
+ - 📦 **Dead Letter Queue** - Never lose important messages
443
+ - ⚡ **Rate Limiting** - Per-channel throttling with critical bypass
444
+ - 🎯 **Type-Safe Config** - Pydantic v2 validation for channels
445
+
446
+ **Architecture:**
447
+ ```
448
+ Trading Bot ──gRPC──> Django gRPC Service ──WebSocket──> Browser
449
+
450
+ [Business Logic]
451
+ [Database Save]
452
+ [Centrifugo Publish]
453
+ ```
454
+
455
+ **Why this approach?**
456
+ - ✅ Django controls all business logic and validation
457
+ - ✅ Single source of truth for data transformations
458
+ - ✅ Graceful degradation - gRPC works even if WebSocket fails
459
+ - ✅ Production-ready resilience patterns built-in
460
+
461
+ **[📚 gRPC Integration Guide →](https://djangocfg.com/docs/features/integrations/grpc)**
462
+
463
+ ---
464
+
397
465
  ### 🤖 AI-Ready Infrastructure
398
466
 
399
467
  **Built-in AI agent framework** - LLM workflow automation with Django ORM integration.
@@ -585,9 +653,11 @@ class ProductionConfig(DjangoConfig):
585
653
  - **[Quick Start](https://djangocfg.com/docs/features/integrations/nextjs-admin/quick-start)** - 5-minute setup
586
654
  - **[Configuration](https://djangocfg.com/docs/features/integrations/nextjs-admin/configuration)** - All options
587
655
 
588
- ### 📡 Real-Time Features
656
+ ### 📡 Real-Time & Microservices
589
657
  - **[Centrifugo Integration](https://djangocfg.com/docs/features/integrations/centrifugo)** - WebSocket setup
590
658
  - **[Live Updates](https://djangocfg.com/docs/features/integrations/centrifugo/live-updates)** - Real-time data
659
+ - **[gRPC Streaming](https://djangocfg.com/docs/features/integrations/grpc)** - Bidirectional streaming
660
+ - **[gRPC → WebSocket Bridge](https://djangocfg.com/docs/features/integrations/grpc/centrifugo-bridge)** - Auto-publish to clients
591
661
 
592
662
  ### 🏗️ Core Features
593
663
  - **[Built-in Apps](https://djangocfg.com/docs/features/built-in-apps/overview)** - 8 enterprise apps
@@ -632,9 +702,9 @@ class ProductionConfig(DjangoConfig):
632
702
 
633
703
  <div align="center">
634
704
 
635
- **Modern Django Framework** • **Type-Safe Configuration** • **Next.js Admin** • **Real-Time WebSockets** • **AI-Ready**
705
+ **Modern Django Framework** • **Type-Safe Configuration** • **Next.js Admin** • **gRPC Streaming** • **Real-Time WebSockets** • **AI-Ready**
636
706
 
637
- Django-CFG is the modern Django framework for enterprise applications. Built with Pydantic v2 for type-safe configuration, includes Next.js admin integration, Centrifugo WebSocket support, AI agent framework, and 8 production-ready apps. Perfect for building scalable Django applications with reduced boilerplate and enterprise features out of the box.
707
+ Django-CFG is the modern Django framework for enterprise applications. Built with Pydantic v2 for type-safe configuration, includes Next.js admin integration, gRPC bidirectional streaming with WebSocket bridge, Centrifugo real-time support, AI agent framework, and 8 production-ready apps. Perfect for building scalable microservices and real-time Django applications with reduced boilerplate and enterprise features out of the box.
638
708
 
639
709
  ---
640
710