feat: retry failed extractions button on pipeline page
- POST /api/ops/pipeline/retry-failed endpoint resets extraction_failed docs to parsed, deletes failed intelligence rows, and re-enqueues them (batch of 200) - Scheduler now auto-retries extraction_failed docs every ~10 minutes (100 per cycle, 60-min cooldown per doc) - Pipeline page shows 'Retry Failed (N)' button when extraction_failed count > 0, with pending/success/error states
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { usePipelineHealth } from '../api/hooks';
|
||||
import { usePipelineHealth, useRetryFailedExtractions } from '../api/hooks';
|
||||
import { LoadingSpinner, DateRangeSelector, Card } from '../components/ui';
|
||||
|
||||
const QUEUE_LABELS: Record<string, string> = {
|
||||
@@ -53,6 +53,7 @@ export function OpsPipelinePage() {
|
||||
const [hours, setHours] = useState(24);
|
||||
const { data, isLoading } = usePipelineHealth(hours);
|
||||
const stream = usePipelineStream();
|
||||
const retryMutation = useRetryFailedExtractions();
|
||||
|
||||
if (isLoading) return <LoadingSpinner />;
|
||||
|
||||
@@ -70,6 +71,8 @@ export function OpsPipelinePage() {
|
||||
.map((s) => [s.status, s.doc_count]),
|
||||
);
|
||||
|
||||
const failedCount = docStages['extraction_failed'] ?? 0;
|
||||
|
||||
// Separate DLQ entries from regular queues
|
||||
const dlqEntries = Object.entries(queueDepths).filter(([k]) => k.startsWith('dlq:'));
|
||||
const regularQueues = Object.entries(QUEUE_LABELS);
|
||||
@@ -79,6 +82,22 @@ export function OpsPipelinePage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<h1 className="text-xl font-semibold text-gray-100">Pipeline Health</h1>
|
||||
<div className="flex items-center gap-3">
|
||||
{failedCount > 0 && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => retryMutation.mutate()}
|
||||
disabled={retryMutation.isPending}
|
||||
className="rounded-md bg-amber-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-amber-500 disabled:opacity-50"
|
||||
>
|
||||
{retryMutation.isPending ? 'Retrying…' : `Retry Failed (${failedCount})`}
|
||||
</button>
|
||||
)}
|
||||
{retryMutation.isSuccess && (
|
||||
<span className="text-xs text-green-400">{retryMutation.data.message}</span>
|
||||
)}
|
||||
{retryMutation.isError && (
|
||||
<span className="text-xs text-red-400">Retry failed</span>
|
||||
)}
|
||||
{stream && (
|
||||
<span className="flex items-center gap-1.5 text-xs text-green-400">
|
||||
<span className="inline-block h-2 w-2 rounded-full bg-green-400 animate-pulse" aria-hidden="true" />
|
||||
|
||||
Reference in New Issue
Block a user