Files
citrus-cms/app/Services/RegisterCreator/ProgressTracker.php
T
2026-04-28 21:14:25 +03:00

261 lines
7.6 KiB
PHP

<?php
namespace App\Services\RegisterCreator;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Auth;
class ProgressTracker
{
private string $jobId;
private int $totalSteps;
private int $currentStep = 0;
private int $totalRegisters = 0;
private ?string $lineData = null;
public function __construct(string $jobId, int $totalSteps = 100, int $totalRegisters = 0, ?string $lineData = null)
{
$this->jobId = $jobId;
$this->totalSteps = $totalSteps;
$this->totalRegisters = $totalRegisters;
$this->lineData = $lineData;
// Update queue status to "running" when job starts processing
$this->updateQueueToRunning();
}
/**
* Update progress in cache
*/
public function update(string $description, ?int $customProgress = null, ?int $customCurrent = null): void
{
try {
$progress = $customProgress ?? $this->calculateProgress();
// If customCurrent is provided, use it; otherwise use currentStep
$current = $customCurrent ?? $this->currentStep;
$progressData = [
'total' => $this->totalSteps,
'current' => $current,
'progress' => $progress,
'description' => $description,
'line_data' => $this->lineData,
'updated_at' => now()->toDateTimeString(),
'status' => 'running'
];
Cache::put("register-creator-progress-{$this->jobId}", $progressData, now()->addHours(24));
Log::debug("Progress updated for job {$this->jobId}", [
'line_data' => $this->lineData,
'progress' => $progress,
'current' => $current,
'total' => $this->totalSteps,
'description' => $description
]);
} catch (\Throwable $th) {
// Don't let progress tracking failure stop the job
Log::error("Failed to update progress for job {$this->jobId}", [
'error' => $th->getMessage()
]);
}
}
/**
* Increment current step
*/
public function increment(string $description): void
{
$this->currentStep++;
$this->update($description);
}
/**
* Set current step
*/
public function setStep(int $step, string $description): void
{
$this->currentStep = $step;
$this->update($description);
}
/**
* Mark as completed
*/
public function complete(string $message = 'Completed'): void
{
// Set current to total when completing
$this->update($message, 100, $this->totalSteps);
Log::info("Job {$this->jobId} completed", [
'line_data' => $this->lineData
]);
// Remove from queue after completion
$this->removeFromQueue();
}
/**
* Mark as failed
*/
public function fail(string $error): void
{
Cache::put("register-creator-progress-{$this->jobId}", [
'total' => $this->totalSteps,
'current' => $this->currentStep,
'progress' => $this->calculateProgress(),
'description' => "Error: {$error}",
'line_data' => $this->lineData,
'status' => 'failed',
'updated_at' => now()->toDateTimeString()
], now()->addHours(24));
Log::error("Job {$this->jobId} failed", [
'line_data' => $this->lineData,
'current' => $this->currentStep,
'total' => $this->totalSteps,
'error' => $error
]);
// Remove from queue after failure
$this->removeFromQueue();
}
/**
* Calculate progress percentage
*/
private function calculateProgress(): int
{
if ($this->totalSteps === 0) {
return 0;
}
return min(100, (int) round(($this->currentStep / $this->totalSteps) * 100));
}
/**
* Get current progress
*/
public function get(): ?array
{
return Cache::get("register-creator-progress-{$this->jobId}");
}
/**
* Clear progress from cache
*/
public function clear(): void
{
Cache::forget("register-creator-progress-{$this->jobId}");
}
/**
* Update queue status to running when job starts processing
* Note: Only updates status fields, preserves user and line_identifier from controller
*/
private function updateQueueToRunning(): void
{
$queue = Cache::get('register-creator-queue-2', []);
if (isset($queue[$this->jobId])) {
// Update only status-related fields, preserve user and line_identifier from controller
$queue[$this->jobId]['status'] = 'running';
$queue[$this->jobId]['started_at'] = now()->toDateTimeString();
// Update line_identifier only if we have lineData and it's not already set
if ($this->lineData && empty($queue[$this->jobId]['line_identifier'])) {
$queue[$this->jobId]['line_identifier'] = $this->lineData;
}
// Sync total_registers with totalSteps if available
if ($this->totalSteps > 0) {
$queue[$this->jobId]['total_registers'] = $this->totalSteps;
}
Cache::put('register-creator-queue-2', $queue, now()->addHours(24));
Log::info("Job {$this->jobId} status updated to running", [
'line_data' => $this->lineData,
'total_documents' => $this->totalSteps,
'preserved_user' => isset($queue[$this->jobId]['user']) ? 'yes' : 'no',
'preserved_line_identifier' => $queue[$this->jobId]['line_identifier'] ?? 'none'
]);
} else {
// Fallback: If queue entry doesn't exist, create it
// This shouldn't happen in normal flow, but added for safety
Log::warning("Queue entry not found for job {$this->jobId}, creating new entry");
try {
$user = Auth::user();
} catch (\Throwable $th) {
$user = null;
}
$queue[$this->jobId] = [
'user' => $user,
'total_registers' => $this->totalSteps > 0 ? $this->totalSteps : $this->totalRegisters,
'line_identifier' => $this->lineData,
'started_at' => now()->toDateTimeString(),
'status' => 'running'
];
Cache::put('register-creator-queue-2', $queue, now()->addHours(24));
}
}
/**
* Remove this job from the queue
*/
private function removeFromQueue(): void
{
$queue = Cache::get('register-creator-queue-2', []);
if (isset($queue[$this->jobId])) {
unset($queue[$this->jobId]);
Cache::put('register-creator-queue-2', $queue, now()->addHours(24));
Log::info("Job {$this->jobId} removed from queue", [
'line_data' => $this->lineData
]);
}
}
/**
* Get job ID
*/
public function getJobId(): string
{
return $this->jobId;
}
/**
* Get total registers count
*/
public function getTotalRegisters(): int
{
return $this->totalRegisters;
}
/**
* Get line data
*/
public function getLineData(): ?string
{
return $this->lineData;
}
}