Files

202 lines
5.7 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Jobs\BatchImportFromGutendex;
use App\Jobs\GenerateSummary;
use App\Models\Book;
use App\Models\Summary;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class GutendexController extends Controller
{
/**
* Display the Gutendex admin dashboard.
*/
public function dashboard()
{
$stats = $this->getStatistics();
$recentImports = $this->getRecentImports();
$recentFailures = $this->getRecentFailures();
return view('admin.gutendex.dashboard', compact('stats', 'recentImports', 'recentFailures'));
}
/**
* Display processing status.
*/
public function status()
{
$stats = $this->getStatistics();
$processing = Summary::processing()->with('book')->get();
$pending = Summary::pending()->with('book')->limit(20)->get();
$failed = Summary::failed()->with('book')->limit(20)->get();
$queueStats = $this->getQueueStatistics();
return view('admin.gutendex.status', compact('stats', 'processing', 'pending', 'failed', 'queueStats'));
}
/**
* Trigger a new import.
*/
public function import(Request $request)
{
$request->validate([
'language' => 'required|string|max:10',
'limit' => 'required|integer|min:1|max:500',
'page' => 'required|integer|min:1',
'generate_summaries' => 'boolean',
]);
$language = $request->input('language', 'en');
$limit = (int) $request->input('limit', 50);
$page = (int) $request->input('page', 1);
$generateSummaries = $request->boolean('generate_summaries', true);
$filters = [
'languages' => $language,
'copyright' => 'false',
];
// Calculate end page
$booksPerPage = 32;
$endPage = $page + (int) ceil($limit / $booksPerPage) - 1;
// Dispatch batch import job
BatchImportFromGutendex::dispatch(
$filters,
$page,
$endPage,
$limit,
$generateSummaries
);
return response()->json([
'success' => true,
'message' => "Import job dispatched for up to {$limit} books",
'details' => [
'language' => $language,
'limit' => $limit,
'start_page' => $page,
'end_page' => $endPage,
'generate_summaries' => $generateSummaries,
],
]);
}
/**
* Retry a failed book summary.
*/
public function retry(Book $book)
{
if (!$book->summary) {
return response()->json([
'success' => false,
'message' => 'Book does not have a summary record',
], 404);
}
if ($book->summary->processing_status === 'completed') {
return response()->json([
'success' => false,
'message' => 'Summary is already completed',
], 400);
}
// Dispatch job to regenerate summary
GenerateSummary::dispatch($book->id);
return response()->json([
'success' => true,
'message' => "Retry job dispatched for: {$book->title}",
'book_id' => $book->id,
]);
}
/**
* Get overall statistics.
*/
protected function getStatistics(): array
{
$totalBooks = Book::count();
$gutendexBooks = Book::gutendex()->count();
$booksWithText = Book::whereNotNull('full_text_url')->count();
$booksWithoutSummaries = Book::gutendex()
->whereNotNull('full_text_url')
->doesntHave('summary')
->count();
$totalSummaries = Summary::count();
$completedSummaries = Summary::completed()->count();
$pendingSummaries = Summary::pending()->count();
$processingSummaries = Summary::processing()->count();
$failedSummaries = Summary::failed()->count();
$completionRate = $totalSummaries > 0
? round(($completedSummaries / $totalSummaries) * 100, 2)
: 0;
return [
'total_books' => $totalBooks,
'gutendex_books' => $gutendexBooks,
'books_with_text' => $booksWithText,
'books_without_summaries' => $booksWithoutSummaries,
'total_summaries' => $totalSummaries,
'completed_summaries' => $completedSummaries,
'pending_summaries' => $pendingSummaries,
'processing_summaries' => $processingSummaries,
'failed_summaries' => $failedSummaries,
'completion_rate' => $completionRate,
];
}
/**
* Get recent imports.
*/
protected function getRecentImports(int $limit = 10): array
{
return Book::gutendex()
->with('category')
->orderByDesc('created_at')
->limit($limit)
->get()
->toArray();
}
/**
* Get recent failures.
*/
protected function getRecentFailures(int $limit = 10): array
{
return Summary::failed()
->with('book')
->orderByDesc('updated_at')
->limit($limit)
->get()
->toArray();
}
/**
* Get queue statistics.
*/
protected function getQueueStatistics(): array
{
try {
$pendingJobs = DB::table('jobs')->count();
$failedJobs = DB::table('failed_jobs')->count();
return [
'pending_jobs' => $pendingJobs,
'failed_jobs' => $failedJobs,
];
} catch (\Exception $e) {
return [
'pending_jobs' => 0,
'failed_jobs' => 0,
];
}
}
}