mirror of
https://github.com/linuxserver/Heimdall.git
synced 2026-08-07 07:16:13 +00:00
Merge pull request #1570 from linuxserver/fix/getstats-graceful-failure
Return graceful output from get_stats instead of a 500
This commit is contained in:
@@ -587,18 +587,46 @@ class ItemController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
* @return void
|
||||
* Return live stats for an enhanced application tile.
|
||||
*
|
||||
* Always responds with HTTP 200 and valid JSON so the frontend refresh
|
||||
* loop (liveStatRefresh.js) keeps re-queueing the tile. On any failure we
|
||||
* degrade gracefully to an inactive, empty tile instead of a 500.
|
||||
*
|
||||
* @param int|string $id
|
||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response
|
||||
*/
|
||||
public function getStats($id)
|
||||
{
|
||||
$item = Item::find($id);
|
||||
$graceful = response()->json(['status' => 'inactive', 'html' => '']);
|
||||
|
||||
$item = Item::find($id);
|
||||
if ($item === null) {
|
||||
return $graceful;
|
||||
}
|
||||
|
||||
// Non-enhanced items (or stale records) have no live-stats class.
|
||||
if (empty($item->class)) {
|
||||
return $graceful;
|
||||
}
|
||||
|
||||
try {
|
||||
$config = $item->getconfig();
|
||||
|
||||
// Guard against a stale/renamed class string from the remote apps repo.
|
||||
if (! class_exists($item->class)) {
|
||||
return $graceful;
|
||||
}
|
||||
|
||||
$config = $item->getconfig();
|
||||
if (isset($item->class)) {
|
||||
$application = new $item->class;
|
||||
$application->config = $config;
|
||||
echo $application->livestats();
|
||||
|
||||
// livestats() returns a JSON string; return it verbatim (no re-encoding).
|
||||
return response($application->livestats());
|
||||
} catch (\Throwable $e) {
|
||||
Log::error('getStats failed for item '.$id.' ('.$item->class.'): '.$e->getMessage());
|
||||
|
||||
return $graceful;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Item;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
* Fixture app whose live stats rendering throws, mirroring the Komga
|
||||
* failure from issue #1558 (broken remote blade / upstream API error).
|
||||
*/
|
||||
class ThrowingStatApp
|
||||
{
|
||||
public $config;
|
||||
|
||||
public function livestats()
|
||||
{
|
||||
throw new \Exception('boom');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixture app whose live stats rendering succeeds and returns the JSON
|
||||
* string the frontend expects.
|
||||
*/
|
||||
class HappyStatApp
|
||||
{
|
||||
public $config;
|
||||
|
||||
public function livestats()
|
||||
{
|
||||
return json_encode(['status' => 'active', 'html' => '<b>ok</b>']);
|
||||
}
|
||||
}
|
||||
|
||||
class GetStatsTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_missing_item_id_does_not_500(): void
|
||||
{
|
||||
$response = $this->get('get_stats/999999');
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson(['status' => 'inactive', 'html' => '']);
|
||||
}
|
||||
|
||||
public function test_throwing_app_degrades_gracefully(): void
|
||||
{
|
||||
$item = Item::factory()->create([
|
||||
'class' => ThrowingStatApp::class,
|
||||
]);
|
||||
|
||||
$response = $this->get('get_stats/'.$item->id);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson(['status' => 'inactive', 'html' => '']);
|
||||
}
|
||||
|
||||
public function test_item_with_no_class_degrades_gracefully(): void
|
||||
{
|
||||
$item = Item::factory()->create([
|
||||
'class' => null,
|
||||
]);
|
||||
|
||||
$response = $this->get('get_stats/'.$item->id);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$response->assertJson(['status' => 'inactive', 'html' => '']);
|
||||
}
|
||||
|
||||
public function test_happy_path_returns_livestats_output_verbatim(): void
|
||||
{
|
||||
$item = Item::factory()->create([
|
||||
'class' => HappyStatApp::class,
|
||||
]);
|
||||
|
||||
$expected = json_encode(['status' => 'active', 'html' => '<b>ok</b>']);
|
||||
|
||||
$response = $this->get('get_stats/'.$item->id);
|
||||
|
||||
$response->assertStatus(200);
|
||||
$this->assertSame($expected, $response->getContent());
|
||||
$response->assertJson(['status' => 'active', 'html' => '<b>ok</b>']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user