add MAL Heartbeat info to / root response

This commit is contained in:
Irfan 2021-06-13 02:51:27 +05:00
parent aecf8db789
commit 5a5dcfb36b
5 changed files with 73 additions and 3 deletions

View File

@ -35,6 +35,9 @@ SOURCE_BAD_HEALTH_RECHECK=10
SOURCE_BAD_HEALTH_RANGE=30
# Max Fail stores
SOURCE_BAD_HEALTH_MAX_STORE=50
# Disable failover if the score reaches the following (0.0-1.0 values ONLY)
# e.g 0.9 means 90% successful requests to MyAnimeList
SOURCE_GOOD_HEALTH_SCORE=0.9
# Max time request is allowed to take
# https://curl.haxx.se/libcurl/c/CURLOPT_TIMEOUT.html
SOURCE_TIMEOUT=5

View File

@ -16,7 +16,7 @@ class SourceHeartbeatMonitor
*/
public function handle($request, Closure $next)
{
event(new SourceHeartbeatEvent(SourceHeartbeatEvent::GOOD_HEALTH, 200));
event(new SourceHeartbeatEvent(SourceHeartbeatEvent::GOOD_HEALTH, 500));
return $next($request);
}

View File

@ -86,7 +86,7 @@ class SourceHeartbeatListener
{
$score = $this->getSuccessfulRequestsScore();
if ($score >= 0.9) {
if ($score >= env('SOURCE_GOOD_HEALTH_SCORE', 0.9)) {
$this->disableFailover();
$this->logger->debug('Failover disabled; Score: '.$score);
$this->logger->debug('Failover DISABLED');

View File

@ -2,6 +2,7 @@
namespace App\Providers;
use App\Events\SourceHeartbeatEvent;
use Illuminate\Support\Facades\Storage;
use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;
@ -25,4 +26,64 @@ class SourceHeartbeatProvider extends ServiceProvider
{
return Storage::exists('source_failover.lock');
}
public static function getLastDowntime() : int
{
try {
return Storage::lastModified('source_failover.lock');
} catch (\Exception $e) {
return 0;
}
}
public static function getHeartbeatScore() : float
{
try {
$failsJson = Storage::get('failovers.json');
$fails = json_decode($failsJson, true);
} catch (\Exception $e) {
$fails = [];
}
// remove any fails greater than SOURCE_BAD_HEALTH_RANGE
foreach ($fails as $fail) {
if ($fail[0] >= (time()-env('SOURCE_BAD_HEALTH_RANGE'))) {
unset($fail);
}
}
// slice
if (count($fails) > env('SOURCE_BAD_HEALTH_MAX_STORE')) {
$fails = array_slice($fails, 0 - env('SOURCE_BAD_HEALTH_MAX_STORE'));
}
$score = 0;
$totalFails = count($fails) - 1;
foreach ($fails as $fail) {
if ((int) $fail[2] === SourceHeartbeatEvent::GOOD_HEALTH) {
$score++;
}
}
$scored = $score / max($totalFails, 1);
return $scored;
}
public static function getHeartbeatStatus() : string
{
$score = self::getHeartbeatScore();
if ($score > 0.5 && $score < env('SOURCE_GOOD_HEALTH_SCORE')) {
return "LEARNING";
}
if ($score <= 0.5) {
return "UNHEALTHY";
}
return "HEALTHY";
}
}

View File

@ -12,7 +12,13 @@ $router->get('/', function () use ($router) {
'github_url' => 'https://github.com/jikan-me/jikan-rest',
'parser_github_url' => 'https://github.com/jikan-me/jikan',
'production_api_url' => 'https://api.jikan.moe/v4/',
'status_url' => 'https://status.jikan.moe'
'status_url' => 'https://status.jikan.moe',
'myanimelist_heartbeat' => [
'status' => \App\Providers\SourceHeartbeatProvider::getHeartbeatStatus(),
'score' => \App\Providers\SourceHeartbeatProvider::getHeartbeatScore(),
'down' => \App\Providers\SourceHeartbeatProvider::isFailoverEnabled(),
'last_downtime' => \App\Providers\SourceHeartbeatProvider::getLastDowntime()
]
]);
});