where('id', $id)->lockForUpdate()->first(); abort_unless($row, 404); $receipt = json_decode($row->receipt, true); $effects = json_decode($row->effects ?? '{}', true) ?: []; if (($effects['cache']['status'] ?? '') !== 'done') { try { ResponseCache::clear(); Cache::forget('article_order_likes'); $effects['cache'] = ['status' => 'done']; } catch (\Throwable) { $effects['cache'] = ['status' => 'pending', 'reason' => 'Cache refresh failed; retry synchronization']; } } if (($effects['search']['status'] ?? '') !== 'done') { try { $ids = array_column($receipt['articles'], 'article_id'); $effects['search'] = $this->index($ids); } catch (\Throwable) { $effects['search'] = ['status' => 'pending', 'reason' => 'Search synchronization failed; retry synchronization']; } } // Sitemap is generated from current DB rows, no external submission is performed. $effects['sitemap'] = ['status' => ($effects['cache']['status'] ?? '') === 'done' ? 'done' : 'pending', 'method' => 'database-driven']; DB::table('editorial_publications')->where('id', $id)->update(['effects' => json_encode($effects), 'updated_at' => now()]); }); return app(Publisher::class)->receipt($id); } public function index(?array $ids = null): array { $driver = config('scout.driver'); if (in_array($driver, ['collection', 'database'])) { return ['status' => 'done', 'method' => 'live-database']; } if ($driver !== 'meilisearch') { return ['status' => 'pending', 'reason' => 'Configure a supported site search driver']; } $name = config('editorial.search_index'); $host = config('scout.meilisearch.host'); if (! $name || (app()->environment('local') && (! in_array(parse_url($host, PHP_URL_HOST), ['localhost', '127.0.0.1', '::1']) || ! str_starts_with($name, 'fna_v3_')))) { return ['status' => 'pending', 'reason' => 'An isolated search index is required']; } $client = new Client($host, config('scout.meilisearch.key')); $index = $client->index($name); $wait = function ($task) use ($client) { $result = $client->waitForTask($task['taskUid'], 10000, 50); if (($result['status'] ?? '') !== 'succeeded') { throw new \RuntimeException('Index task failed'); } }; $wait($index->updateSortableAttributes(['iIsTop', 'created_at'])); $wait($index->updateFilterableAttributes(['iStatus', 'iCategoryId'])); $query = Articles::query()->where('iStatus', 1); if ($ids !== null) { $query->whereIn('id', $ids); } $documents = $query->get()->map(fn ($a) => $a->toSearchableArray() + ['created_at' => $a->created_at?->timestamp])->all(); if ($documents) { $wait($index->addDocuments($documents, 'id')); } return ['status' => 'done', 'method' => 'meilisearch', 'index' => $name, 'documents' => count($documents)]; } }