oCategory?->sSlug === 'freenode') $urls[] = Seo::url(); if ($a->oCategory) $urls[] = Seo::url(Seo::categoryPath($a->oCategory)); $event = $deleted || !Seo::public($a) ? 'delete' : 'update'; $key = hash('sha256',json_encode([$a->id,$event,$a->sContentUpdatedAt,$a->sTitle,$a->sContent,$a->sThumb,$a->iStatus])); $this->enqueue($key,$urls,$event); } public function enqueue(string $key, array $urls, string $event = 'update'): void { if (!app()->environment(['production','testing']) || !config('editorial.indexnow_enabled',app()->environment('production'))) return; DB::table('seo_notifications')->insertOrIgnore(['event_key'=>$key,'urls'=>json_encode(array_values(array_unique($urls))), 'event'=>$event,'state'=>json_encode(['status'=>'pending','attempts'=>0]),'created_at'=>now(),'updated_at'=>now()]); } public function retry(int $limit = 10): int { $processed = 0; foreach (DB::table('seo_notifications')->orderBy('id')->cursor() as $candidate) { $s = json_decode($candidate->state,true); if (($s['status'] ?? '') !== 'pending' || ($s['next_attempt_at'] ?? 0) > now()->timestamp) continue; DB::transaction(function () use ($candidate,&$processed) { $row = DB::table('seo_notifications')->where('id',$candidate->id)->lockForUpdate()->first(); $state = json_decode($row->state,true); if (($state['status'] ?? '') !== 'pending' || ($state['next_attempt_at'] ?? 0) > now()->timestamp) return; $urls = json_decode($row->urls,true); if ($row->event !== 'delete') $urls = array_values(array_filter($urls,function($url) { $path = parse_url($url,PHP_URL_PATH); if (preg_match('~^/a/([a-zA-Z0-9_-]+)\.html$~',$path,$m)) { $a = Articles::where('sSlug',$m[1])->first(); return $a && Seo::indexable($a); } if ($path === '/') return app(ArticlesService::class)->getLatestFreeNodeSlug() !== null; return true; })); $state = app(IndexNowNotification::class)->submit($state,$urls); DB::table('seo_notifications')->where('id',$row->id)->update(['state'=>json_encode($state),'updated_at'=>now()]); $processed++; }); if ($processed >= $limit) break; } return $processed; } }