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/Metrics/WikiMetricsTest.php b/tests/Metrics/WikiMetricsTest.php index 6648594f..82796349 100644 --- a/tests/Metrics/WikiMetricsTest.php +++ b/tests/Metrics/WikiMetricsTest.php @@ -15,7 +15,11 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Schema; +use Log; +use Psr\Log\LogLevel; use Tests\TestCase; +use TiMacDonald\Log\LogEntry; +use TiMacDonald\Log\LogFake; class WikiMetricsTest extends TestCase { use RefreshDatabase; @@ -70,6 +74,55 @@ public function testNoDuplicateRecordsWithOnlyDateChange() { ]); } + public function testPreventMetricsCollectionWhenRecordExistsForToday(): void { + Log::swap(new LogFake()); + + $wiki = Wiki::factory()->create(); + WikiDb::first()->update(['wiki_id' => $wiki->id]); + + $wiki->wikiSiteStats()->create([ + 'pages' => 10, + 'users' => 3, + ]); + + $wikiMetrics = new WikiMetrics(); + $wikiMetrics->saveMetrics($wiki); + + $this->assertDatabaseCount('wiki_daily_metrics', 1) + ->assertDatabaseHas('wiki_daily_metrics', [ + 'wiki_id' => $wiki->id, + 'date' => now()->toDateString(), + 'pages' => 10, + 'total_user_count' => 3, + ]); + + $wiki->wikiSiteStats()->first()->update([ + 'pages' => 12, + 'users' => 5, + ]); + + $wikiMetrics->saveMetrics($wiki); + + $this->assertDatabaseCount('wiki_daily_metrics', 1) + ->assertDatabaseHas('wiki_daily_metrics', [ + 'wiki_id' => $wiki->id, + 'date' => now()->toDateString(), + 'pages' => 10, + 'total_user_count' => 3, + ]); + + Log::assertLogged(function (LogEntry $log) use ($wiki) { + if ($log->level !== LogLevel::WARNING) { + return false; + } + + return str_contains( + $log->message, + "Daily metric already exists for Wiki ID {$wiki->id} on " . now()->toDateString() + ); + }); + } + public function testRecordCreatedWhenWikiFirstDeleted() { $wiki = Wiki::factory()->create([ 'domain' => 'thisfake.wikibase.cloud',