# Async Image Processing Implementation

## Overview

The image processing system has been updated to handle external images asynchronously, preventing timeouts when processing stories with many images. This provides real-time progress updates to users showing which images are being processed.

## Backend Components

### 1. `ImageProcessingProgressService`
- Tracks progress for individual story image processing sessions
- Thread-safe with `ConcurrentHashMap` for multi-user support
- Provides progress information: total images, processed count, current image, status, errors

### 2. `AsyncImageProcessingService`
- Handles asynchronous image processing using Spring's `@Async` annotation
- Counts external images before processing
- Provides progress callbacks during processing
- Updates story content when processing completes
- Automatic cleanup of progress data after completion

### 3. Enhanced `ImageService`
- Added `processContentImagesWithProgress()` method with callback support
- Progress callbacks provide real-time updates during image download/processing
- Maintains compatibility with existing synchronous processing

### 4. Updated `StoryController`
- `POST /api/stories` and `PUT /api/stories/{id}` now trigger async image processing
- `GET /api/stories/{id}/image-processing-progress` endpoint for progress polling
- Processing starts immediately after story save and returns control to user

## Frontend Components

### 1. `ImageProcessingProgressTracker` (Utility Class)
```typescript
const tracker = new ImageProcessingProgressTracker(storyId);
tracker.onProgress((progress) => {
  console.log(`Processing ${progress.processedImages}/${progress.totalImages}`);
});
tracker.onComplete(() => console.log('Done!'));
tracker.start();
```

### 2. `ImageProcessingProgressComponent` (React Component)
```tsx
<ImageProcessingProgressComponent
  storyId={storyId}
  autoStart={true}
  onComplete={() => refreshStory()}
/>
```

## User Experience

### Before (Synchronous)
1. User saves story with external images
2. Request hangs for 30+ seconds processing images
3. Browser may timeout
4. No feedback about progress
5. User doesn't know if it's working

### After (Asynchronous)
1. User saves story with external images
2. Save completes immediately
3. Progress indicator appears: "Processing 5 images. Currently image 2 of 5..."
4. User can continue using the application
5. Progress updates every second
6. Story automatically refreshes when processing completes

## API Endpoints

### Progress Endpoint
```
GET /api/stories/{id}/image-processing-progress
```

**Response when processing:**
```json
{
  "isProcessing": true,
  "totalImages": 5,
  "processedImages": 2,
  "currentImageUrl": "https://example.com/image.jpg",
  "status": "Processing image 3 of 5",
  "progressPercentage": 40.0,
  "completed": false,
  "error": ""
}
```

**Response when completed:**
```json
{
  "isProcessing": false,
  "totalImages": 5,
  "processedImages": 5,
  "currentImageUrl": "",
  "status": "Completed: 5 images processed",
  "progressPercentage": 100.0,
  "completed": true,
  "error": ""
}
```

**Response when no processing:**
```json
{
  "isProcessing": false,
  "message": "No active image processing"
}
```

## Integration Examples

### React Hook Usage
```tsx
import { useImageProcessingProgress } from '../utils/imageProcessingProgress';

function StoryEditor({ storyId }) {
  const { progress, isTracking, startTracking } = useImageProcessingProgress(storyId);

  const handleSave = async () => {
    await saveStory();
    startTracking(); // Start monitoring progress
  };

  return (
    <div>
      {isTracking && progress && (
        <div className="progress-indicator">
          Processing {progress.processedImages}/{progress.totalImages} images...
        </div>
      )}
      <button onClick={handleSave}>Save Story</button>
    </div>
  );
}
```

### Manual Progress Tracking
```typescript
// After saving a story with external images
const tracker = new ImageProcessingProgressTracker(storyId);

tracker.onProgress((progress) => {
  updateProgressBar(progress.progressPercentage);
  showStatus(progress.status);
  if (progress.currentImageUrl) {
    showCurrentImage(progress.currentImageUrl);
  }
});

tracker.onComplete((finalProgress) => {
  hideProgressBar();
  showNotification('Image processing completed!');
  refreshStoryContent(); // Reload story with processed images
});

tracker.onError((error) => {
  hideProgressBar();
  showError(`Image processing failed: ${error}`);
});

tracker.start();
```

## Configuration

### Polling Interval
Default: 1 second (1000ms)
```typescript
const tracker = new ImageProcessingProgressTracker(storyId, 500); // Poll every 500ms
```

### Timeout
Default: 5 minutes (300000ms)
```typescript
const tracker = new ImageProcessingProgressTracker(storyId, 1000, 600000); // 10 minute timeout
```

### Spring Async Configuration
The backend uses Spring's default async executor. For production, consider configuring a custom thread pool in your application properties:

```yaml
spring:
  task:
    execution:
      pool:
        core-size: 4
        max-size: 8
        queue-capacity: 100
```

## Error Handling

### Backend Errors
- Network timeouts downloading images
- Invalid image formats
- Disk space issues
- All errors are logged and returned in progress status

### Frontend Errors
- Network failures during progress polling
- Timeout if processing takes too long
- Graceful degradation - user can continue working

## Benefits

1. **No More Timeouts**: Large image processing operations won't timeout HTTP requests
2. **Better UX**: Users get real-time feedback about processing progress
3. **Improved Performance**: Users can continue using the app while images process
4. **Error Visibility**: Clear error messages when image processing fails
5. **Scalability**: Multiple users can process images simultaneously without blocking

## Future Enhancements

1. **WebSocket Support**: Replace polling with WebSocket for real-time push updates
2. **Batch Processing**: Queue multiple stories for batch image processing
3. **Retry Logic**: Automatic retry for failed image downloads
4. **Progress Persistence**: Save progress to database for recovery after server restart
5. **Image Optimization**: Automatic resize/compress images during processing