Chat — Tasks¶
Overview¶
The chat.tasks module contains background jobs responsible for maintaining data hygiene and system health.
Currently, the primary task focuses on:
- cleaning up unused file uploads (attachments)
This prevents:
- storage bloat
- orphaned files
- unnecessary database growth
Task: cleanup_orphan_attachments¶
Purpose¶
This task removes attachments that were uploaded but never linked to a message.
In the chat system, attachments follow a two-step flow:
- upload attachment via REST
- attach it to a message via websocket
If step 2 never happens, the attachment becomes orphaned.
This task ensures those unused files are eventually cleaned up.
Behavior¶
The task:
- calculates a cutoff timestamp based on a configurable number of hours
- finds all attachments that:
- are not linked to any message
- were created before the cutoff time
- deletes:
- the file from storage
- the database record
- returns the number of deleted attachments
Key rules¶
An attachment is considered orphaned when:
messageis nullcreated_atis older than the cutoff time
Data flow¶
flowchart TD
A[Start task] --> B[Compute cutoff time]
B --> C[Query orphan attachments]
C --> D[Iterate attachments]
D --> E[Delete file from storage]
E --> F[Delete DB record]
F --> G[Count deletions]
G --> H[Return result]
Parameters¶
hours¶
- type: integer
- default: 24
Defines how old an attachment must be before it is considered safe to delete.
Why this task exists¶
Upload-first workflow¶
Attachments are uploaded before message creation.
This creates a temporary state where attachments exist without a message.
Failure scenarios¶
Orphaned attachments can occur when:
- user cancels message sending
- websocket fails after upload
- client crashes or disconnects
- attachment is uploaded but never used
Without cleanup:
- files accumulate indefinitely
- storage costs increase
- database becomes cluttered
Scheduling¶
This task should be scheduled periodically using Celery Beat or a similar scheduler.
Recommended frequency:
- every hour
- or every few hours depending on traffic
Safety considerations¶
Time buffer¶
The hours parameter ensures:
- recent uploads are not deleted prematurely
- users have time to send messages after uploading
Ownership constraints¶
Only attachments with:
- no linked message
are deleted.
This guarantees:
- no data loss for valid messages
Performance considerations¶
- query is indexed by created_at and message
- iteration is done in Python (can be optimized with batching if needed)
- file deletion may be IO-heavy depending on storage backend
For large datasets, consider:
- batch deletion
- chunked queries
- async storage backends
Storage considerations¶
The task deletes:
- file from storage (att.file.delete)
- database record (att.delete())
This ensures:
- no orphaned files remain on disk or cloud storage
Failure handling¶
If the task fails mid-run:
- already deleted attachments remain deleted
- remaining attachments will be retried in the next run
The task is idempotent for remaining records.
Observability¶
The task returns:
- number of deleted attachments
This can be used for:
- logging
- monitoring
- alerting if deletion spikes unexpectedly
Relationship to other layers¶
Views layer¶
- handles attachment uploads
Consumers layer¶
- links attachments to messages
Services layer¶
- orchestrates message creation and attachment linking
Tasks layer¶
- cleans up unused attachments
What this task does not do¶
This task does not:
- delete attachments linked to messages
- validate file content
- enforce upload limits
- notify users
- manage permissions
It is strictly a cleanup mechanism.
Future improvements¶
Possible enhancements include:
- batch deletion for large datasets
- logging integration
- metrics export (e.g. Prometheus)
- configurable retention policies per org
- soft-delete instead of hard-delete (if audit required)
Summary¶
The cleanup_orphan_attachments task ensures that unused uploaded files are removed safely and efficiently.
It supports the upload-first attachment workflow while preventing:
- storage leaks
- database clutter
- long-term orphaned data accumulation