diff --git a/services/nginx/app/classes/invoice_period_flag_service.php b/services/nginx/app/classes/invoice_period_flag_service.php index 6e683b5d..99e99eb8 100644 --- a/services/nginx/app/classes/invoice_period_flag_service.php +++ b/services/nginx/app/classes/invoice_period_flag_service.php @@ -529,6 +529,11 @@ class invoice_period_flag_service } if (!is_array($flags)) { + // Cache miss — enqueue for warming on the next cron run + try { + (new redis())->enqueue_invoice_period_warming($dateFrom, $dateTo); + } catch (Throwable) { + } return []; } diff --git a/services/nginx/app/classes/redis.php b/services/nginx/app/classes/redis.php index 19958bf4..29e7f601 100644 --- a/services/nginx/app/classes/redis.php +++ b/services/nginx/app/classes/redis.php @@ -447,6 +447,35 @@ class redis implements redis_i return $this; } + /** + * @inheritDoc + */ + public function enqueue_invoice_period_warming(string $dateFrom, string $dateTo): self + { + $this->get_client()->sadd('invoice_period_warming_queue', [$dateFrom . '|' . $dateTo]); + return $this; + } + + /** + * @inheritDoc + */ + public function consume_invoice_period_warming_queue(): array + { + $client = $this->get_client(); + $members = $client->smembers('invoice_period_warming_queue'); + if (!empty($members)) { + $client->del('invoice_period_warming_queue'); + } + $periods = []; + foreach ($members as $member) { + $parts = explode('|', (string)$member, 2); + if (count($parts) === 2 && $parts[0] !== '' && $parts[1] !== '') { + $periods[] = ['dateFrom' => $parts[0], 'dateTo' => $parts[1]]; + } + } + return $periods; + } + /** * @inheritDoc */ diff --git a/services/nginx/app/cron/Cron.php b/services/nginx/app/cron/Cron.php index 2793b966..db52c3a9 100644 --- a/services/nginx/app/cron/Cron.php +++ b/services/nginx/app/cron/Cron.php @@ -160,11 +160,26 @@ function WarmInvoicePeriodAutomaticFlagsCron(): void $service = new invoice_period_flag_service(); $now = new DateTime(); $previousMonth = new DateTime('first day of previous month'); + + $toWarm = []; foreach ([$now, $previousMonth] as $date) { $dateFrom = $date->format('Y-m-01'); $dateTo = $date->format('Y-m-t'); - $service->warmOrderItemRowsForPeriod($dateFrom, $dateTo); - $service->warmAutomaticFlagsForPeriod($dateFrom, $dateTo); + $toWarm[$dateFrom . '|' . $dateTo] = ['dateFrom' => $dateFrom, 'dateTo' => $dateTo]; + } + + try { + $queued = (new redis())->consume_invoice_period_warming_queue(); + foreach ($queued as $period) { + $key = $period['dateFrom'] . '|' . $period['dateTo']; + $toWarm[$key] = $period; + } + } catch (Throwable) { + } + + foreach ($toWarm as $period) { + $service->warmOrderItemRowsForPeriod($period['dateFrom'], $period['dateTo']); + $service->warmAutomaticFlagsForPeriod($period['dateFrom'], $period['dateTo']); } } diff --git a/services/nginx/app/interfaces/redis_i.php b/services/nginx/app/interfaces/redis_i.php index e11b028c..a431312d 100644 --- a/services/nginx/app/interfaces/redis_i.php +++ b/services/nginx/app/interfaces/redis_i.php @@ -381,4 +381,18 @@ interface redis_i * @return self */ public function clear_permission(string $cache_key): self; + + /** + * Enqueue a period for automatic flags warming. + * @param string $dateFrom + * @param string $dateTo + * @return self + */ + public function enqueue_invoice_period_warming(string $dateFrom, string $dateTo): self; + + /** + * Consume all queued warming periods and clear the queue. + * @return array + */ + public function consume_invoice_period_warming_queue(): array; } \ No newline at end of file