Async Exports Component¶
Table of Contents¶
- Context
- Overview
- Usage
- Implementation Guide
- Architecture
- Interface Reference
- REST API Reference
- Configuration
- Testing
- Monitoring
- Common Pitfalls
- References
Context¶
- Scope: Global
- Ownership: Health Insurance Affiliation & Global Customer Dashboard
- Purpose: Provides asynchronous export capabilities for large datasets across countries
- Architecture: Global component with scope-based routing (global APIs + legacy dependency injection)
- Tech framing: Global async export component #30249 ⧉
Overview¶
The async exports component enables the asynchronous generation and processing of large data exports (CSV, Excel, etc.) without blocking web requests. It provides a complete workflow from request creation to file delivery via email notifications.
Usage¶
For Global Components (Recommended Approach)¶
This is the preferred approach as we move toward globalization. Global exports call directly to global component public APIs:
- Add your export type to the
ExportTypeenum andExportConfig.EXPORT_DEFINITIONS - Implement the export function in your global component's public API
- Add the function call to the global export handler in the worker
- Use the REST API to create export requests
For Local Components (Legacy Pattern)¶
Use this pattern only for country-specific functionality that are not globalized yet:
- Create a local dependency implementation by extending
AsyncExportsDependency - Implement the
generate_exportmethod with your country-specific export logic - Register the dependency during app initialization
- Use the REST API to create export requests
Implementation Guide¶
Step 1: Add New Export Type Configuration¶
All export types must be configured in components/async_exports/public/enums/export_type.py:
class ExportType(AlanBaseEnum):
employees = "employees"
exemptions = "exemptions"
your_new_export = "your_new_export" # Add your export type here
class ExportConfig:
EXPORT_DEFINITIONS: dict[ExportType, ExportConfiguration] = {
# Existing exports...
ExportType("your_new_export"): ExportConfiguration(
scope="global", # "global" for global components, "local" for country-specific
retention_period_days=7 # How long to keep the export files before deletion
),
}
Step 2A: Global Component Implementation (Recommended)¶
For global exports:
- Implement function in
components/your_global_component/public/actions/export.py - Add import and call in
components/async_exports/internal/workers/export_worker.pyin the_generate_global_component_exportfunction
Function signature must match the Interface Reference above.
Step 2B: Local Component Implementation (Legacy)¶
For local exports:
- Create dependency class extending
AsyncExportsDependencyincomponents/{country}/bootstrap/dependencies/async_exports.py - Implement
generate_exportmethod matching the Interface Reference signature - Register dependency in your app's
components_config.pyusingset_app_dependency
See France implementation example: components/fr/bootstrap/dependencies/async_exports.py
Step 3: Adapt Email notifications¶
- Add your translation and link for the email notifications in
components/async_exports/notification/fr/generator.pyso that your new export type can be matched to the correct email content.
Step 4: API Usage Examples¶
Create Export Request (POST):
{
"export_type": "your_export_type",
"file_format": "csv",
"filters": {"status": "active"},
"context_account_id": "account-uuid",
"company_ids": ["123", "456"]
}
List Export Results (GET):
Architecture¶
Key Components¶
- ExportRequest/ExportResult: Database models for tracking export lifecycle
- GeneratedExportData: Interface data transfer object
- Export Worker: Background job processor (Redis Queue)
- S3 Service: File storage and URL generation
- Email Notifications: User notifications for completed exports
Flow¶
- API Call → Create
ExportRequest→ Queue background job - Worker → Determine scope → Call global API or local dependency
- Storage → Upload to S3 → Email notification → Auto-cleanup
Interface Reference¶
Export Function Signature (Both Global & Local)¶
Both global and local implementations must match this signature:
Parameters & Returns¶
Input Parameters:
- filters: Optional filtering criteria as key-value pairs
- file_format: Output format (CSV, Excel, etc.)
- company_ids: List of company IDs for authorization context
- operational_scope_ids: List of operational scope IDs for filtering
Returns GeneratedExportData:
- file_content: File stream/buffer with the export data
- mimetype: MIME type for the generated file
- items_count: Number of items in the export
Implementation Requirements¶
- Authorization: Respect provided company and operational scope IDs
- Filtering: Handle the filters parameter for user-defined criteria
- Error Handling: Raise exceptions that will be caught by the worker
- File Formats: Support at least CSV, consider Excel for complex data
REST API Reference¶
Base URL: /api/async_exports
POST - Create Export¶
- Creates new export request
- Returns export ID for tracking
GET - List Exports¶
- Lists user's export requests with filtering
- Returns export metadata, processing status and outcome
Full API Documentation: Admin Tools API ⧉
Configuration¶
- Queue: Redis Queue with retry policy and dedicated
async_exportsqueue - Storage: S3 for temporary file storage
- S3 Buckets:
async-exports-prod,async-exports-demo,async-exports-acceptance, - Retention: Per-export-type retention periods in
ExportConfig.EXPORT_DEFINITIONS - Email: Notifications sent for exports taking >45 seconds
Testing¶
Unit Tests: Test export implementation with mocked dependencies
Integration Tests: Test via REST API with real workflow
Monitoring¶
- APM: Datadog monitoring ⧉
- Logs: Structured with export_request_id context
- Alerts: Sentry error tracking
- Metrics: Success rates, processing times, file sizes
Common Pitfalls¶
- Memory: Stream data instead of loading everything into memory
- Timeouts: Implement chunking for very large exports
- Authorization: Always validate company/scope access
- Configuration: Add export types to
ExportConfig.EXPORT_DEFINITIONS - Scope Choice: Use "global" unless you have country-specific needs
References¶
- Global Example:
components/global_customer_dashboard/public/actions/employee - Local Example:
components/fr/bootstrap/dependencies/async_exports.pyapps/fr_api/components_config.py- Worker:
components/async_exports/internal/workers/export_worker.py - Full Documentation ⧉ (available after next docs build)
- Tech Framing: Global async export component #30249 ⧉