feat: Add real-time queue depth indicator to viewer UI
Implements a visual badge that displays the count of active work items (queued + currently processing) in the worker service. The badge appears next to the claude-mem logo and updates in real-time via SSE. Features: - Shows count of pending messages + active SDK generators - Only displays when queueDepth > 0 - Subtle pulse animation for visual feedback - Theme-aware styling Backend changes: - Added getTotalActiveWork() method to SessionManager - Updated worker-service to broadcast queueDepth via SSE - Enhanced processing status API endpoint Frontend changes: - Updated Header component to display queue bubble - Enhanced useSSE hook to track queueDepth state - Added CSS styling with pulse animation Closes #122 Closes #96 Closes #97 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -322,9 +322,11 @@ export class WorkerService {
|
||||
|
||||
// Send initial processing status (based on queue depth + active generators)
|
||||
const isProcessing = this.sessionManager.isAnySessionProcessing();
|
||||
const queueDepth = this.sessionManager.getTotalActiveWork(); // Includes queued + actively processing
|
||||
this.sseBroadcaster.broadcast({
|
||||
type: 'processing_status',
|
||||
isProcessing
|
||||
isProcessing,
|
||||
queueDepth
|
||||
});
|
||||
}
|
||||
|
||||
@@ -806,11 +808,12 @@ export class WorkerService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get processing status (for viewer UI spinner)
|
||||
* Get processing status (for viewer UI spinner and queue indicator)
|
||||
*/
|
||||
private handleGetProcessingStatus(req: Request, res: Response): void {
|
||||
const isProcessing = this.sessionManager.isAnySessionProcessing();
|
||||
res.json({ isProcessing });
|
||||
const queueDepth = this.sessionManager.getTotalActiveWork(); // Includes queued + actively processing
|
||||
res.json({ isProcessing, queueDepth });
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -823,7 +826,7 @@ export class WorkerService {
|
||||
*/
|
||||
broadcastProcessingStatus(): void {
|
||||
const isProcessing = this.sessionManager.isAnySessionProcessing();
|
||||
const queueDepth = this.sessionManager.getTotalQueueDepth();
|
||||
const queueDepth = this.sessionManager.getTotalActiveWork(); // Includes queued + actively processing
|
||||
const activeSessions = this.sessionManager.getActiveSessionCount();
|
||||
|
||||
logger.info('WORKER', 'Broadcasting processing status', {
|
||||
@@ -834,7 +837,8 @@ export class WorkerService {
|
||||
|
||||
this.sseBroadcaster.broadcast({
|
||||
type: 'processing_status',
|
||||
isProcessing
|
||||
isProcessing,
|
||||
queueDepth
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -256,6 +256,23 @@ export class SessionManager {
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get total active work (queued + currently processing)
|
||||
* Counts both pending messages and items actively being processed by SDK agents
|
||||
*/
|
||||
getTotalActiveWork(): number {
|
||||
let total = 0;
|
||||
for (const session of this.sessions.values()) {
|
||||
// Count queued messages
|
||||
total += session.pendingMessages.length;
|
||||
// Count currently processing item (1 per active generator)
|
||||
if (session.generatorPromise !== null) {
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any session is actively processing (has pending messages OR active generator)
|
||||
* Used for activity indicator to prevent spinner from stopping while SDK is processing
|
||||
|
||||
Reference in New Issue
Block a user