$positiveLabels @return list */ 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; } }