From 72483aeca9e47ebd94d87a9354c0e0e96af5fa6d Mon Sep 17 00:00:00 2001 From: Dat Date: Thu, 30 Jul 2026 17:13:12 +0200 Subject: [PATCH 1/4] fix(api): make PollForMediaWikiJobsJob skip soft-deleted wikis --- app/Jobs/PollForMediaWikiJobsJob.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/Jobs/PollForMediaWikiJobsJob.php b/app/Jobs/PollForMediaWikiJobsJob.php index 6e3ad016..0f2486f6 100644 --- a/app/Jobs/PollForMediaWikiJobsJob.php +++ b/app/Jobs/PollForMediaWikiJobsJob.php @@ -3,6 +3,7 @@ namespace App\Jobs; use App\Services\MediaWikiHostResolver; +use App\Services\UnknownWikiDomainException; use App\Wiki; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; @@ -16,7 +17,7 @@ class PollForMediaWikiJobsJob extends Job implements ShouldBeUnique, ShouldQueue public function handle(MediaWikiHostResolver $mwHostResolver): void { $this->mwHostResolver = $mwHostResolver; - $allWikiDomains = Wiki::all()->pluck('domain'); + $allWikiDomains = Wiki::whereNull('deleted_at')->pluck('domain'); foreach ($allWikiDomains as $wikiDomain) { if ($this->hasPendingJobs($wikiDomain)) { $this->enqueueWiki($wikiDomain); @@ -25,11 +26,17 @@ public function handle(MediaWikiHostResolver $mwHostResolver): void { } private function hasPendingJobs(string $wikiDomain): bool { - $response = Http::withHeaders([ - 'host' => $wikiDomain, - ])->get( - $this->mwHostResolver->getBackendUrlForDomain($wikiDomain) . '/w/api.php?action=query&meta=siteinfo&siprop=statistics&format=json' - ); + try { + $response = Http::withHeaders([ + 'host' => $wikiDomain, + ])->get( + $this->mwHostResolver->getBackendUrlForDomain($wikiDomain) . '/w/api.php?action=query&meta=siteinfo&siprop=statistics&format=json' + ); + } catch (UnknownWikiDomainException $e) { + Log::warning('Skipping wiki ' . $wikiDomain . ' for pending MediaWiki jobs: ' . $e->getMessage()); + + return false; + } if ($response->failed()) { $this->job->markAsFailed(); From 3a7351f221a5fac86f62619874835c7083367758 Mon Sep 17 00:00:00 2001 From: Dat Date: Thu, 30 Jul 2026 17:13:12 +0200 Subject: [PATCH 2/4] fix(api): make PollForMediaWikiJobsJob skip soft-deleted wikis --- app/Jobs/PollForMediaWikiJobsJob.php | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/app/Jobs/PollForMediaWikiJobsJob.php b/app/Jobs/PollForMediaWikiJobsJob.php index 6e3ad016..0f2486f6 100644 --- a/app/Jobs/PollForMediaWikiJobsJob.php +++ b/app/Jobs/PollForMediaWikiJobsJob.php @@ -3,6 +3,7 @@ namespace App\Jobs; use App\Services\MediaWikiHostResolver; +use App\Services\UnknownWikiDomainException; use App\Wiki; use Illuminate\Contracts\Queue\ShouldBeUnique; use Illuminate\Contracts\Queue\ShouldQueue; @@ -16,7 +17,7 @@ class PollForMediaWikiJobsJob extends Job implements ShouldBeUnique, ShouldQueue public function handle(MediaWikiHostResolver $mwHostResolver): void { $this->mwHostResolver = $mwHostResolver; - $allWikiDomains = Wiki::all()->pluck('domain'); + $allWikiDomains = Wiki::whereNull('deleted_at')->pluck('domain'); foreach ($allWikiDomains as $wikiDomain) { if ($this->hasPendingJobs($wikiDomain)) { $this->enqueueWiki($wikiDomain); @@ -25,11 +26,17 @@ public function handle(MediaWikiHostResolver $mwHostResolver): void { } private function hasPendingJobs(string $wikiDomain): bool { - $response = Http::withHeaders([ - 'host' => $wikiDomain, - ])->get( - $this->mwHostResolver->getBackendUrlForDomain($wikiDomain) . '/w/api.php?action=query&meta=siteinfo&siprop=statistics&format=json' - ); + try { + $response = Http::withHeaders([ + 'host' => $wikiDomain, + ])->get( + $this->mwHostResolver->getBackendUrlForDomain($wikiDomain) . '/w/api.php?action=query&meta=siteinfo&siprop=statistics&format=json' + ); + } catch (UnknownWikiDomainException $e) { + Log::warning('Skipping wiki ' . $wikiDomain . ' for pending MediaWiki jobs: ' . $e->getMessage()); + + return false; + } if ($response->failed()) { $this->job->markAsFailed(); From 1b38cd8dff489e7037a285c726472d46434a361d Mon Sep 17 00:00:00 2001 From: Dat Date: Mon, 3 Aug 2026 12:48:30 +0200 Subject: [PATCH 3/4] Polling jobs loads active wikis once --- app/Jobs/PollForMediaWikiJobsJob.php | 37 ++++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/app/Jobs/PollForMediaWikiJobsJob.php b/app/Jobs/PollForMediaWikiJobsJob.php index 0f0f8291..48514ad8 100644 --- a/app/Jobs/PollForMediaWikiJobsJob.php +++ b/app/Jobs/PollForMediaWikiJobsJob.php @@ -3,6 +3,7 @@ namespace App\Jobs; use App\Services\MediaWikiHostResolver; +use App\Services\UnknownDBVersionException; use App\Services\UnknownWikiDomainException; use App\Wiki; use Illuminate\Contracts\Queue\ShouldBeUnique; @@ -17,26 +18,30 @@ class PollForMediaWikiJobsJob extends Job implements ShouldBeUnique, ShouldQueue public function handle(MediaWikiHostResolver $mwHostResolver): void { $this->mwHostResolver = $mwHostResolver; - $allWikiDomains = Wiki::all()->pluck('domain'); - foreach ($allWikiDomains as $wikiDomain) { - if ($this->hasPendingJobs($wikiDomain)) { - $this->enqueueWiki($wikiDomain); + $wikis = Wiki::with('wikiDb') + ->get(); + + foreach ($wikis as $wiki) { + try { + $backendUrl = $this->mwHostResolver->getBackendUrlForWiki($wiki); + } catch (UnknownWikiDomainException | UnknownDBVersionException $e) { + Log::warning('Skipping wiki ' . $wiki->domain . ' for pending MediaWiki jobs: ' . $e->getMessage()); + + continue; + } + + if ($this->hasPendingJobs($wiki->domain, $backendUrl)) { + $this->enqueueWiki($wiki->domain); } } } - private function hasPendingJobs(string $wikiDomain): bool { - try { - $response = Http::withHeaders([ - 'host' => $wikiDomain, - ])->get( - $this->mwHostResolver->getBackendUrlForDomain($wikiDomain) . '/w/api.php?action=query&meta=siteinfo&siprop=statistics&format=json' - ); - } catch (UnknownWikiDomainException $e) { - Log::warning('Skipping wiki ' . $wikiDomain . ' for pending MediaWiki jobs: ' . $e->getMessage()); - - return false; - } + private function hasPendingJobs(string $wikiDomain, string $backendUrl): bool { + $response = Http::withHeaders([ + 'host' => $wikiDomain, + ])->get( + $backendUrl . '/w/api.php?action=query&meta=siteinfo&siprop=statistics&format=json' + ); if ($response->failed()) { $this->job->markAsFailed(); From 490467371917f82862be5647e0a3970cb381c70e Mon Sep 17 00:00:00 2001 From: Dat Date: Mon, 3 Aug 2026 12:49:21 +0200 Subject: [PATCH 4/4] add new helpers to pass wiki model directly and compute backend host from wiki object --- app/Jobs/PollForMediaWikiJobsJob.php | 2 +- app/Services/MediaWikiHostResolver.php | 21 +++++++++++++++++++-- tests/Jobs/PollForMediaWikiJobsJobTest.php | 2 +- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/app/Jobs/PollForMediaWikiJobsJob.php b/app/Jobs/PollForMediaWikiJobsJob.php index 48514ad8..ef8d8718 100644 --- a/app/Jobs/PollForMediaWikiJobsJob.php +++ b/app/Jobs/PollForMediaWikiJobsJob.php @@ -24,7 +24,7 @@ public function handle(MediaWikiHostResolver $mwHostResolver): void { foreach ($wikis as $wiki) { try { $backendUrl = $this->mwHostResolver->getBackendUrlForWiki($wiki); - } catch (UnknownWikiDomainException | UnknownDBVersionException $e) { + } catch (UnknownWikiDomainException|UnknownDBVersionException $e) { Log::warning('Skipping wiki ' . $wiki->domain . ' for pending MediaWiki jobs: ' . $e->getMessage()); continue; diff --git a/app/Services/MediaWikiHostResolver.php b/app/Services/MediaWikiHostResolver.php index ef8584eb..7fa75dd3 100644 --- a/app/Services/MediaWikiHostResolver.php +++ b/app/Services/MediaWikiHostResolver.php @@ -44,6 +44,15 @@ public function getBackendUrlForDomain(string $domain): string { return 'http://' . $this->getBackendHostForDomain($domain); } + public function getBackendUrlForWiki($wiki): string { + return 'http://' . $this->getBackendHostForWiki($wiki); + } + + public function getBackendHostForWiki($wiki): string { + // TODO: Make host format configurable for flexibility + return sprintf('mediawiki-%s-app-backend.default.svc.cluster.local', $this->getMwVersionForWiki($wiki)); + } + private function getMwVersionForDomain(string $domain): string { $wiki = Wiki::where('domain', $domain)->first(); @@ -51,12 +60,20 @@ private function getMwVersionForDomain(string $domain): string { throw new UnknownWikiDomainException("Unknown Wiki Domain '{$domain}'."); } - $dbVersion = $wiki->wikiDb->version; + return $this->getMwVersionForWiki($wiki); + } + + private function getMwVersionForWiki($wiki): string { + $dbVersion = $wiki->wikiDb?->version; + + if ($dbVersion === null) { + throw new UnknownDBVersionException("Unknown DB version for domain '{$wiki->domain}'."); + } $versionMap = config('mw-db-version-map'); if (array_key_exists($dbVersion, $versionMap)) { return $versionMap[$dbVersion]; } - throw new UnknownDBVersionException("Unknown DB version '{$dbVersion}' for domain '{$domain}'."); + throw new UnknownDBVersionException("Unknown DB version '{$dbVersion}' for domain '{$wiki->domain}'."); } } diff --git a/tests/Jobs/PollForMediaWikiJobsJobTest.php b/tests/Jobs/PollForMediaWikiJobsJobTest.php index 4dd7821c..0cc21691 100644 --- a/tests/Jobs/PollForMediaWikiJobsJobTest.php +++ b/tests/Jobs/PollForMediaWikiJobsJobTest.php @@ -29,7 +29,7 @@ protected function setUp(): void { $this->mwBackendHost = 'http://mediawiki.localhost'; $this->mockMwHostResolver = $this->createMock(MediaWikiHostResolver::class); - $this->mockMwHostResolver->method('getBackendUrlForDomain')->willReturn( + $this->mockMwHostResolver->method('getBackendUrlForWiki')->willReturn( $this->mwBackendHost ); }