Skip to content

Commit b050cda

Browse files
authored
Merge branch 'main' into fixes-branch
2 parents 086bbbf + d6c50c9 commit b050cda

51 files changed

Lines changed: 3235 additions & 88 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ASYNC_RESPONSE_IMPLEMENTATION.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Async Response Semantics Implementation
2+
3+
## Overview
4+
Implemented standardized async response fields for endpoints returning 202 Accepted status, providing clients with consistent polling guidance and operation tracking.
5+
6+
## Standard Response Schema
7+
8+
### AsyncResponseDto
9+
Located at: `backend/src/common/dto/async-response.dto.ts`
10+
11+
**Required Fields:**
12+
- `statusCode`: HTTP status code (always 202 for async operations)
13+
- `message`: Human-readable message describing the operation
14+
- `operationId`: Unique identifier for tracking this operation
15+
- `retryAfterSeconds`: Recommended seconds to wait before polling the status endpoint
16+
- `statusEndpoint`: Endpoint to poll for operation status updates
17+
18+
**Optional Fields:**
19+
- `operationType`: Type of operation being performed (for client categorization)
20+
- `status`: Initial status of the operation
21+
- `metadata`: Additional operation-specific metadata
22+
23+
### AsyncResponseBuilder
24+
Helper class for constructing async responses with fluent API:
25+
- `setMessage(message)`: Set the response message
26+
- `setRetryAfterSeconds(seconds)`: Set polling interval
27+
- `setOperationType(type)`: Set operation type
28+
- `setStatus(status)`: Set initial status
29+
- `setMetadata(metadata)`: Set additional metadata
30+
31+
## Migrated Endpoints
32+
33+
### 1. Data Export Endpoint
34+
**File:** `backend/src/modules/data-export/data-export.controller.ts`
35+
**Endpoint:** `POST /users/data/export`
36+
37+
**Response Example:**
38+
```json
39+
{
40+
"statusCode": 202,
41+
"message": "Export request received and queued. You will receive an email when your data is ready.",
42+
"operationId": "550e8400-e29b-41d4-a716-446655440000",
43+
"retryAfterSeconds": 10,
44+
"statusEndpoint": "/users/data/export/550e8400-e29b-41d4-a716-446655440000/status",
45+
"operationType": "data-export",
46+
"status": "pending"
47+
}
48+
```
49+
50+
### 2. Analytics Export Endpoints
51+
**File:** `backend/src/modules/statistics/statistics.controller.ts`
52+
**Endpoints:**
53+
- `POST /admin/statistics/export/:dataType/jobs`
54+
- `GET /admin/statistics/export/:dataType` (legacy route)
55+
56+
**Response Example:**
57+
```json
58+
{
59+
"statusCode": 202,
60+
"message": "Analytics export job queued successfully",
61+
"operationId": "550e8400-e29b-41d4-a716-446655440000",
62+
"retryAfterSeconds": 15,
63+
"statusEndpoint": "/admin/statistics/export/jobs/550e8400-e29b-41d4-a716-446655440000",
64+
"operationType": "analytics-export",
65+
"status": "pending",
66+
"metadata": {
67+
"dataType": "all",
68+
"format": "json"
69+
}
70+
}
71+
```
72+
73+
### 3. Tax Report Generation Endpoint
74+
**File:** `backend/src/modules/reports/reports.controller.ts`
75+
**Endpoint:** `POST /reports/tax/:year/async`
76+
77+
**Response Example:**
78+
```json
79+
{
80+
"statusCode": 202,
81+
"message": "Tax report generation queued successfully",
82+
"operationId": "12345",
83+
"retryAfterSeconds": 10,
84+
"statusEndpoint": "/reports/jobs/12345/status",
85+
"operationType": "report-generation",
86+
"status": "pending",
87+
"metadata": {
88+
"reportType": "tax",
89+
"year": 2024,
90+
"format": "csv"
91+
}
92+
}
93+
```
94+
95+
## Tests
96+
97+
### Unit Tests
98+
**File:** `backend/src/common/dto/async-response.dto.spec.ts`
99+
- Validates AsyncResponseDto structure
100+
- Tests AsyncResponseBuilder fluent API
101+
- Verifies method chaining
102+
- Tests error handling for missing required fields
103+
104+
### Controller Tests
105+
**File:** `backend/src/modules/data-export/data-export.controller.spec.ts`
106+
- Validates async response schema from data export endpoint
107+
- Verifies correct field values (statusCode, operationId, retryAfterSeconds, statusEndpoint)
108+
- Tests status endpoint construction with operation ID
109+
- Validates service integration
110+
111+
## Usage Pattern
112+
113+
```typescript
114+
import { AsyncResponseBuilder } from '../../common/dto';
115+
116+
const result = await someService.queueOperation(params);
117+
return new AsyncResponseBuilder(
118+
result.operationId,
119+
`/operations/${result.operationId}/status`,
120+
)
121+
.setMessage('Operation queued successfully')
122+
.setRetryAfterSeconds(10)
123+
.setOperationType('operation-type')
124+
.setStatus('pending')
125+
.setMetadata({ /* operation-specific data */ })
126+
.build();
127+
```
128+
129+
## Consistency Across Async Operations
130+
131+
The implementation ensures consistency across:
132+
- **Exports**: Data export, analytics export
133+
- **Background Processing**: Report generation, backup operations
134+
- **Webhook-triggered Jobs**: Can be extended to webhook-triggered async operations
135+
136+
All async endpoints now return the same response structure, enabling clients to:
137+
1. Poll at consistent intervals based on `retryAfterSeconds`
138+
2. Track operations using `operationId`
139+
3. Query status using the provided `statusEndpoint`
140+
4. Categorize operations using `operationType`
141+
142+
## Acceptance Criteria Met
143+
144+
✅ Standard response schema implemented with required fields (retryAfterSeconds, operationId, statusEndpoint)
145+
✅ At least 2 async endpoints migrated (3 endpoints migrated: data export, analytics export, report generation)
146+
✅ Tests validate schema and values (unit tests for DTO/builder, integration tests for controller)

0 commit comments

Comments
 (0)