114 lines
No EOL
2.8 KiB
TypeScript
Executable file
114 lines
No EOL
2.8 KiB
TypeScript
Executable file
/**
|
|
* Task cancellation utilities for long-running generation processes.
|
|
*/
|
|
|
|
import { toast } from 'sonner';
|
|
|
|
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || '/api';
|
|
|
|
export interface TaskCancellationResponse {
|
|
success: boolean;
|
|
message?: string;
|
|
error?: string;
|
|
}
|
|
|
|
/**
|
|
* Cancel a task by its ID
|
|
*/
|
|
export async function cancelTask(taskId: string): Promise<TaskCancellationResponse> {
|
|
try {
|
|
const url = `${API_BASE_URL}/tasks/${taskId}`;
|
|
|
|
const response = await fetch(url, {
|
|
method: 'DELETE',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
|
|
if (!response.ok) {
|
|
if (response.status === 404) {
|
|
return {
|
|
success: false,
|
|
error: 'Task not found or already completed',
|
|
};
|
|
}
|
|
|
|
const errorData = await response.json().catch(() => ({}));
|
|
return {
|
|
success: false,
|
|
error: errorData.error || `Failed to cancel task: ${response.statusText}`,
|
|
};
|
|
}
|
|
|
|
const data = await response.json();
|
|
return {
|
|
success: true,
|
|
message: data.message || 'Task cancelled successfully',
|
|
};
|
|
} catch (error) {
|
|
console.error('Error cancelling task:', error);
|
|
return {
|
|
success: false,
|
|
error: error instanceof Error ? error.message : 'Network error while cancelling task',
|
|
};
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cancel a task with user feedback
|
|
*/
|
|
export async function cancelTaskWithFeedback(taskId: string, taskDescription: string = 'task'): Promise<boolean> {
|
|
try {
|
|
const result = await cancelTask(taskId);
|
|
|
|
if (result.success) {
|
|
toast.success(result.message || `${taskDescription} cancelled successfully`);
|
|
return true;
|
|
} else {
|
|
toast.error(result.error || `Failed to cancel ${taskDescription}`);
|
|
return false;
|
|
}
|
|
} catch (error) {
|
|
console.error('Error cancelling task with feedback:', error);
|
|
toast.error(`Failed to cancel ${taskDescription}`);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Hook-style function for creating a cancellation handler
|
|
*/
|
|
export function useCancellationHandler(taskId: string | null, onCancel?: () => void) {
|
|
return async () => {
|
|
if (!taskId) {
|
|
console.warn('No task ID available for cancellation');
|
|
return false;
|
|
}
|
|
|
|
const success = await cancelTaskWithFeedback(taskId, 'generation');
|
|
|
|
if (success && onCancel) {
|
|
onCancel();
|
|
}
|
|
|
|
return success;
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Utility for handling WebSocket cancellation events
|
|
*/
|
|
export function handleWebSocketCancellation(
|
|
taskId: string,
|
|
onCancelled: () => void,
|
|
taskDescription: string = 'task'
|
|
) {
|
|
// This will be implemented when we add WebSocket support
|
|
return (event: any) => {
|
|
if (event.task_id === taskId && event.type === 'task_cancelled') {
|
|
toast.info(`${taskDescription} was cancelled`);
|
|
onCancelled();
|
|
}
|
|
};
|
|
} |