sp2-verify-1770324794/.sdlc/features/async-jobs/spec.md
rdev-worker 154c535204
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
build: /implement-feature async-jobs --requirements 'API: POST /jobs pushes ...
2026-02-05 21:04:47 +00:00

115 lines
2.7 KiB
Markdown

# Feature Specification: Async Jobs
**Feature:** async-jobs
**Status:** approved
**Author:** Claude
**Created:** 2026-02-05
## Overview
Implement an async job processing system using Redis as the job queue backend. The API service exposes endpoints to create and query jobs, while the background worker processes jobs from the Redis queue.
## Requirements
### Functional Requirements
1. **POST /api/api/jobs** - Create a new async job
- Accepts JSON payload with job type and data
- Pushes job to Redis queue
- Returns job ID and initial status ("pending")
2. **GET /api/api/jobs/{id}** - Get job status
- Returns current job status and metadata
- Statuses: pending, running, completed, failed
3. **Worker Processing**
- Worker pops jobs from Redis queue (blocking pop)
- Simulates work (configurable delay)
- Updates job status in Redis upon completion/failure
### Non-Functional Requirements
- Jobs must survive API restarts (persisted in Redis)
- Multiple workers can process jobs concurrently
- Job status queries must be fast (O(1) lookup)
## API Design
### Create Job
```
POST /api/api/jobs
Content-Type: application/json
{
"type": "process_data",
"payload": {
"key": "value"
}
}
```
Response (201 Created):
```json
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "process_data",
"status": "pending",
"created_at": "2026-02-05T10:00:00Z"
}
}
```
### Get Job Status
```
GET /api/api/jobs/{id}
```
Response (200 OK):
```json
{
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"type": "process_data",
"status": "completed",
"payload": {"key": "value"},
"created_at": "2026-02-05T10:00:00Z",
"started_at": "2026-02-05T10:00:01Z",
"completed_at": "2026-02-05T10:00:03Z"
}
}
```
## Data Model
### Job Structure (stored in Redis)
```go
type Job struct {
ID string `json:"id"`
Type string `json:"type"`
Payload map[string]any `json:"payload"`
Status string `json:"status"` // pending, running, completed, failed
CreatedAt time.Time `json:"created_at"`
StartedAt *time.Time `json:"started_at,omitempty"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
Error string `json:"error,omitempty"`
}
```
### Redis Keys
- `jobs:queue` - List for pending jobs (RPUSH/BLPOP)
- `jobs:data:{id}` - Hash for job metadata
## Acceptance Criteria
1. POST /api/api/jobs creates a job and returns 201 with job ID
2. GET /api/api/jobs/{id} returns job status
3. GET /api/api/jobs/{id} returns 404 for unknown jobs
4. Worker processes jobs from queue
5. Job status updates are visible via GET endpoint
6. Simulated work delay is configurable