69 lines
2.6 KiB
PHP
69 lines
2.6 KiB
PHP
<?php
|
|
|
|
namespace App\Business;
|
|
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
/** Reuse label classification across monthly/platform jobs; writers invalidate it. */
|
|
class PlantingOrderLabelLookup
|
|
{
|
|
/** @param list<string> $positiveLabels @return list<string> */
|
|
public function orderNumbers(int $companyId, array $positiveLabels): array
|
|
{
|
|
sort($positiveLabels, SORT_STRING);
|
|
$rules = hash('sha256', json_encode($positiveLabels, JSON_THROW_ON_ERROR));
|
|
$key = $this->key($companyId);
|
|
$read = function () use ($key, $rules, $companyId): ?array {
|
|
$cached = Cache::get($key);
|
|
|
|
return is_array($cached) && ($cached['rules'] ?? null) === $rules
|
|
&& ($cached['revision'] ?? null) === $this->revision($companyId)
|
|
? $cached['orders'] : null;
|
|
};
|
|
if (($orders = $read()) !== null) {
|
|
return $orders;
|
|
}
|
|
|
|
return Cache::lock($key . ':build', 300)->block(305, function () use ($companyId, $positiveLabels, $key, $rules, $read): array {
|
|
if (($orders = $read()) !== null) {
|
|
return $orders;
|
|
}
|
|
$revision = $this->revision($companyId);
|
|
$orders = [];
|
|
foreach (DB::table('jst_order_labels')->where('company_id', $companyId)
|
|
->where(function ($query) use ($positiveLabels): void {
|
|
if ($positiveLabels !== []) {
|
|
$query->whereIn('label', $positiveLabels);
|
|
}
|
|
$query->orWhereRaw('FIND_IN_SET(?, item_code) > 0', [JstOrderLabelPlantingRules::PLANTING_ITEM_CODE]);
|
|
})->select('order_no')->distinct()->cursor() as $row) {
|
|
$orders[] = (string) $row->order_no;
|
|
}
|
|
// An import/rule change during the scan must not publish an old result.
|
|
if ($this->revision($companyId) === $revision) {
|
|
Cache::put($key, ['rules' => $rules, 'revision' => $revision, 'orders' => $orders], now()->addHours(24));
|
|
}
|
|
|
|
return $orders;
|
|
});
|
|
}
|
|
|
|
public function forget(int $companyId): void
|
|
{
|
|
$key = $this->key($companyId);
|
|
Cache::store('upstream_shared')->forever($key . ':revision', bin2hex(random_bytes(16)));
|
|
Cache::forget($key);
|
|
}
|
|
|
|
public function revision(int $companyId): ?string
|
|
{
|
|
return Cache::store('upstream_shared')->get($this->key($companyId) . ':revision');
|
|
}
|
|
|
|
private function key(int $companyId): string
|
|
{
|
|
return 'planting-order-labels:v1:' . $companyId;
|
|
}
|
|
}
|