From 29aafe9f75fa8765b8f15a0fbea8a8fe2e33a5e4 Mon Sep 17 00:00:00 2001 From: Dominik Hebeler <dominik@suma-ev.de> Date: Tue, 19 Feb 2019 12:10:04 +0100 Subject: [PATCH] Added the option to auto disable search engines --- app/Console/Commands/LogRotate.php | 119 ----------------- .../Commands/MonthlyRequestsGather.php | 121 ++++++++++++++++++ app/Console/Kernel.php | 10 +- app/MetaGer.php | 19 ++- app/Models/Searchengine.php | 6 + .../2019_02_19_094337_monthlyrequests.php | 33 +++++ 6 files changed, 175 insertions(+), 133 deletions(-) delete mode 100644 app/Console/Commands/LogRotate.php create mode 100644 app/Console/Commands/MonthlyRequestsGather.php create mode 100644 database/migrations/2019_02_19_094337_monthlyrequests.php diff --git a/app/Console/Commands/LogRotate.php b/app/Console/Commands/LogRotate.php deleted file mode 100644 index c539881ff..000000000 --- a/app/Console/Commands/LogRotate.php +++ /dev/null @@ -1,119 +0,0 @@ -<?php - -namespace App\Console\Commands; - -use Illuminate\Console\Command; -use Illuminate\Support\Facades\Redis; - -class LogRotate extends Command -{ - /** - * The name and signature of the console command. - * - * @var string - */ - protected $signature = 'log:rotate'; - - /** - * The console command description. - * - * @var string - */ - protected $description = 'Dieses Kommando bezieht alle Log-Einträge aus dem Redis System und exportiert diese in entsprechende Dateien.'; - - /** - * Create a new command instance. - * - * @return void - */ - public function __construct() - { - parent::__construct(); - } - - /** - * Execute the console command. - * - * @return mixed - */ - public function handle() - { - # Wir extrahieren die Logs mit den Daten der einzelnen Suchmaschinen: - # In den Daten ist festgehalten, wie oft eine jede Suchmaschine abgefragt wurde - # und wie häufig diese geantwortet hat: - $this->extractSearchEngineLogs(); - } - - private function extractSearchEngineLogs() - { - $redis = Redis::connection('redisLogs'); - # Hier legen wir das Ergebnis ab: - # [ - # 'fastbot' => [ - # '' - # ] - # ] - $searchEngineLogs = ['recent' => [], 'overall' => []]; - try { - # Wir benötigen zunächst die Namen aller Suchmaschinen: - $sumasFile = config_path() . "/sumas.xml"; - $xml = simplexml_load_file($sumasFile); - $xml = $xml->xpath("suma"); - $sumaNames = []; - foreach ($xml as $suma) { - $searchEngineLogs['recent'][$suma["name"]->__toString()] = ["requests" => 0, "answered" => 0]; - } - #Auslesen/hinzufügen der Daten: - foreach ($searchEngineLogs['recent'] as $name => $values) { - $searchEngineLogs['recent'][$name]["requests"] = $redis->getset('logs.engines.requests.' . $name, 0); - $searchEngineLogs['recent'][$name]["answered"] = $redis->getset('logs.engines.answered.' . $name, 0); - } - - $filePath = "/var/log/metager/"; - # Wir haben nun die aktuellen daten und müssen diese noch mit den aktuellen Kombinieren: - # Hierbei behalten wir die Daten, seid dem letzten Rotate so wie sie sind und verknüpfen diese mit einer gesamt Statistik. - if (file_exists($filePath . "engine.log") && is_readable($filePath . "engine.log")) { - $oldData = file_get_contents($filePath . "engine.log"); - # JSON Decode - $oldData = json_decode($oldData, true); - if (isset($oldData['overall'])) { - $searchEngineLogs['overall'] = $oldData['overall']; - } - } - - # Jetzt fügen wir zu den Gesamtdaten die zuletzt erfassten hinzu: - foreach ($searchEngineLogs['recent'] as $name => $values) { - if (isset($searchEngineLogs['overall'][$name]["requests"])) { - $searchEngineLogs['overall'][$name]["requests"] += $values["requests"]; - } else { - $searchEngineLogs['overall'][$name]["requests"] = $values["requests"]; - } - if (isset($searchEngineLogs['overall'][$name]["answered"])) { - $searchEngineLogs['overall'][$name]["answered"] += $values["answered"]; - } else { - $searchEngineLogs['overall'][$name]["answered"] = $values["answered"]; - } - } - - # Ins JSON Format umwandeln: - $searchEngineLogs = json_encode($searchEngineLogs, JSON_PRETTY_PRINT); - - # Und in die Datei sichern - if (((file_exists($filePath . "engine.log") && is_writable($filePath . "engine.log")) || (!file_exists($filePath . "engine.log") && is_writable($filePath))) && file_put_contents($filePath . "engine.log", $searchEngineLogs) !== false) { - $this->info("Logs der Suchmaschinen erfolgreich exportiert."); - return; - } else { - # Der Schreibvorgang war nicht erfolgreich. Wir packen die Daten zurück - foreach (json_decode($searchEngineLogs, true) as $name => $values) { - $redis->incrby('logs.engines.requests.' . $name, $values["requests"]); - $redis->incrby('logs.engines.answered.' . $name, $values["answered"]); - } - $this->info("Konnte die Datei \"$filePath" . "engine.log\" nicht erstellen. Keine Rechte."); - return; - } - - } catch (\ErrorException $e) { - return; - } - } -} diff --git a/app/Console/Commands/MonthlyRequestsGather.php b/app/Console/Commands/MonthlyRequestsGather.php new file mode 100644 index 000000000..f2cbb06c0 --- /dev/null +++ b/app/Console/Commands/MonthlyRequestsGather.php @@ -0,0 +1,121 @@ +<?php + +namespace App\Console\Commands; + +use DB; +use Illuminate\Console\Command; +use Illuminate\Support\Facades\Redis; + +class MonthlyRequestsGather extends Command +{ + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'requests:gather'; + + /** + * The console command description. + * + * @var string + */ + protected $description = 'Sends the gathered monthly requests from the redis to the central Database'; + + private $values = []; + + /** + * Create a new command instance. + * + * @return void + */ + public function __construct() + { + parent::__construct(); + } + + /** + * Execute the console command. + * + * @return mixed + */ + public function handle() + { + # Read in the suma Files + $sumaFile = config_path('sumas.json'); + $sumaEnFile = config_path('sumasEn.json'); + if (file_exists($sumaFile) && file_exists($sumaEnFile)) { + $sumas = json_decode(file_get_contents($sumaFile)); + $sumasEn = json_decode(file_get_contents($sumaEnFile)); + + $this->gatherLogs($sumas); + $this->gatherLogs($sumasEn); + + foreach ($this->values as $name => $value) { + $entry = DB::table('monthlyrequests')->where(['name' => $name])->first(); + $newCount = $value; + if ($entry === null) { + DB::table('monthlyrequests')->insert(['name' => $name, 'count' => $newCount]); + } else { + $newCount = $value + $entry->count; + DB::table('monthlyrequests')->where(['name' => $name])->update(['count' => $newCount]); + } + } + + $this->disableOverusedEngines($sumaFile, $sumas); + $this->disableOverusedEngines($sumaEnFile, $sumasEn); + + } + } + + private function disableOverusedEngines($sumasFile, $sumas) + { + $currentValues = DB::table('monthlyrequests')->get(); + foreach ($sumas->sumas as $sumaName => $suma) { + if (!empty($suma->disabled) && $suma->disabled === true) { + continue; + } + + if (empty($suma->{"monthly-requests"})) { + continue; + } + $currentValue = 0; + foreach ($currentValues as $value) { + if ($value->name === $sumaName) { + $currentValue = $value->count; + } + } + + $monthlyRequests = $suma->{"monthly-requests"}; + + if (!empty($suma->{"auto-disabled"}) && $suma->{"auto-disabled"} === true) { + # Maybe this engine should be enabled again + if ($currentValue < $monthlyRequests) { + unset($sumas->sumas->{$sumaName}->{"auto-disabled"}); + file_put_contents($sumasFile, json_encode($sumas, JSON_PRETTY_PRINT)); + } + } else if ($currentValue >= $monthlyRequests) { + $sumas->sumas->{$sumaName}->{"auto-disabled"} = true; + file_put_contents($sumasFile, json_encode($sumas, JSON_PRETTY_PRINT)); + } + } + } + + private function gatherLogs($sumas) + { + foreach ($sumas->sumas as $sumaName => $suma) { + if (!empty($suma->{"monthly-requests"})) { + $monthlyLimit = $suma->{"monthly-requests"}; + $currentValue = Redis::get('monthlyRequests:' . $sumaName); + Redis::del('monthlyRequests:' . $sumaName); + if (empty($currentValue)) { + $currentValue = 0; + } + if (empty($this->values[$sumaName]) && $currentValue > 0) { + $this->values[$sumaName] = intval($currentValue); + } + } + + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index d3655e50e..6290dc5c2 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -25,10 +25,14 @@ class Kernel extends ConsoleKernel */ protected function schedule(Schedule $schedule) { - $schedule->command('log:rotate')->everyTenMinutes(); + $schedule->command('requests:gather')->everyFifteenMinutes(); + + $schedule->call(function () { + DB::table('monthlyrequests')->truncate(); + })->monthlyOn(1, '00:00'); // Delete all of the old humanverification entries - $schedule->call(function() { + $schedule->call(function () { DB::delete('DELETE FROM humanverification WHERE updated_at < (now() - interval 72 hour) AND whitelist = 0 ORDER BY updated_at DESC'); DB::delete('DELETE FROM humanverification WHERE updated_at < (now() - interval 2 week) AND whitelist = 1 ORDER BY updated_at DESC'); })->everyThirtyMinutes(); @@ -42,6 +46,6 @@ class Kernel extends ConsoleKernel protected function commands() { require base_path('routes/console.php'); - $this->load(__DIR__.'/Commands'); + $this->load(__DIR__ . '/Commands'); } } diff --git a/app/MetaGer.php b/app/MetaGer.php index 65a1e4a69..f1eca712b 100644 --- a/app/MetaGer.php +++ b/app/MetaGer.php @@ -542,7 +542,8 @@ class MetaGer foreach ($this->sumaFile->foki->{$this->fokus}->sumas as $suma) { # Check if this engine is disabled and can't be used $disabled = empty($this->sumaFile->sumas->{$suma}->disabled) ? false : $this->sumaFile->sumas->{$suma}->disabled; - if ($disabled) { + $autoDisabled = empty($this->sumaFile->sumas->{$suma}->{"auto-disabled"}) ? false : $this->sumaFile->sumas->{$suma}->{"auto-disabled"}; + if ($disabled || $autoDisabled) { continue; } @@ -710,6 +711,11 @@ class MetaGer foreach ($this->sumaFile->foki->{$this->fokus}->sumas as $suma) { if ($this->sumaFile->sumas->{$suma}->{"filter-opt-in"}) { if (!empty($filter->sumas->{$suma})) { + # If the searchengine is disabled this filter shouldn't be available + if ((!empty($this->sumaFile->sumas->{$suma}->disabled) && $this->sumaFile->sumas->{$suma}->disabled === true) + || (!empty($this->sumaFile->sumas->{$suma}->{"auto-disabled"}) && $this->sumaFile->sumas->{$suma}->{"auto-disabled"} === true)) { + continue; + } $availableFilter[$filterName] = $filter; } } @@ -1343,16 +1349,7 @@ class MetaGer # 2 Arten von Logs in einem wird die Anzahl der Abfragen an eine Suchmaschine gespeichert und in der anderen # die Anzahl, wie häufig diese Ergebnisse geliefert hat. - $enginesToLoad = $this->enginesToLoad; - $redis->pipeline(function ($pipe) use ($enginesToLoad, $logEntry) { - $pipe->rpush('logs.search', $logEntry); - foreach ($this->enginesToLoad as $name => $answered) { - $pipe->incr('logs.engines.requests.' . $name); - if ($answered) { - $pipe->incr('logs.engines.answered.' . $name); - } - } - }); + $redis->rpush('logs.search', $logEntry); } catch (\Exception $e) { return; } diff --git a/app/Models/Searchengine.php b/app/Models/Searchengine.php index 686268a28..03b584048 100644 --- a/app/Models/Searchengine.php +++ b/app/Models/Searchengine.php @@ -134,6 +134,12 @@ abstract class Searchengine // each Searcher has it's own queue lying under the redis key <name>.queue Redis::rpush($this->name . ".queue", $mission); + // The request is not cached and will be submitted to the searchengine + // We need to check if the number of requests to this engine are limited + if (!empty($this->engine->{"monthly-requests"})) { + Redis::incr("monthlyRequests:" . $this->name); + } + /** * We have Searcher processes running for MetaGer * Each Searcher is dedicated to one specific Searchengine and fetches it's results. diff --git a/database/migrations/2019_02_19_094337_monthlyrequests.php b/database/migrations/2019_02_19_094337_monthlyrequests.php new file mode 100644 index 000000000..bb1491894 --- /dev/null +++ b/database/migrations/2019_02_19_094337_monthlyrequests.php @@ -0,0 +1,33 @@ +<?php + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +class Monthlyrequests extends Migration +{ + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('monthlyrequests', function (Blueprint $table) { + $table->string('name')->unique(); + $table->integer('count'); + $table->timestamp('updated_at'); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::drop('sponsorenlinks'); + } +} -- GitLab