gutendex integration, phase 6

This commit is contained in:
Doar Mihai
2026-03-29 16:14:18 +03:00
parent 0b26cde74e
commit 86de669aee
12 changed files with 1820 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
<?php
namespace App\Console\Commands;
use App\Jobs\BatchImportFromGutendex;
use App\Jobs\ImportBookFromGutendex;
use Illuminate\Console\Command;
class ImportFromGutendex extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'gutendex:import
{--language=en : Language code to filter books}
{--limit=100 : Maximum number of books to import}
{--page=1 : Starting page number}
{--queue : Run the import via queue jobs}
{--no-summary : Skip summary generation}
{--copyright=false : Copyright filter (false for public domain)}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Import books from Gutendex API with optional filters';
/**
* Execute the console command.
*/
public function handle(): int
{
$language = $this->option('language');
$limit = (int) $this->option('limit');
$page = (int) $this->option('page');
$useQueue = $this->option('queue');
$generateSummary = !$this->option('no-summary');
$copyright = $this->option('copyright');
$this->info('Gutendex Import');
$this->info('==============');
$this->newLine();
// Build filters
$filters = [
'languages' => $language,
'copyright' => $copyright,
];
$this->table(
['Setting', 'Value'],
[
['Language', $language],
['Limit', $limit],
['Starting Page', $page],
['Mode', $useQueue ? 'Queued' : 'Immediate'],
['Generate Summaries', $generateSummary ? 'Yes' : 'No'],
['Copyright Filter', $copyright],
]
);
if (!$this->confirm('Do you want to proceed with this import?', true)) {
$this->warn('Import cancelled.');
return self::SUCCESS;
}
$this->newLine();
if ($useQueue) {
return $this->handleQueuedImport($filters, $page, $limit, $generateSummary);
} else {
return $this->handleImmediateImport($filters, $page, $limit, $generateSummary);
}
}
/**
* Handle queued import.
*/
protected function handleQueuedImport(array $filters, int $page, int $limit, bool $generateSummary): int
{
$this->info('Dispatching batch import job...');
// Calculate end page based on limit (assuming ~32 books per page)
$booksPerPage = 32;
$endPage = $page + (int) ceil($limit / $booksPerPage) - 1;
BatchImportFromGutendex::dispatch(
$filters,
$page,
$endPage,
$limit,
$generateSummary
);
$this->info('✓ Batch import job dispatched successfully!');
$this->newLine();
$this->comment('The import will be processed in the background.');
$this->comment('Run the queue worker: php artisan queue:work');
$this->comment('Monitor progress: php artisan summary:status');
return self::SUCCESS;
}
/**
* Handle immediate import (synchronous).
*/
protected function handleImmediateImport(array $filters, int $page, int $limit, bool $generateSummary): int
{
$this->warn('⚠ Running immediate import. This may take a while...');
$this->warn('⚠ For large imports, consider using --queue option.');
$this->newLine();
$gutendexClient = app(\App\Services\GutendexClient::class);
$totalImported = 0;
$totalSkipped = 0;
$currentPage = $page;
$progressBar = $this->output->createProgressBar($limit);
$progressBar->start();
while ($totalImported < $limit) {
$response = $gutendexClient->searchBooks(null, $currentPage, $filters);
if (empty($response['results'])) {
$this->newLine();
$this->warn('No more results available.');
break;
}
foreach ($response['results'] as $bookData) {
if ($totalImported >= $limit) {
break 2;
}
$gutenbergId = $bookData['id'] ?? null;
if (!$gutenbergId) {
continue;
}
// Check if already exists
if (\App\Models\Book::where('gutenberg_id', $gutenbergId)->exists()) {
$totalSkipped++;
$progressBar->advance();
continue;
}
// Dispatch job
ImportBookFromGutendex::dispatch($gutenbergId, $generateSummary);
$totalImported++;
$progressBar->advance();
}
if (empty($response['next'])) {
break;
}
$currentPage++;
}
$progressBar->finish();
$this->newLine(2);
$this->info('✓ Import jobs dispatched successfully!');
$this->newLine();
$this->table(
['Metric', 'Count'],
[
['Jobs Dispatched', $totalImported],
['Books Skipped (existing)', $totalSkipped],
['Pages Processed', $currentPage - $page + 1],
]
);
$this->newLine();
$this->comment('Jobs have been dispatched to the queue.');
$this->comment('Run the queue worker: php artisan queue:work');
return self::SUCCESS;
}
}