From 05840b58ff563d6627cbbecb8e5a445c21dfca6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 15 Oct 2026 16:31:18 +0200 Subject: [PATCH 1/2] feat(command): add queue option for sitemap generation - Introduced a new `--queue` option to the `uwil:sitemap:refresh` command. - Added `GenerateSitemapJob` for handling sitemap generation in the background. - Updated service provider to schedule the job with the configured cron expression. - Enhanced tests to cover new job dispatching functionality. --- README.md | 6 +++ .../Commands/GenerateSitemapCommand.php | 16 ++++-- src/Jobs/GenerateSitemapJob.php | 24 +++++++++ src/SitemapGeneratorServiceProvider.php | 11 ++-- tests/Feature/GenerateSitemapCommandTest.php | 40 ++++++++++++++ tests/Unit/Jobs/GenerateSitemapJobTest.php | 54 +++++++++++++++++++ 6 files changed, 142 insertions(+), 9 deletions(-) create mode 100644 src/Jobs/GenerateSitemapJob.php create mode 100644 tests/Unit/Jobs/GenerateSitemapJobTest.php diff --git a/README.md b/README.md index 3313109..b1b517a 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,12 @@ composer require uwil/sitemap-generator php artisan uwil:sitemap:refresh ``` + Or dispatch the generation to the queue: + + ```bash + php artisan uwil:sitemap:refresh --queue + ``` + A route is automatically registered to serve your generated sitemap: `GET /sitemap.xml` diff --git a/src/Console/Commands/GenerateSitemapCommand.php b/src/Console/Commands/GenerateSitemapCommand.php index fc39c68..10d2c9f 100644 --- a/src/Console/Commands/GenerateSitemapCommand.php +++ b/src/Console/Commands/GenerateSitemapCommand.php @@ -14,6 +14,7 @@ use Uwil\SitemapGenerator\Exceptions\SitemapException; use Uwil\SitemapGenerator\Config\SitemapConfig; use Uwil\SitemapGenerator\SitemapGenerator; use Spatie\Sitemap\Tags\Url; +use Uwil\SitemapGenerator\Jobs\GenerateSitemapJob; class GenerateSitemapCommand extends Command { @@ -22,7 +23,7 @@ class GenerateSitemapCommand extends Command * * @var string */ - protected $signature = 'uwil:sitemap:refresh {--D|dry-run}'; + protected $signature = 'uwil:sitemap:refresh {--D|dry-run} {--queue}'; /** * The console command description. @@ -41,10 +42,10 @@ class GenerateSitemapCommand extends Command try { $this->info('Generating Sitemap..'); - $sitemap = $generator->generate(); - if ($this->option('dry-run')) { + $sitemap = $generator->generate(); $this->renderTableIntoConsole($sitemap); + return 0; } @@ -52,7 +53,14 @@ class GenerateSitemapCommand extends Command $this->info("'{$config->sitemapStorage}' exist, will overwrite."); } - $config->sitemapStorage->writeInto($sitemap->render()); + if ($this->option('queue')) { + GenerateSitemapJob::dispatch(); + $this->info('Sitemap generation job dispatched to queue.'); + + return 0; + } + + GenerateSitemapJob::dispatchSync(); $this->info('A new sitemap.xml was generated'); diff --git a/src/Jobs/GenerateSitemapJob.php b/src/Jobs/GenerateSitemapJob.php new file mode 100644 index 0000000..26461c2 --- /dev/null +++ b/src/Jobs/GenerateSitemapJob.php @@ -0,0 +1,24 @@ +generate(); + + $config->sitemapStorage->writeInto($sitemap->render()); + } +} diff --git a/src/SitemapGeneratorServiceProvider.php b/src/SitemapGeneratorServiceProvider.php index 053c261..a324b96 100644 --- a/src/SitemapGeneratorServiceProvider.php +++ b/src/SitemapGeneratorServiceProvider.php @@ -5,14 +5,15 @@ declare(strict_types=1); namespace Uwil\SitemapGenerator; use Illuminate\Config\Repository as ConfigRepository; -use Uwil\SitemapGenerator\Localizers\McamaraRouteLocalizer; use Illuminate\Console\Scheduling\Schedule; use Illuminate\Contracts\Foundation\Application; use Illuminate\Support\ServiceProvider; -use Uwil\SitemapGenerator\Console\Commands\GenerateSitemapCommand; -use Uwil\SitemapGenerator\Config\SitemapConfig; -use Uwil\SitemapGenerator\Contracts\RouteLocalizerInterface; use Illuminate\Translation\Translator; +use Uwil\SitemapGenerator\Config\SitemapConfig; +use Uwil\SitemapGenerator\Console\Commands\GenerateSitemapCommand; +use Uwil\SitemapGenerator\Contracts\RouteLocalizerInterface; +use Uwil\SitemapGenerator\Jobs\GenerateSitemapJob; +use Uwil\SitemapGenerator\Localizers\McamaraRouteLocalizer; class SitemapGeneratorServiceProvider extends ServiceProvider { @@ -29,7 +30,7 @@ class SitemapGeneratorServiceProvider extends ServiceProvider if ($this->app->runningInConsole() && $config->schedule) { $this->app->booted(function () use ($config): void { $schedule = resolve(Schedule::class); - $schedule->job('uwil:sitemap:refresh')->cron((string) $config->cron); + $schedule->job(new GenerateSitemapJob())->cron((string) $config->cron); }); } } diff --git a/tests/Feature/GenerateSitemapCommandTest.php b/tests/Feature/GenerateSitemapCommandTest.php index bd4d7b4..0889704 100644 --- a/tests/Feature/GenerateSitemapCommandTest.php +++ b/tests/Feature/GenerateSitemapCommandTest.php @@ -4,10 +4,15 @@ declare(strict_types=1); namespace Uwil\SitemapGenerator\Tests\Feature; +use Illuminate\Console\Scheduling\Schedule; +use Illuminate\Support\Facades\Queue; use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Storage; use Uwil\SitemapGenerator\Config\SitemapConfig; use Uwil\SitemapGenerator\Console\Commands\GenerateSitemapCommand; +use Uwil\SitemapGenerator\Jobs\GenerateSitemapJob; +use Illuminate\Console\Scheduling\Event; +use Webmozart\Assert\Assert; covers(GenerateSitemapCommand::class); @@ -80,4 +85,39 @@ describe('GenerateSitemapCommand test', function () { // THEN $result->assertNotFound(); }); + + it('dispatches the job to queue when using --queue option', function () { + /** @var \Uwil\SitemapGenerator\Tests\TestCase $this */ + // GIVEN + Queue::fake(); + + // WHEN + /** @var \Illuminate\Testing\PendingCommand $command */ + $command = $this->artisan('uwil:sitemap:refresh --queue'); + + // THEN + $command + ->expectsOutput('Generating Sitemap..') + ->expectsOutput('Sitemap generation job dispatched to queue.') + ->assertSuccessful() + ->run(); + + Queue::assertPushed(GenerateSitemapJob::class); + }); + + it('schedules GenerateSitemapJob with configured cron expression', function () { + // GIVEN + $schedule = resolve(Schedule::class); + + // WHEN + $schedule->job(new GenerateSitemapJob())->cron('15 4 * * *'); + $events = collect($schedule->events()); + + // THEN + $event = $events->first(fn ($e) => str_contains($e->description ?? '', 'GenerateSitemapJob')); + Assert::isInstanceOf($event, Event::class); + + expect($event)->not->toBeNull() + ->and($event->expression)->toBe('15 4 * * *'); + }); }); diff --git a/tests/Unit/Jobs/GenerateSitemapJobTest.php b/tests/Unit/Jobs/GenerateSitemapJobTest.php new file mode 100644 index 0000000..251ab75 --- /dev/null +++ b/tests/Unit/Jobs/GenerateSitemapJobTest.php @@ -0,0 +1,54 @@ +outputDisk)->delete($this->outputPath); + }); + + afterEach(function () { + /** @var \Uwil\SitemapGenerator\Tests\TestCase $this */ + Storage::disk($this->outputDisk)->delete($this->outputPath); + }); + + it('generates and writes the sitemap to storage when handled', function () { + /** @var \Uwil\SitemapGenerator\Tests\TestCase $this */ + // GIVEN + Route::name('contact')->get('/{locale}/contact', fn () => 'contact'); + config()->set(SitemapConfig::CONFIG_KEY . '.single_pages', ['contact']); + + // WHEN + GenerateSitemapJob::dispatchSync(); + + // THEN + expect(Storage::disk($this->outputDisk)->exists($this->outputPath))->toBeTrue(); + $content = Storage::disk($this->outputDisk)->get($this->outputPath); + expect($content) + ->toContain('toContain('/fr/contact') + ->toContain('/en/contact'); + }); + + it('can be dispatched to queue', function () { + // GIVEN + Queue::fake(); + + // WHEN + GenerateSitemapJob::dispatch(); + + // THEN + Queue::assertPushed(GenerateSitemapJob::class); + }); +}); From af77118f74ac77df6f42a7de89554021fb1967f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Thu, 15 Oct 2026 16:34:20 +0200 Subject: [PATCH 2/2] docs: update changelog for v8.1.0 release --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8f0522..6568518 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ All notable changes to `sitemap-generator` will be documented in this file. - This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html), - Commits respect [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) & use [Gitmoji](https://gitmoji.dev/). +## **[v8.1.0] - 15/10/2026** + +### Added + +- `GenerateSitemapJob` queueable job (`ShouldQueue`) for asynchronous and background sitemap generation. +- `--queue` option on `uwil:sitemap:refresh` artisan command to dispatch generation to the queue. + +### Fixed + +- Fixed scheduler crash on staging (`Target class [uwil:sitemap:refresh] does not exist`) in `SitemapGeneratorServiceProvider` by scheduling `new GenerateSitemapJob()` instead of command signature string. + ## **[v8.0.0] - 14/10/2026** ### Added