Optimizations + fix failing tests

This commit is contained in:
myrmidex 2025-08-06 20:01:28 +02:00
parent 5a142d2a3c
commit 4412974cfb
7 changed files with 81 additions and 31 deletions

View file

@ -17,14 +17,25 @@ class FeedsController extends BaseController
*/
public function index(Request $request): JsonResponse
{
$feeds = Feed::orderBy('is_active', 'desc')
$perPage = min($request->get('per_page', 15), 100);
$feeds = Feed::with(['language'])
->withCount('articles')
->orderBy('is_active', 'desc')
->orderBy('name')
->get();
->paginate($perPage);
return $this->sendResponse(
FeedResource::collection($feeds),
'Feeds retrieved successfully.'
);
return $this->sendResponse([
'feeds' => FeedResource::collection($feeds->items()),
'pagination' => [
'current_page' => $feeds->currentPage(),
'last_page' => $feeds->lastPage(),
'per_page' => $feeds->perPage(),
'total' => $feeds->total(),
'from' => $feeds->firstItem(),
'to' => $feeds->lastItem(),
]
], 'Feeds retrieved successfully.');
}
/**

View file

@ -63,14 +63,13 @@ public function store(Request $request): JsonResponse
*/
public function show(Feed $feed, PlatformChannel $channel): JsonResponse
{
$route = Route::where('feed_id', $feed->id)
->where('platform_channel_id', $channel->id)
->with(['feed', 'platformChannel'])
->first();
$route = $this->findRoute($feed, $channel);
if (!$route) {
return $this->sendNotFound('Routing configuration not found.');
}
$route->load(['feed', 'platformChannel']);
return $this->sendResponse(
new RouteResource($route),
@ -84,9 +83,7 @@ public function show(Feed $feed, PlatformChannel $channel): JsonResponse
public function update(Request $request, Feed $feed, PlatformChannel $channel): JsonResponse
{
try {
$route = Route::where('feed_id', $feed->id)
->where('platform_channel_id', $channel->id)
->first();
$route = $this->findRoute($feed, $channel);
if (!$route) {
return $this->sendNotFound('Routing configuration not found.');
@ -118,9 +115,7 @@ public function update(Request $request, Feed $feed, PlatformChannel $channel):
public function destroy(Feed $feed, PlatformChannel $channel): JsonResponse
{
try {
$route = Route::where('feed_id', $feed->id)
->where('platform_channel_id', $channel->id)
->first();
$route = $this->findRoute($feed, $channel);
if (!$route) {
return $this->sendNotFound('Routing configuration not found.');
@ -145,9 +140,7 @@ public function destroy(Feed $feed, PlatformChannel $channel): JsonResponse
public function toggle(Feed $feed, PlatformChannel $channel): JsonResponse
{
try {
$route = Route::where('feed_id', $feed->id)
->where('platform_channel_id', $channel->id)
->first();
$route = $this->findRoute($feed, $channel);
if (!$route) {
return $this->sendNotFound('Routing configuration not found.');
@ -168,4 +161,14 @@ public function toggle(Feed $feed, PlatformChannel $channel): JsonResponse
return $this->sendError('Failed to toggle routing configuration status: ' . $e->getMessage(), [], 500);
}
}
/**
* Find a route by feed and channel
*/
private function findRoute(Feed $feed, PlatformChannel $channel): ?Route
{
return Route::where('feed_id', $feed->id)
->where('platform_channel_id', $channel->id)
->first();
}
}

View file

@ -23,9 +23,10 @@ public function toArray(Request $request): array
'description' => $this->description,
'created_at' => $this->created_at->toISOString(),
'updated_at' => $this->updated_at->toISOString(),
'articles_count' => $this->when($request->routeIs('api.feeds.*'), function () {
return $this->articles()->count();
}),
'articles_count' => $this->when(
$request->routeIs('api.feeds.*') && isset($this->articles_count),
$this->articles_count
),
];
}
}

View file

@ -5,6 +5,7 @@
use App\Models\Article;
use App\Models\ArticlePublication;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class DashboardStatsService
{
@ -76,13 +77,35 @@ private function getDateRange(string $period): ?array
*/
public function getSystemStats(): array
{
// Optimize with single queries using conditional aggregation
$feedStats = DB::table('feeds')
->selectRaw('
COUNT(*) as total_feeds,
SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active_feeds
')
->first();
$channelStats = DB::table('platform_channels')
->selectRaw('
COUNT(*) as total_channels,
SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active_channels
')
->first();
$routeStats = DB::table('routes')
->selectRaw('
COUNT(*) as total_routes,
SUM(CASE WHEN is_active = 1 THEN 1 ELSE 0 END) as active_routes
')
->first();
return [
'total_feeds' => \App\Models\Feed::count(),
'active_feeds' => \App\Models\Feed::where('is_active', true)->count(),
'total_channels' => \App\Models\PlatformChannel::count(),
'active_channels' => \App\Models\PlatformChannel::where('is_active', true)->count(),
'total_routes' => \App\Models\Route::count(),
'active_routes' => \App\Models\Route::where('is_active', true)->count(),
'total_feeds' => $feedStats->total_feeds,
'active_feeds' => $feedStats->active_feeds,
'total_channels' => $channelStats->total_channels,
'active_channels' => $channelStats->active_channels,
'total_routes' => $routeStats->total_routes,
'active_routes' => $routeStats->active_routes,
];
}
}

View file

@ -17,6 +17,12 @@ public function up(): void
$table->boolean('is_duplicate')->default(false);
$table->timestamp('validated_at')->nullable();
$table->timestamps();
$table->index('url');
$table->index('is_valid');
$table->index('validated_at');
$table->index('created_at');
$table->index(['is_valid', 'created_at']);
});
}

View file

@ -17,6 +17,9 @@ public function up(): void
->after('is_duplicate');
$table->timestamp('approved_at')->nullable()->after('approval_status');
$table->string('approved_by')->nullable()->after('approved_at');
$table->index('approval_status');
$table->index(['is_valid', 'approval_status']);
});
}

View file

@ -18,7 +18,10 @@ public function test_index_returns_successful_response(): void
$response->assertStatus(200)
->assertJsonStructure([
'success',
'data',
'data' => [
'feeds',
'pagination'
],
'message'
]);
}
@ -32,7 +35,7 @@ public function test_index_returns_feeds_ordered_by_active_status_then_name(): v
$response = $this->getJson('/api/v1/feeds');
$response->assertStatus(200);
$feeds = $response->json('data');
$feeds = $response->json('data.feeds');
// First should be active feeds in alphabetical order
$this->assertEquals('A Feed', $feeds[0]['name']);