feat(mobile-fixes-phase4): Complete US-405 - Fix batchProgressStore - Restaurare Joburi Failed
Implemented by Ralph autonomous loop. Iteration: 4 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -104,8 +104,8 @@
|
||||
"unifiedItems computed include joburile failed pentru afișare",
|
||||
"npm run build passes"
|
||||
],
|
||||
"passes": false,
|
||||
"notes": ""
|
||||
"passes": true,
|
||||
"notes": "Completed in iteration 4"
|
||||
},
|
||||
{
|
||||
"id": "US-406",
|
||||
|
||||
@@ -21,3 +21,9 @@ Stories: 8 (US-401 to US-408)
|
||||
[2026-01-12 19:23:21] Working on story: US-403
|
||||
[2026-01-12 19:23:21] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_3_US-403.log)
|
||||
[2026-01-12 19:27:05] SUCCESS: Story US-403 passed!
|
||||
[2026-01-12 19:27:05] Changes committed
|
||||
[2026-01-12 19:27:05] Progress: 4/8 stories completed
|
||||
[2026-01-12 19:27:07] === Iteration 4/50 ===
|
||||
[2026-01-12 19:27:07] Working on story: US-405
|
||||
[2026-01-12 19:27:07] Running Claude... (log: /workspace/roa2web/scripts/ralph/logs/iteration_4_US-405.log)
|
||||
[2026-01-12 19:31:08] SUCCESS: Story US-405 passed!
|
||||
|
||||
@@ -287,9 +287,13 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
console.log('[BatchProgress] All jobs finished, stopping polling')
|
||||
isPolling.value = false
|
||||
|
||||
// US-009: Remove completed batch from localStorage
|
||||
if (batchId.value) {
|
||||
// US-405: Only remove batch from localStorage if there are NO failed jobs
|
||||
// Failed jobs need to persist so they're visible after refresh
|
||||
if (batchId.value && data.failed_count === 0) {
|
||||
console.log('[BatchProgress] No failed jobs, removing batch from storage')
|
||||
removeActiveBatch(batchId.value)
|
||||
} else if (data.failed_count > 0) {
|
||||
console.log(`[BatchProgress] Batch has ${data.failed_count} failed jobs, keeping in storage for retry`)
|
||||
}
|
||||
|
||||
break
|
||||
@@ -339,12 +343,46 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
* Clear a specific batch ID from localStorage.
|
||||
* Called when a batch is determined to be complete (all items processed).
|
||||
*
|
||||
* US-405: Can also be called when all failed jobs have been resolved
|
||||
* (e.g., after successful retry or deletion of failed receipts).
|
||||
*
|
||||
* @param {string} batchIdToRemove - Batch ID to remove from storage
|
||||
*/
|
||||
function clearStoredBatch(batchIdToRemove) {
|
||||
removeActiveBatch(batchIdToRemove)
|
||||
}
|
||||
|
||||
/**
|
||||
* US-405: Check if a batch should be cleared from storage.
|
||||
* Returns true if the batch has no remaining failed jobs that need attention.
|
||||
*
|
||||
* Call this after retry or delete operations to clean up batches
|
||||
* that no longer have failed jobs.
|
||||
*/
|
||||
function shouldClearBatch() {
|
||||
// If no jobs remain, batch can be cleared
|
||||
if (jobs.value.size === 0) return true
|
||||
|
||||
// If any jobs are still failed, keep the batch
|
||||
for (const job of jobs.value.values()) {
|
||||
if (job.status === 'failed') return false
|
||||
}
|
||||
|
||||
// No failed jobs remain
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* US-405: Clear batch from storage if no failed jobs remain.
|
||||
* Call this after retry/delete operations to clean up localStorage.
|
||||
*/
|
||||
function clearBatchIfNoFailedJobs() {
|
||||
if (shouldClearBatch() && batchId.value) {
|
||||
console.log('[BatchProgress] No failed jobs remain, clearing batch from storage')
|
||||
removeActiveBatch(batchId.value)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all stored batch IDs from localStorage.
|
||||
* Used during cleanup or when all batches are confirmed complete.
|
||||
@@ -365,12 +403,13 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
|
||||
/**
|
||||
* Restore jobs from a stored batch by fetching current status from API.
|
||||
* Only pending/processing jobs are added to the store (completed/failed are already receipts).
|
||||
* Restores pending, processing, AND failed jobs to the store.
|
||||
*
|
||||
* US-023: Called on page refresh/return to restore visibility of active jobs.
|
||||
* US-405: Now includes failed jobs so users can see OCR errors after refresh.
|
||||
*
|
||||
* @param {string} storedBatchId - The batch ID to restore from
|
||||
* @returns {Promise<{hasActiveJobs: boolean, jobCount: number}>} Result of restoration
|
||||
* @returns {Promise<{hasActiveJobs: boolean, jobCount: number, hasFailedJobs: boolean}>} Result of restoration
|
||||
*/
|
||||
async function restoreJobsFromBatch(storedBatchId) {
|
||||
try {
|
||||
@@ -387,26 +426,35 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
if (!data.jobs || data.jobs.length === 0) {
|
||||
console.log(`[BatchProgress] Batch ${storedBatchId} has no jobs, removing from storage`)
|
||||
removeActiveBatch(storedBatchId)
|
||||
return { hasActiveJobs: false, jobCount: 0 }
|
||||
return { hasActiveJobs: false, jobCount: 0, hasFailedJobs: false }
|
||||
}
|
||||
|
||||
// Count and filter active jobs (pending/processing only)
|
||||
// US-405: Include failed jobs in restoration (not just pending/processing)
|
||||
// Failed jobs need to remain visible so users can see and resolve errors
|
||||
const jobsToRestore = data.jobs.filter(
|
||||
job => job.status === 'pending' || job.status === 'processing' || job.status === 'failed'
|
||||
)
|
||||
|
||||
// Count active jobs (pending/processing) for polling decision
|
||||
const activeJobs = data.jobs.filter(
|
||||
job => job.status === 'pending' || job.status === 'processing'
|
||||
)
|
||||
|
||||
if (activeJobs.length === 0) {
|
||||
// All jobs are completed or failed - no need to restore to UI
|
||||
console.log(`[BatchProgress] Batch ${storedBatchId} has no active jobs (all completed/failed), removing from storage`)
|
||||
// Count failed jobs for return value
|
||||
const failedJobs = data.jobs.filter(job => job.status === 'failed')
|
||||
|
||||
if (jobsToRestore.length === 0) {
|
||||
// All jobs are completed - safe to remove batch from storage
|
||||
console.log(`[BatchProgress] Batch ${storedBatchId} has no jobs to restore (all completed), removing from storage`)
|
||||
removeActiveBatch(storedBatchId)
|
||||
return { hasActiveJobs: false, jobCount: 0 }
|
||||
return { hasActiveJobs: false, jobCount: 0, hasFailedJobs: false }
|
||||
}
|
||||
|
||||
// Set batch ID and add active jobs to store
|
||||
// Set batch ID and add jobs to store
|
||||
batchId.value = storedBatchId
|
||||
|
||||
// Add jobs to the Map (merge with existing if any)
|
||||
for (const job of activeJobs) {
|
||||
for (const job of jobsToRestore) {
|
||||
jobs.value.set(job.job_id, {
|
||||
job_id: job.job_id,
|
||||
filename: job.filename,
|
||||
@@ -417,17 +465,22 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
})
|
||||
}
|
||||
|
||||
console.log(`[BatchProgress] Restored ${activeJobs.length} active jobs from batch ${storedBatchId}`)
|
||||
console.log(`[BatchProgress] Restored ${jobsToRestore.length} jobs from batch ${storedBatchId} (${activeJobs.length} active, ${failedJobs.length} failed)`)
|
||||
|
||||
// Start polling for updates
|
||||
if (!isPolling.value) {
|
||||
// Only start polling if there are active jobs (pending/processing)
|
||||
// Failed-only batches don't need polling - they're waiting for user action
|
||||
if (activeJobs.length > 0 && !isPolling.value) {
|
||||
isPolling.value = true
|
||||
abortController = new AbortController()
|
||||
// Start polling loop in background
|
||||
pollLoop()
|
||||
}
|
||||
|
||||
return { hasActiveJobs: true, jobCount: activeJobs.length }
|
||||
return {
|
||||
hasActiveJobs: activeJobs.length > 0,
|
||||
jobCount: jobsToRestore.length,
|
||||
hasFailedJobs: failedJobs.length > 0
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[BatchProgress] Error restoring batch ${storedBatchId}:`, err)
|
||||
|
||||
@@ -437,7 +490,7 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
removeActiveBatch(storedBatchId)
|
||||
}
|
||||
|
||||
return { hasActiveJobs: false, jobCount: 0 }
|
||||
return { hasActiveJobs: false, jobCount: 0, hasFailedJobs: false }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,6 +631,10 @@ export const useBatchProgressStore = defineStore('batchProgress', () => {
|
||||
clearStoredBatch,
|
||||
clearAllStoredBatches,
|
||||
|
||||
// US-405: Failed Jobs Cleanup
|
||||
shouldClearBatch,
|
||||
clearBatchIfNoFailedJobs,
|
||||
|
||||
// US-023: Restore Jobs from Batch
|
||||
restoreJobsFromBatch,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user