(jobId: string)
| 553 | } |
| 554 | |
| 555 | private updateJobProgress(jobId: string): void { |
| 556 | const job = activeJobs.get(jobId); |
| 557 | if (!job) { |
| 558 | handleLog(`[queue] Job ${jobId} not found for progress update`); |
| 559 | return; |
| 560 | } |
| 561 | |
| 562 | const jobChunks = Array.from(this.workChunks.values()).filter( |
| 563 | (c) => c.jobId === jobId, |
| 564 | ); |
| 565 | |
| 566 | if (jobChunks.length === 0) { |
| 567 | handleLog(`[${getLogPrefix(job.type)}] No chunks found for job ${jobId}`); |
| 568 | return; |
| 569 | } |
| 570 | |
| 571 | const totalProcessedDays = jobChunks.reduce( |
| 572 | (sum, chunk) => sum + (chunk.data.processedDays || 0), |
| 573 | 0, |
| 574 | ); |
| 575 | |
| 576 | const oldProgress = job.progress; |
| 577 | const oldProcessedCount = job.processedCount || 0; |
| 578 | |
| 579 | job.processedCount = totalProcessedDays; |
| 580 | job.progress = job.totalToProcess |
| 581 | ? Math.min( |
| 582 | 99, |
| 583 | Math.round((totalProcessedDays / job.totalToProcess) * 100), |
| 584 | ) |
| 585 | : Math.min( |
| 586 | 99, |
| 587 | Math.round( |
| 588 | jobChunks.reduce((sum, chunk) => sum + chunk.progress, 0) / |
| 589 | jobChunks.length, |
| 590 | ), |
| 591 | ); |
| 592 | |
| 593 | job.status = ImportStatus.ProcessingHeartbeats; |
| 594 | job.message = formatStatus( |
| 595 | ImportStatus.ProcessingHeartbeats, |
| 596 | job.type, |
| 597 | job.processedCount, |
| 598 | job.totalToProcess, |
| 599 | job.progress, |
| 600 | undefined, |
| 601 | job.importedCount, |
| 602 | job.error, |
| 603 | ); |
| 604 | |
| 605 | activeJobs.set(jobId, job); |
| 606 | |
| 607 | if ( |
| 608 | oldProgress !== job.progress || |
| 609 | oldProcessedCount !== job.processedCount |
| 610 | ) { |
| 611 | handleLog( |
| 612 | `[${getLogPrefix(job.type)}] Job ${jobId} progress: ${job.processedCount}/${job.totalToProcess} days (${job.progress}%)`, |
no test coverage detected