feat(#71): implement graph data API
Implemented three new API endpoints for knowledge graph visualization: 1. GET /api/knowledge/graph - Full knowledge graph - Returns all entries and links with optional filtering - Supports filtering by tags, status, and node count limit - Includes orphan detection (entries with no links) 2. GET /api/knowledge/graph/stats - Graph statistics - Total entries and links counts - Orphan entries detection - Average links per entry - Top 10 most connected entries - Tag distribution across entries 3. GET /api/knowledge/graph/:slug - Entry-centered subgraph - Returns graph centered on specific entry - Supports depth parameter (1-5) for traversal distance - Includes all connected nodes up to specified depth New Files: - apps/api/src/knowledge/graph.controller.ts - apps/api/src/knowledge/graph.controller.spec.ts Modified Files: - apps/api/src/knowledge/dto/graph-query.dto.ts (added GraphFilterDto) - apps/api/src/knowledge/entities/graph.entity.ts (extended with new types) - apps/api/src/knowledge/services/graph.service.ts (added new methods) - apps/api/src/knowledge/services/graph.service.spec.ts (added tests) - apps/api/src/knowledge/knowledge.module.ts (registered controller) - apps/api/src/knowledge/dto/index.ts (exported new DTOs) - docs/scratchpads/71-graph-data-api.md (implementation notes) Test Coverage: 21 tests (all passing) - 14 service tests including orphan detection, filtering, statistics - 7 controller tests for all three endpoints Follows TDD principles with tests written before implementation. All code quality gates passed (lint, typecheck, tests). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
245
apps/orchestrator/src/queue/README.md
Normal file
245
apps/orchestrator/src/queue/README.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# Queue Module
|
||||
|
||||
BullMQ-based task queue with priority ordering and retry logic.
|
||||
|
||||
## Overview
|
||||
|
||||
The Queue module provides a robust task queuing system for the orchestrator service using BullMQ and Valkey (Redis-compatible). It supports priority-based task ordering, exponential backoff retry logic, and real-time queue monitoring.
|
||||
|
||||
## Features
|
||||
|
||||
- **Priority-based ordering** (1-10): Higher priority tasks processed first
|
||||
- **Retry logic**: Exponential backoff on failures
|
||||
- **Queue monitoring**: Real-time statistics (pending, active, completed, failed)
|
||||
- **Queue control**: Pause/resume processing
|
||||
- **Event pub/sub**: Task lifecycle events published to Valkey
|
||||
- **Task removal**: Remove tasks from queue
|
||||
|
||||
## Usage
|
||||
|
||||
### Adding Tasks
|
||||
|
||||
```typescript
|
||||
import { QueueService } from './queue/queue.service';
|
||||
|
||||
@Injectable()
|
||||
export class MyService {
|
||||
constructor(private readonly queueService: QueueService) {}
|
||||
|
||||
async createTask() {
|
||||
const context = {
|
||||
repository: 'my-org/my-repo',
|
||||
branch: 'main',
|
||||
workItems: ['task-1', 'task-2'],
|
||||
};
|
||||
|
||||
// Add task with default options (priority 5, maxRetries 3)
|
||||
await this.queueService.addTask('task-123', context);
|
||||
|
||||
// Add high-priority task with custom retries
|
||||
await this.queueService.addTask('urgent-task', context, {
|
||||
priority: 10, // Highest priority
|
||||
maxRetries: 5,
|
||||
});
|
||||
|
||||
// Add delayed task (5 second delay)
|
||||
await this.queueService.addTask('delayed-task', context, {
|
||||
delay: 5000,
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Monitoring Queue
|
||||
|
||||
```typescript
|
||||
async function monitorQueue() {
|
||||
const stats = await this.queueService.getStats();
|
||||
console.log(stats);
|
||||
// {
|
||||
// pending: 5,
|
||||
// active: 2,
|
||||
// completed: 10,
|
||||
// failed: 1,
|
||||
// delayed: 0
|
||||
// }
|
||||
}
|
||||
```
|
||||
|
||||
### Queue Control
|
||||
|
||||
```typescript
|
||||
// Pause queue processing
|
||||
await this.queueService.pause();
|
||||
|
||||
// Resume queue processing
|
||||
await this.queueService.resume();
|
||||
|
||||
// Remove task from queue
|
||||
await this.queueService.removeTask('task-123');
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Configure via environment variables:
|
||||
|
||||
```bash
|
||||
# Valkey connection
|
||||
ORCHESTRATOR_VALKEY_HOST=localhost
|
||||
ORCHESTRATOR_VALKEY_PORT=6379
|
||||
ORCHESTRATOR_VALKEY_PASSWORD=secret
|
||||
|
||||
# Queue configuration
|
||||
ORCHESTRATOR_QUEUE_NAME=orchestrator-tasks
|
||||
ORCHESTRATOR_QUEUE_MAX_RETRIES=3
|
||||
ORCHESTRATOR_QUEUE_BASE_DELAY=1000 # 1 second
|
||||
ORCHESTRATOR_QUEUE_MAX_DELAY=60000 # 1 minute
|
||||
ORCHESTRATOR_QUEUE_CONCURRENCY=5 # 5 concurrent workers
|
||||
```
|
||||
|
||||
## Priority
|
||||
|
||||
Priority range: 1-10
|
||||
|
||||
- **10**: Highest priority (processed first)
|
||||
- **5**: Default priority
|
||||
- **1**: Lowest priority (processed last)
|
||||
|
||||
Internally, priorities are inverted for BullMQ (which uses lower numbers for higher priority).
|
||||
|
||||
## Retry Logic
|
||||
|
||||
Failed tasks are automatically retried with exponential backoff:
|
||||
|
||||
- **Attempt 1**: Wait 2 seconds (baseDelay * 2^1)
|
||||
- **Attempt 2**: Wait 4 seconds (baseDelay * 2^2)
|
||||
- **Attempt 3**: Wait 8 seconds (baseDelay * 2^3)
|
||||
- **Attempt 4+**: Capped at maxDelay (default 60 seconds)
|
||||
|
||||
Configure retry behavior:
|
||||
- `maxRetries`: Number of retry attempts (default: 3)
|
||||
- `baseDelay`: Base delay in milliseconds (default: 1000)
|
||||
- `maxDelay`: Maximum delay cap (default: 60000)
|
||||
|
||||
## Events
|
||||
|
||||
The queue publishes events to Valkey pub/sub:
|
||||
|
||||
- `task.queued`: Task added to queue
|
||||
- `task.processing`: Task started processing
|
||||
- `task.retry`: Task retrying after failure
|
||||
- `task.completed`: Task completed successfully
|
||||
- `task.failed`: Task failed permanently
|
||||
|
||||
Subscribe to events:
|
||||
|
||||
```typescript
|
||||
await valkeyService.subscribeToEvents((event) => {
|
||||
if (event.type === 'task.completed') {
|
||||
console.log('Task completed:', event.data.taskId);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────┐
|
||||
│ QueueService│
|
||||
└──────┬──────┘
|
||||
│
|
||||
├──────────> BullMQ Queue (adds tasks)
|
||||
│
|
||||
├──────────> BullMQ Worker (processes tasks)
|
||||
│
|
||||
└──────────> ValkeyService (state + events)
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
1. **QueueService**: Main service for queue operations
|
||||
2. **BullMQ Queue**: Task queue with priority and retry
|
||||
3. **BullMQ Worker**: Processes tasks from queue
|
||||
4. **ValkeyService**: State management and pub/sub
|
||||
|
||||
## Types
|
||||
|
||||
### QueuedTask
|
||||
|
||||
```typescript
|
||||
interface QueuedTask {
|
||||
taskId: string;
|
||||
priority: number; // 1-10
|
||||
retries: number;
|
||||
maxRetries: number;
|
||||
context: TaskContext;
|
||||
}
|
||||
```
|
||||
|
||||
### AddTaskOptions
|
||||
|
||||
```typescript
|
||||
interface AddTaskOptions {
|
||||
priority?: number; // 1-10, default 5
|
||||
maxRetries?: number; // default 3
|
||||
delay?: number; // delay in milliseconds
|
||||
}
|
||||
```
|
||||
|
||||
### QueueStats
|
||||
|
||||
```typescript
|
||||
interface QueueStats {
|
||||
pending: number;
|
||||
active: number;
|
||||
completed: number;
|
||||
failed: number;
|
||||
delayed: number;
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
Validation errors:
|
||||
- `Priority must be between 1 and 10`: Invalid priority value
|
||||
- `maxRetries must be non-negative`: Negative retry count
|
||||
|
||||
Task processing errors:
|
||||
- Automatically retried up to `maxRetries`
|
||||
- Published as `task.failed` event after final failure
|
||||
- Error details stored in Valkey state
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```bash
|
||||
pnpm test queue.service.spec.ts
|
||||
```
|
||||
|
||||
Tests pure functions (calculateBackoffDelay, configuration).
|
||||
|
||||
### Integration Tests
|
||||
|
||||
Integration tests require a running Valkey instance:
|
||||
|
||||
```bash
|
||||
# Start Valkey
|
||||
docker run -p 6379:6379 valkey/valkey:latest
|
||||
|
||||
# Run integration tests
|
||||
pnpm test queue.integration.spec.ts
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `bullmq`: Task queue
|
||||
- `ioredis`: Redis/Valkey client (via ValkeyService)
|
||||
- `@nestjs/common`: NestJS dependency injection
|
||||
- `@nestjs/config`: Configuration management
|
||||
|
||||
## Related
|
||||
|
||||
- `ValkeyModule`: State management and pub/sub
|
||||
- `ORCH-107`: Valkey client implementation
|
||||
- `ORCH-109`: Agent lifecycle management (uses queue)
|
||||
Reference in New Issue
Block a user