Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 39 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
| BulkSyncG3WRun | |
0.00% |
0 / 39 |
|
0.00% |
0 / 4 |
30 | |
0.00% |
0 / 1 |
| __construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| middleware | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
| handle | |
0.00% |
0 / 27 |
|
0.00% |
0 / 1 |
6 | |||
| failed | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace App\Jobs; |
| 4 | |
| 5 | use App\Services\PresupuestosService; |
| 6 | use Illuminate\Bus\Queueable; |
| 7 | use Illuminate\Contracts\Queue\ShouldQueue; |
| 8 | use Illuminate\Foundation\Bus\Dispatchable; |
| 9 | use Illuminate\Queue\InteractsWithQueue; |
| 10 | use Illuminate\Queue\Middleware\RateLimited; |
| 11 | use Illuminate\Queue\Middleware\WithoutOverlapping; |
| 12 | use Illuminate\Queue\SerializesModels; |
| 13 | use Illuminate\Support\Facades\Log; |
| 14 | |
| 15 | /** |
| 16 | * FIRE-1170: per-region worker for the "Sincronización masiva" admin tool. |
| 17 | * One job per region per run — the controller fans out N jobs (one per |
| 18 | * selected region) and they share the `g3w` rate-limiter with the regular |
| 19 | * cron sync. The `WithoutOverlapping` lock keys on (region, runId) so two |
| 20 | * different runs can target the same region concurrently without colliding |
| 21 | * but the same run can't double-process a region if it gets re-dispatched. |
| 22 | * |
| 23 | * Mirrors the SyncG3WRegion pattern from FIRE-1151. |
| 24 | */ |
| 25 | class BulkSyncG3WRun implements ShouldQueue |
| 26 | { |
| 27 | use Dispatchable; |
| 28 | use InteractsWithQueue; |
| 29 | use Queueable; |
| 30 | use SerializesModels; |
| 31 | |
| 32 | public int $tries = 3; |
| 33 | |
| 34 | /** @var array<int,int> seconds between retries */ |
| 35 | public array $backoff = [30, 90, 300]; |
| 36 | |
| 37 | /** Hard kill at 1 hour — bulk runs can be longer than the daily cron. */ |
| 38 | public int $timeout = 3600; |
| 39 | |
| 40 | /** |
| 41 | * @param array<int,string> $fields UI checkbox names (see PresupuestosService::BULK_SYNC_FIELD_MAP) |
| 42 | */ |
| 43 | public function __construct( |
| 44 | public readonly int $runId, |
| 45 | public readonly string $region, |
| 46 | public readonly string $dateFrom, |
| 47 | public readonly string $dateTo, |
| 48 | public readonly array $fields, |
| 49 | public readonly bool $suppressOps, |
| 50 | public readonly bool $suppressFin, |
| 51 | ) {} |
| 52 | |
| 53 | public function middleware(): array |
| 54 | { |
| 55 | return [ |
| 56 | (new WithoutOverlapping("g3w:bulk:{$this->region}:{$this->runId}")) |
| 57 | ->expireAfter(7200) |
| 58 | ->dontRelease(), |
| 59 | new RateLimited('g3w'), |
| 60 | ]; |
| 61 | } |
| 62 | |
| 63 | public function handle(PresupuestosService $service): void |
| 64 | { |
| 65 | // The job can take 20+ minutes for large date ranges. Disable the |
| 66 | // PHP execution timeout — this matters when the job runs via |
| 67 | // `dispatchAfterResponse` on a web worker (which inherits the |
| 68 | // request's max_execution_time). A real queue worker doesn't have |
| 69 | // this limit. |
| 70 | @set_time_limit(0); |
| 71 | |
| 72 | $start = microtime(true); |
| 73 | |
| 74 | try { |
| 75 | $service->bulkSyncByFilters( |
| 76 | $this->runId, |
| 77 | $this->region, |
| 78 | $this->dateFrom, |
| 79 | $this->dateTo, |
| 80 | $this->fields, |
| 81 | $this->suppressOps, |
| 82 | $this->suppressFin, |
| 83 | ); |
| 84 | $status = 'ok'; |
| 85 | } catch (\Throwable $e) { |
| 86 | $status = 'failed'; |
| 87 | Log::channel('g3w')->error('BulkSyncG3WRun failed', [ |
| 88 | 'run_id' => $this->runId, |
| 89 | 'region' => $this->region, |
| 90 | 'error' => $e->getMessage(), |
| 91 | ]); |
| 92 | throw $e; |
| 93 | } finally { |
| 94 | Log::channel('g3w')->info('BulkSyncG3WRun finished', [ |
| 95 | 'run_id' => $this->runId, |
| 96 | 'region' => $this->region, |
| 97 | 'wall_ms' => (int) round((microtime(true) - $start) * 1000), |
| 98 | 'status' => $status ?? 'unknown', |
| 99 | 'attempt' => $this->attempts(), |
| 100 | ]); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | public function failed(\Throwable $e): void |
| 105 | { |
| 106 | Log::channel('g3w')->error('BulkSyncG3WRun exhausted retries', [ |
| 107 | 'run_id' => $this->runId, |
| 108 | 'region' => $this->region, |
| 109 | 'error' => $e->getMessage(), |
| 110 | ]); |
| 111 | } |
| 112 | } |