diff --git a/compute/worker/.env.example b/compute/worker/.env.example
index fa18018..eef2843 100644
--- a/compute/worker/.env.example
+++ b/compute/worker/.env.example
@@ -30,8 +30,13 @@ S3_FORCE_PATH_STYLE=true
# Queue + execution tuning
COMPUTE_PREWARM_MODELS=true
+COMPUTE_WHISPER_CONCURRENCY=1
+COMPUTE_PDF_CONCURRENCY=2
+COMPUTE_WHISPER_TIMEOUT_MS=30000
+COMPUTE_PDF_TIMEOUT_MS=90000
+COMPUTE_JOB_ATTEMPTS=2
COMPUTE_JOBS_STREAM_MAX_BYTES=268435456
COMPUTE_JOB_STATES_MAX_BYTES=67108864
# Optional stale window for reusing in-flight opKey entries before forcing a new attempt
# Default is max(30m, 4x max compute timeout); running jobs also refresh heartbeat every 5s
-# COMPUTE_OP_STALE_MS=180000
+# COMPUTE_OP_STALE_MS=1800000
diff --git a/src/app/(app)/pdf/[id]/page.tsx b/src/app/(app)/pdf/[id]/page.tsx
index 1cbb1f1..caaccae 100644
--- a/src/app/(app)/pdf/[id]/page.tsx
+++ b/src/app/(app)/pdf/[id]/page.tsx
@@ -75,11 +75,14 @@ export default function PDFViewerPage() {
const backNavTimeoutRef = useRef | null>(null);
const clearCurrDocRef = useRef(clearCurrDoc);
const [isNavigatingBack, setIsNavigatingBack] = useState(false);
- const parseState = parseStatus ?? 'pending';
- const isParseReady = parseState === 'ready';
+ const parseUiState: 'unknown' | NonNullable = parseStatus ?? 'unknown';
+ const isParseReady = parseUiState === 'ready';
const forceReparseDisabled = isForceReparseDisabled(parseStatus);
+ const hasRealParseProgress = !!parseProgress
+ && parseProgress.totalPages > 0
+ && parseProgress.pagesParsed >= 0;
const shouldShowExpandedParseLoader = !isLoading
- && (parseState === 'pending' || parseState === 'running' || parseState === 'failed');
+ && (parseUiState === 'failed' || hasRealParseProgress);
useEffect(() => {
setIsLoading(true);
@@ -283,10 +286,10 @@ export default function PDFViewerPage() {
const renderPdfStatusLoader = () => {
const compactLabel = isLoading
? 'Opening PDF...'
- : (parseState === 'ready' ? 'Rendering pages...' : 'Checking parse state...');
+ : (parseUiState === 'ready' ? 'Rendering pages...' : 'Checking parse state...');
const compactSubLabel = isLoading
? 'Loading document data'
- : (parseState === 'ready' ? 'Preparing first frame' : 'Preparing layout parser');
+ : (parseUiState === 'ready' ? 'Preparing first frame' : 'Waiting for parse status');
const totalPages = parseProgress?.totalPages ?? 0;
const pagesParsed = parseProgress?.pagesParsed ?? 0;
@@ -299,25 +302,30 @@ export default function PDFViewerPage() {
let statusText = 'Loading PDF...';
let statusSubText = 'Initializing document renderer';
if (!isLoading) {
- if (parseState === 'pending') {
+ if (parseUiState === 'unknown') {
+ statusText = 'Checking parse state...';
+ statusSubText = 'Waiting for server status snapshot';
+ } else if (parseUiState === 'pending') {
statusText = 'Preparing PDF layout...';
statusSubText = parseProgress?.phase === 'merge'
? 'Finalizing stitched block structure'
: 'Queueing parser and preparing page extraction';
- } else if (parseState === 'running') {
+ } else if (parseUiState === 'running') {
statusText = 'Parsing PDF layout blocks...';
statusSubText = parseProgress?.phase === 'merge'
? 'Merging cross-page sections'
: 'Inferring reading order and text regions';
- } else if (parseState === 'failed') {
+ } else if (parseUiState === 'failed') {
statusText = 'PDF parsing failed. Retry to continue.';
statusSubText = 'The parser could not build a usable layout map';
}
}
- const stageLabel = parseState === 'failed'
+ const stageLabel = parseUiState === 'unknown'
+ ? 'Stage: checking'
+ : parseUiState === 'failed'
? 'Stage: blocked'
- : (parseState === 'pending'
+ : (parseUiState === 'pending'
? 'Stage: prepare'
: (isMerging ? 'Stage: merge' : 'Stage: infer'));
@@ -354,7 +362,7 @@ export default function PDFViewerPage() {
- {!isLoading && parseState === 'failed' ? (
+ {!isLoading && parseUiState === 'failed' ? (
+ );
+ }
+
return (
-
-
+
);
}
\ No newline at end of file