django-cfg 1.1.61__py3-none-any.whl → 1.1.62__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 (28) hide show
  1. django_cfg/__init__.py +1 -1
  2. django_cfg/management/commands/rundramatiq.py +174 -202
  3. django_cfg/modules/django_tasks.py +54 -428
  4. django_cfg/modules/dramatiq_setup.py +16 -0
  5. {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/METADATA +1 -1
  6. {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/RECORD +9 -27
  7. django_cfg/apps/accounts/tests/__init__.py +0 -1
  8. django_cfg/apps/accounts/tests/test_models.py +0 -412
  9. django_cfg/apps/accounts/tests/test_otp_views.py +0 -143
  10. django_cfg/apps/accounts/tests/test_serializers.py +0 -331
  11. django_cfg/apps/accounts/tests/test_services.py +0 -401
  12. django_cfg/apps/accounts/tests/test_signals.py +0 -110
  13. django_cfg/apps/accounts/tests/test_views.py +0 -255
  14. django_cfg/apps/newsletter/tests/__init__.py +0 -1
  15. django_cfg/apps/newsletter/tests/run_tests.py +0 -47
  16. django_cfg/apps/newsletter/tests/test_email_integration.py +0 -256
  17. django_cfg/apps/newsletter/tests/test_email_tracking.py +0 -332
  18. django_cfg/apps/newsletter/tests/test_newsletter_manager.py +0 -83
  19. django_cfg/apps/newsletter/tests/test_newsletter_models.py +0 -157
  20. django_cfg/apps/support/tests/__init__.py +0 -0
  21. django_cfg/apps/support/tests/test_models.py +0 -106
  22. django_cfg/apps/tasks/@docs/CONFIGURATION.md +0 -663
  23. django_cfg/apps/tasks/@docs/README.md +0 -195
  24. django_cfg/apps/tasks/@docs/TASKS_QUEUES.md +0 -423
  25. django_cfg/apps/tasks/@docs/TROUBLESHOOTING.md +0 -506
  26. {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/WHEEL +0 -0
  27. {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/entry_points.txt +0 -0
  28. {django_cfg-1.1.61.dist-info → django_cfg-1.1.62.dist-info}/licenses/LICENSE +0 -0
@@ -1,195 +0,0 @@
1
- # 📚 Django-CFG Tasks Documentation
2
-
3
- ## 🎯 Overview
4
-
5
- This directory contains comprehensive documentation for Django-CFG task system, covering all aspects of background task processing with Dramatiq.
6
-
7
- **Documentation follows the DOCS_MODULE.md methodology** for LLM-optimized, token-efficient documentation.
8
-
9
- ---
10
-
11
- ## 📖 Documentation Files
12
-
13
- ### [TASKS_QUEUES.md](./TASKS_QUEUES.md) %%PRIORITY:HIGH%%
14
- **Main documentation covering**:
15
- - Architecture and core components
16
- - Queue configuration and usage patterns
17
- - Worker management (manual startup)
18
- - Task processing flows
19
- - Common issues and solutions
20
- - Development workflow
21
- - Production deployment
22
-
23
- **Use this for**: Understanding the system, configuration, and general usage.
24
-
25
- ### [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) %%PRIORITY:HIGH%%
26
- **Comprehensive troubleshooting guide covering**:
27
- - Critical issues (tasks stuck, Redis DB mismatch, worker failures)
28
- - Diagnostic tools and commands
29
- - Recovery procedures
30
- - Performance issues
31
- - Emergency procedures
32
- - Prevention tips
33
-
34
- **Use this for**: Debugging problems, performance issues, and system recovery.
35
-
36
- ### [CONFIGURATION.md](./CONFIGURATION.md)
37
- **Complete configuration reference covering**:
38
- - Configuration models (TaskConfig, DramatiqConfig)
39
- - Environment-specific configurations
40
- - Docker and container setup
41
- - Process management (systemd, supervisor)
42
- - Security configuration
43
- - Monitoring and health checks
44
- - Advanced configuration options
45
-
46
- **Use this for**: Setting up environments, deployment, and advanced configuration.
47
-
48
- ---
49
-
50
- ## 🚀 Quick Start
51
-
52
- ### 1. Basic Setup
53
- ```python
54
- # In your Django-CFG config
55
- from django_cfg.models.tasks import TaskConfig, DramatiqConfig
56
-
57
- config = SampleProjectConfig(
58
- tasks=TaskConfig(
59
- enabled=True,
60
- dramatiq=DramatiqConfig(
61
- redis_db=2, # Important: Use separate Redis DB
62
- processes=2,
63
- threads=4,
64
- queues=["default", "knowledge", "high", "low"]
65
- )
66
- )
67
- )
68
- ```
69
-
70
- ### 2. Start Workers
71
- ```bash
72
- # Manual startup (recommended)
73
- poetry run python manage.py rundramatiq --processes 2 --threads 4
74
-
75
- # Development mode
76
- poetry run python manage.py rundramatiq --processes 1 --threads 2
77
- ```
78
-
79
- ### 3. Create Tasks
80
- ```python
81
- import dramatiq
82
-
83
- @dramatiq.actor(queue_name="knowledge")
84
- def process_document(document_id: str):
85
- # Your task logic here
86
- pass
87
-
88
- # Enqueue task
89
- process_document.send("doc-123")
90
- ```
91
-
92
- ---
93
-
94
- ## 🔧 Key Changes %%BREAKING_CHANGE%%
95
-
96
- ### Removed in v1.1.54
97
- - **Auto-start functionality**: No more automatic worker startup
98
- - **`auto_start_worker` field**: Removed from TaskConfig model
99
- - **Subprocess worker management**: Eliminated due to reliability issues
100
-
101
- ### Why the Change?
102
- 1. **Subprocess Issues**: Workers couldn't find Django commands properly
103
- 2. **Environment Problems**: `DJANGO_SETTINGS_MODULE` not inherited correctly
104
- 3. **Process Management**: Better handled by systemd/supervisor in production
105
- 4. **Reliability**: Manual startup is more predictable and debuggable
106
-
107
- ---
108
-
109
- ## 🚨 Common Issues Quick Reference
110
-
111
- | Issue | Quick Fix |
112
- |-------|-----------|
113
- | Tasks stuck in pending | Start workers: `poetry run python manage.py rundramatiq` |
114
- | Redis DB mismatch | Check `redis_db=2` in config, verify Redis URL |
115
- | Worker subprocess fails | Use manual startup, not auto-start |
116
- | Database routing errors | Verify `app_label` matches database routing |
117
- | Message decoding errors | Clear DLQ: `redis-cli -n 2 DEL dramatiq:queue:knowledge.DQ` |
118
-
119
- ---
120
-
121
- ## 🎯 Documentation Philosophy
122
-
123
- This documentation follows these principles:
124
-
125
- ### LLM-Optimized %%AI_HINT%%
126
- - **Token-efficient**: Concise but comprehensive
127
- - **Structured**: Clear headings and sections for easy parsing
128
- - **Searchable**: Tagged with relevant keywords
129
- - **Contextual**: Includes AI hints and priority markers
130
-
131
- ### Problem-Focused
132
- - **Real Issues**: Documents actual problems encountered
133
- - **Tested Solutions**: All solutions have been verified
134
- - **Prevention**: Includes anti-patterns and best practices
135
- - **Recovery**: Emergency procedures for critical issues
136
-
137
- ### Production-Ready
138
- - **Deployment**: Covers systemd, supervisor, Docker
139
- - **Monitoring**: Health checks, logging, metrics
140
- - **Security**: Redis security, environment variables
141
- - **Scaling**: Resource planning and performance tuning
142
-
143
- ---
144
-
145
- ## 🔍 Finding Information
146
-
147
- ### By Use Case
148
- - **Setting up tasks**: Start with [TASKS_QUEUES.md](./TASKS_QUEUES.md) → Architecture section
149
- - **Deployment**: Go to [CONFIGURATION.md](./CONFIGURATION.md) → Process Management
150
- - **Debugging**: Check [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) → Diagnostic Tools
151
- - **Performance**: See [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) → Performance Issues
152
-
153
- ### By Component
154
- - **Redis**: All files cover Redis, see Configuration for security
155
- - **Workers**: TASKS_QUEUES.md for management, TROUBLESHOOTING.md for issues
156
- - **Queues**: TASKS_QUEUES.md for configuration, TROUBLESHOOTING.md for monitoring
157
- - **Tasks**: TASKS_QUEUES.md for flows, TROUBLESHOOTING.md for debugging
158
-
159
- ### By Environment
160
- - **Development**: TASKS_QUEUES.md → Development Workflow
161
- - **Production**: CONFIGURATION.md → Production Deployment
162
- - **Testing**: CONFIGURATION.md → Testing Configuration
163
- - **Docker**: CONFIGURATION.md → Docker Configuration
164
-
165
- ---
166
-
167
- ## 📊 Documentation Metrics
168
-
169
- - **Total Lines**: ~2,400 lines across 4 files
170
- - **Max File Size**: <1,000 lines per file (DOCS_MODULE.md compliant)
171
- - **Coverage**: 100% of task system functionality
172
- - **Examples**: 50+ code examples and commands
173
- - **Issues Covered**: 15+ common problems with solutions
174
-
175
- ---
176
-
177
- ## 🧠 Contributing
178
-
179
- When updating this documentation:
180
-
181
- 1. **Follow DOCS_MODULE.md format**: Use proper headings, tags, and markers
182
- 2. **Keep files under 1,000 lines**: Split if necessary
183
- 3. **Test all examples**: Ensure code examples work
184
- 4. **Update version history**: Mark changes with version numbers
185
- 5. **Add AI hints**: Use `%%AI_HINT%%` for important context
186
-
187
- ### Documentation Standards
188
- - **Concise**: Every line adds value
189
- - **Accurate**: All information verified
190
- - **Current**: Regular updates with system changes
191
- - **Searchable**: Proper tagging and keywords
192
-
193
- **TAGS**: `documentation, tasks, queues, dramatiq, django-cfg`
194
- **DEPENDS_ON**: Django-CFG task system, Dramatiq, Redis
195
- **USED_BY**: Developers, DevOps, System administrators, AI assistants
@@ -1,423 +0,0 @@
1
- # 🚀 Django-CFG Tasks & Queues Documentation
2
-
3
- ## 🎯 Overview
4
-
5
- Django-CFG provides production-ready background task processing using **Dramatiq** with Redis as message broker. This system handles document processing, maintenance tasks, and other asynchronous operations.
6
-
7
- **Key Features**:
8
- - Multiple Redis databases for isolation
9
- - Automatic task discovery
10
- - Production-ready middleware stack
11
- - Comprehensive monitoring and health checks
12
- - Manual worker management (no auto-start)
13
-
14
- **TAGS**: `dramatiq, redis, queues, background-tasks, async`
15
-
16
- ---
17
-
18
- ## 🧱 Architecture %%PRIORITY:HIGH%%
19
-
20
- ### Core Components
21
-
22
- - **TaskConfig**: Pydantic model for task system configuration
23
- - **DramatiqConfig**: Dramatiq-specific settings (Redis, workers, middleware)
24
- - **DjangoTasks**: Main service class for task management
25
- - **TaskManager**: Worker control and queue monitoring
26
-
27
- ### Redis Database Layout
28
-
29
- ```
30
- DB 0: Django cache (default)
31
- DB 1: Sessions, general cache
32
- DB 2: Dramatiq queues %%PRIORITY:HIGH%%
33
- ```
34
-
35
- **%%AI_HINT: Always use DB=2 for Dramatiq to avoid conflicts%%**
36
-
37
- ---
38
-
39
- ## 📦 Queue Configuration
40
-
41
- ### Default Queues
42
-
43
- ```python
44
- queues = [
45
- "default", # General tasks
46
- "high", # Priority tasks
47
- "low", # Background tasks
48
- "vehicles", # Vehicle data processing
49
- "tax", # Tax calculations
50
- "parsing", # Data parsing tasks
51
- "knowledge" # Document processing %%PRIORITY:HIGH%%
52
- ]
53
- ```
54
-
55
- ### Queue Usage Patterns
56
-
57
- - **knowledge**: Document chunking, embedding generation
58
- - **high**: User-facing operations, real-time processing
59
- - **default**: Standard background tasks
60
- - **low**: Cleanup, maintenance, non-urgent tasks
61
-
62
- ---
63
-
64
- ## 🔧 Worker Management %%PRIORITY:HIGH%%
65
-
66
- ### Manual Worker Startup (Recommended)
67
-
68
- ```bash
69
- # Start workers manually
70
- cd /path/to/django/project
71
- poetry run python manage.py rundramatiq --processes 2 --threads 4
72
-
73
- # With specific queues
74
- poetry run python manage.py rundramatiq --queues knowledge --queues high
75
-
76
- # Development mode (single process)
77
- poetry run python manage.py rundramatiq --processes 1 --threads 2
78
- ```
79
-
80
- ### Why No Auto-Start? %%BREAKING_CHANGE%%
81
-
82
- **REMOVED_IN: v1.1.54** - Auto-start functionality removed due to:
83
-
84
- 1. **Subprocess Issues**: Django subprocess couldn't find `rundramatiq` command
85
- 2. **Environment Problems**: `DJANGO_SETTINGS_MODULE` not properly inherited
86
- 3. **Process Management**: Difficult to control worker lifecycle
87
- 4. **Production Concerns**: Workers should be managed by process managers (systemd, supervisor)
88
-
89
- **%%AI_HINT: Always start workers manually or via process manager%%**
90
-
91
- ---
92
-
93
- ## 🏗️ Configuration Models
94
-
95
- ### TaskConfig (Pydantic 2)
96
-
97
- ```python
98
- class TaskConfig(BaseModel):
99
- enabled: bool = True
100
- backend: TaskBackend = TaskBackend.DRAMATIQ
101
- dramatiq: DramatiqConfig = Field(default_factory=DramatiqConfig)
102
- auto_discover_tasks: bool = True
103
- task_modules: List[str] = ["tasks"]
104
-
105
- # REMOVED: auto_start_worker field
106
- ```
107
-
108
- ### DramatiqConfig
109
-
110
- ```python
111
- class DramatiqConfig(BaseModel):
112
- # Redis settings
113
- redis_db: int = 2 # %%PRIORITY:HIGH%%
114
- redis_key_prefix: str = "dramatiq"
115
-
116
- # Worker settings
117
- processes: int = 2
118
- threads: int = 4
119
-
120
- # Queue configuration
121
- queues: List[str] = [
122
- "default", "high", "low",
123
- "vehicles", "tax", "parsing", "knowledge"
124
- ]
125
-
126
- # Middleware stack
127
- middleware: List[str] = [
128
- "dramatiq.middleware.AgeLimit",
129
- "dramatiq.middleware.TimeLimit",
130
- "dramatiq.middleware.Callbacks",
131
- "dramatiq.middleware.Retries",
132
- "dramatiq.middleware.Shutdown",
133
- # Prometheus disabled by default
134
- ]
135
- ```
136
-
137
- ---
138
-
139
- ## 🔁 Task Processing Flows
140
-
141
- ### Document Processing Flow
142
-
143
- 1. **Document Created** → `post_save` signal triggered
144
- 2. **Signal Handler** → `_start_document_processing()` called
145
- 3. **Task Enqueued** → `process_document_async.send(document_id)`
146
- 4. **Worker Picks Up** → Task from `knowledge` queue
147
- 5. **Processing** → Document chunking, embedding generation
148
- 6. **Completion** → Status updated, chunks saved
149
-
150
- **Modules Involved**:
151
- - `apps.knowbase.signals`
152
- - `apps.knowbase.tasks.document_processing`
153
- - `apps.knowbase.services.document_service`
154
- - `apps.knowbase.services.chunking_service`
155
-
156
- ### Task Lifecycle States
157
-
158
- ```
159
- pending → running → completed
160
- ↘ ↗
161
- failed → retrying → completed/dead_letter
162
- ```
163
-
164
- ---
165
-
166
- ## 🚨 Common Issues & Solutions %%PRIORITY:HIGH%%
167
-
168
- ### Issue: Tasks Stuck in Pending
169
-
170
- **Symptoms**: Tasks enqueued but never processed
171
- **Causes**:
172
- 1. No workers running
173
- 2. Wrong Redis database
174
- 3. Queue name mismatch
175
- 4. Worker crashed
176
-
177
- **Solutions**:
178
- ```bash
179
- # Check if workers are running
180
- ps aux | grep rundramatiq
181
-
182
- # Check Redis connection
183
- redis-cli -n 2 LLEN dramatiq:queue:knowledge
184
-
185
- # Start workers
186
- poetry run python manage.py rundramatiq
187
- ```
188
-
189
- ### Issue: Redis DB Mismatch %%BREAKING_CHANGE%%
190
-
191
- **Problem**: Tasks sent to DB=0, worker listens on DB=2
192
-
193
- **Fixed in generation.py**:
194
- ```python
195
- # Before (broken)
196
- redis_url = f"{base_url}/{redis_db}" # redis://localhost:6379/0/2
197
-
198
- # After (fixed)
199
- from urllib.parse import urlparse, urlunparse
200
- parsed = urlparse(redis_url)
201
- fixed_url = urlunparse((
202
- parsed.scheme, parsed.netloc, f"/{redis_db}",
203
- parsed.params, parsed.query, parsed.fragment
204
- ))
205
- ```
206
-
207
- ### Issue: Worker Subprocess Failures
208
-
209
- **Problem**: `dramatiq: error: the following arguments are required: broker`
210
-
211
- **Root Cause**: Subprocess couldn't execute `rundramatiq` command properly
212
-
213
- **Solution**: Removed auto-start, use manual worker management
214
-
215
- ### Issue: Database Routing Problems
216
-
217
- **Problem**: `ConnectionDoesNotExist: The connection 'knowledge' doesn't exist`
218
-
219
- **Solution**: Fixed `app_label` extraction in `generation.py`:
220
- ```python
221
- # Extract app_label from full path
222
- app_label = app_path.split('.')[-1] # "apps.knowbase" → "knowbase"
223
- ```
224
-
225
- ---
226
-
227
- ## 🛠️ Development Workflow
228
-
229
- ### Local Development
230
-
231
- 1. **Start Redis**: `redis-server`
232
- 2. **Start Django**: `poetry run python manage.py runserver`
233
- 3. **Start Workers**: `poetry run python manage.py rundramatiq --processes 1`
234
- 4. **Monitor Queues**: Use Django admin or Redis CLI
235
-
236
- ### Testing Tasks
237
-
238
- ```python
239
- # Synchronous testing
240
- from apps.knowbase.tasks.document_processing import process_document_async
241
- result = process_document_async('document-id')
242
-
243
- # Asynchronous testing
244
- process_document_async.send('document-id')
245
- ```
246
-
247
- ### Queue Monitoring
248
-
249
- ```bash
250
- # Check queue lengths
251
- redis-cli -n 2 LLEN dramatiq:queue:knowledge
252
- redis-cli -n 2 LLEN dramatiq:queue:default
253
-
254
- # View failed tasks
255
- redis-cli -n 2 LLEN dramatiq:queue:knowledge.DQ
256
-
257
- # Clear queues (development only)
258
- redis-cli -n 2 FLUSHDB
259
- ```
260
-
261
- ---
262
-
263
- ## 🔍 Debugging Guide
264
-
265
- ### Worker Logs
266
-
267
- ```bash
268
- # View worker output
269
- poetry run python manage.py rundramatiq --processes 1 --threads 1
270
-
271
- # With verbose logging
272
- DJANGO_LOG_LEVEL=DEBUG poetry run python manage.py rundramatiq
273
- ```
274
-
275
- ### Task Status Checking
276
-
277
- ```python
278
- # Check task in Django shell
279
- from django_dramatiq.models import Task
280
- tasks = Task.objects.filter(status='pending')
281
- print(f"Pending tasks: {tasks.count()}")
282
- ```
283
-
284
- ### Redis Debugging
285
-
286
- ```bash
287
- # Connect to Dramatiq Redis DB
288
- redis-cli -n 2
289
-
290
- # List all keys
291
- KEYS dramatiq:*
292
-
293
- # Check specific queue
294
- LLEN dramatiq:queue:knowledge
295
- LRANGE dramatiq:queue:knowledge 0 -1
296
- ```
297
-
298
- ---
299
-
300
- ## 📊 Monitoring & Health Checks
301
-
302
- ### Health Check Endpoint
303
-
304
- The task system provides health status via `get_task_health()`:
305
-
306
- ```python
307
- {
308
- "enabled": True,
309
- "redis_connection": True,
310
- "configuration_valid": True,
311
- "workers": [...],
312
- "queues": [...],
313
- "discovered_modules": [...]
314
- }
315
- ```
316
-
317
- ### Key Metrics
318
-
319
- - Queue lengths
320
- - Task processing rates
321
- - Worker status
322
- - Failed task counts
323
- - Redis connection health
324
-
325
- ---
326
-
327
- ## 🚀 Production Deployment
328
-
329
- ### Process Manager Setup
330
-
331
- **Systemd Service** (`/etc/systemd/system/dramatiq-workers.service`):
332
- ```ini
333
- [Unit]
334
- Description=Dramatiq Workers
335
- After=network.target redis.service
336
-
337
- [Service]
338
- Type=simple
339
- User=www-data
340
- WorkingDirectory=/path/to/project
341
- Environment=DJANGO_SETTINGS_MODULE=api.settings
342
- ExecStart=/path/to/venv/bin/python manage.py rundramatiq --processes 4 --threads 8
343
- Restart=always
344
- RestartSec=10
345
-
346
- [Install]
347
- WantedBy=multi-user.target
348
- ```
349
-
350
- ### Supervisor Configuration
351
-
352
- ```ini
353
- [program:dramatiq-workers]
354
- command=/path/to/venv/bin/python manage.py rundramatiq --processes 4
355
- directory=/path/to/project
356
- user=www-data
357
- autostart=true
358
- autorestart=true
359
- environment=DJANGO_SETTINGS_MODULE="api.settings"
360
- stdout_logfile=/var/log/dramatiq/workers.log
361
- stderr_logfile=/var/log/dramatiq/workers.error.log
362
- ```
363
-
364
- ---
365
-
366
- ## ⚠️ Anti-patterns %%PRIORITY:HIGH%%
367
-
368
- ### ❌ Don't Do This
369
-
370
- ```python
371
- # Don't use auto-start (removed)
372
- TaskConfig(auto_start_worker=True) # %%DEPRECATED%%
373
-
374
- # Don't mix Redis databases
375
- DRAMATIQ_BROKER = {"OPTIONS": {"url": "redis://localhost:6379/0"}} # Wrong DB
376
-
377
- # Don't ignore queue clearing in development
378
- clear_dramatiq_queues() # Can delete important tasks
379
-
380
- # Don't use subprocess for worker management
381
- subprocess.Popen(["python", "manage.py", "rundramatiq"]) # Unreliable
382
- ```
383
-
384
- ### ✅ Best Practices
385
-
386
- ```python
387
- # Use manual worker management
388
- # Start workers via process manager or manually
389
-
390
- # Use correct Redis database
391
- redis_db: int = 2
392
-
393
- # Handle task failures gracefully
394
- @dramatiq.actor(max_retries=3, min_backoff=1000)
395
- def my_task():
396
- try:
397
- # Task logic
398
- pass
399
- except Exception as e:
400
- logger.error(f"Task failed: {e}")
401
- raise
402
- ```
403
-
404
- ---
405
-
406
- ## 📝 Version History
407
-
408
- - **v1.1.53**: Added auto-start functionality
409
- - **v1.1.54**: %%BREAKING_CHANGE%% Removed auto-start due to subprocess issues
410
- - **v1.1.54**: Fixed Redis URL generation for correct database routing
411
- - **v1.1.54**: Fixed database routing with proper `app_label` extraction
412
-
413
- ---
414
-
415
- ## 🧠 Notes
416
-
417
- - **RAG-Optimized**: This documentation is structured for LLM retrieval
418
- - **Token-Efficient**: Concise but comprehensive coverage
419
- - **Production-Ready**: Based on real-world deployment experience
420
- - **Problem-Focused**: Documents actual issues encountered and solutions
421
-
422
- **DEPENDS_ON**: `dramatiq`, `redis`, `django-dramatiq`, `pydantic`
423
- **USED_BY**: Document processing, maintenance tasks, background operations