gutendex integration, phase 6
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user