diff --git a/app/Metrics/App/WikiMetrics.php b/app/Metrics/App/WikiMetrics.php index e0915e93..69e485e6 100644 --- a/app/Metrics/App/WikiMetrics.php +++ b/app/Metrics/App/WikiMetrics.php @@ -25,6 +25,15 @@ public function saveMetrics(Wiki $wiki): void { $this->wiki = $wiki; $today = now()->format('Y-m-d'); + $previousRecord = WikiDailyMetrics::where('wiki_id', $wiki->id)->latest('date')->first(); + + // Skip expensive metrics collection if a record for today already exists. + if ($previousRecord?->date === $today) { + Log::warning("Daily metric already exists for Wiki ID {$wiki->id} on {$today}; skipping metrics collection."); + + return; + } + $tripleCount = $this->getNumOfTriples(); $todayPageCount = $wiki->wikiSiteStats()->first()->pages ?? 0; $isDeleted = (bool) $wiki->deleted_at; @@ -57,8 +66,7 @@ public function saveMetrics(Wiki $wiki): void { 'total_user_count' => $numberOfUsers, ]); - // compare current record to previous record and only save if there is a change - $previousRecord = WikiDailyMetrics::where('wiki_id', $wiki->id)->latest('date')->first(); + // compare current metrics to previous record and only save if there is a change if ($previousRecord?->areMetricsEqual($dailyMetrics)) { Log::info("Record unchanged for Wiki ID {$wiki->id}, no new record added."); diff --git a/tests/Jobs/UpdateWikiDailyMetricJobTest.php b/tests/Jobs/UpdateWikiDailyMetricJobTest.php index e3c601c5..3e246467 100644 --- a/tests/Jobs/UpdateWikiDailyMetricJobTest.php +++ b/tests/Jobs/UpdateWikiDailyMetricJobTest.php @@ -8,8 +8,11 @@ use App\WikiDb; use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Queue; use Tests\TestCase; +use TiMacDonald\Log\LogEntry; +use TiMacDonald\Log\LogFake; class UpdateWikiDailyMetricJobTest extends TestCase { use RefreshDatabase; @@ -72,4 +75,46 @@ public function testRunJobForAllWikisIncludingDeletedWikis() { 'entity_schema_count' => 0, ]); } + + public function testWikiMetricsCollectionStopsEarlyWhenRecordExistsForToday() { + Log::swap(new LogFake()); + + $wiki = Wiki::factory()->create([ + 'domain' => 'duplicate.wikibase.cloud', + ]); + + dispatch(new ProvisionWikiDbJob()); + + $wikiDb = WikiDb::whereDoesntHave('wiki')->first(); + $wikiDb->update(['wiki_id' => $wiki->id]); + + $wiki->wikiSiteStats()->create([ + 'pages' => 10, + 'users' => 3, + ]); + + UpdateWikiDailyMetricJob::dispatch(); + + $wiki->wikiSiteStats()->first()->update([ + 'pages' => 12, + 'users' => 5, + ]); + + UpdateWikiDailyMetricJob::dispatch(); + + $this->assertDatabaseCount('wiki_daily_metrics', 1) + ->assertDatabaseHas('wiki_daily_metrics', [ + 'wiki_id' => $wiki->id, + 'date' => Carbon::today()->toDateString(), + 'pages' => 10, + ]); + + Log::assertLogged(function (LogEntry $log) use ($wiki) { + if ($log->level !== 'warning') { + return false; + } + + return str_contains($log->message, "Daily metric already exists for Wiki ID {$wiki->id} on " . Carbon::today()->toDateString()); + }); + } }