diff --git a/README.md b/README.md index 548e23a..060b642 100644 --- a/README.md +++ b/README.md @@ -105,6 +105,9 @@ DB::transaction(function () { }); ``` +> [!WARNING] +> Make sure to not call `Rmq::stage` within a loop since each call does a database insertion. + ### Phase 2: Deleting the files Delete the files staged by the singleton: @@ -123,7 +126,7 @@ use Medilies\RmQ\Facades\RmQ; RmQ::deleteAll(); ``` -Delete all the staged files using a command: +Delete all the staged files using a command (you can also [schedule](https://laravel.com/docs/11.x/scheduling#scheduling-artisan-commands) it): ```shell php artisan rm-q:delete @@ -141,8 +144,6 @@ Route::put('edit-user-details', function (Request $request) { })->middleware(RmqMiddleware::class); ``` -Using a Queued Job (TODO). - ## Changelog Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. diff --git a/src/Commands/RmqCleanupCommand.php b/src/Commands/RmqCleanupCommand.php new file mode 100644 index 0000000..fd49157 --- /dev/null +++ b/src/Commands/RmqCleanupCommand.php @@ -0,0 +1,25 @@ +delete(); + + $this->comment('Table cleaned up.'); + + return self::SUCCESS; + } +} diff --git a/src/Commands/RmqDeleteCommand.php b/src/Commands/RmqDeleteCommand.php index 46c0aa4..b23f595 100644 --- a/src/Commands/RmqDeleteCommand.php +++ b/src/Commands/RmqDeleteCommand.php @@ -11,8 +11,6 @@ class RmqDeleteCommand extends Command public $description = 'Delete staged files'; - // TODO: add a job - public function handle(): int { RmQ::deleteAll(); diff --git a/src/Commands/RmqStatsCommand.php b/src/Commands/RmqStatsCommand.php new file mode 100644 index 0000000..385f0df --- /dev/null +++ b/src/Commands/RmqStatsCommand.php @@ -0,0 +1,47 @@ + */ + $rows = RmqFile::select('status', DB::raw('COUNT(*) as total')) // @phpstan-ignore-line + ->groupBy('status') + ->get() + ->map(fn (RmqFile $row) => [ + 'Status' => $this->getStatusLabel($row->status), + 'Count' => $row->total, // @phpstan-ignore-line + ]) + ->toArray(); + + $this->table(['Status', 'Count'], [ + ...$rows, + [ + 'Status' => 'total', + 'Count' => array_sum(array_column($rows, 'Count')), + ], + ]); + + return self::SUCCESS; + } + + private function getStatusLabel(int $status): string + { + return match ($status) { + RmqFile::STAGED => 'Staged', + RmqFile::DELETED => 'Deleted', + RmqFile::FAILED => 'Failed', + default => 'Unknown', + }; + } +} diff --git a/src/Models/RmqFile.php b/src/Models/RmqFile.php index 5d8b347..59e1f29 100644 --- a/src/Models/RmqFile.php +++ b/src/Models/RmqFile.php @@ -17,6 +17,8 @@ * @property ?Carbon $deleted_at * * @method static Builder|static whereStaged() + * @method static Builder|static whereDeleted() + * @method static Builder|static whereFailed() * @method static Builder|static whereInstance(?string $instance) * @method static Builder|static whereBeforeSeconds(int $beforeSeconds) */ @@ -77,6 +79,18 @@ public function scopeWhereStaged(Builder $query): void $query->where('status', static::STAGED); } + /** @param Builder $query */ + public function scopeWhereDeleted(Builder $query): void + { + $query->where('status', static::DELETED); + } + + /** @param Builder $query */ + public function scopeWhereFailed(Builder $query): void + { + $query->where('status', static::FAILED); + } + /** @param Builder $query */ public function scopeWhereInstance(Builder $query, ?string $instance): void { diff --git a/src/RmqServiceProvider.php b/src/RmqServiceProvider.php index 7c4d83b..1cf43d2 100644 --- a/src/RmqServiceProvider.php +++ b/src/RmqServiceProvider.php @@ -3,7 +3,9 @@ namespace Medilies\RmQ; use Illuminate\Support\ServiceProvider; +use Medilies\RmQ\Commands\RmqCleanupCommand; use Medilies\RmQ\Commands\RmqDeleteCommand; +use Medilies\RmQ\Commands\RmqStatsCommand; class RmqServiceProvider extends ServiceProvider { @@ -47,6 +49,8 @@ protected function registerCommands(): void $this->commands([ RmqDeleteCommand::class, + RmqCleanupCommand::class, + RmqStatsCommand::class, ]); } } diff --git a/tests/laravel/RmqCleanupCommandTest.php b/tests/laravel/RmqCleanupCommandTest.php new file mode 100644 index 0000000..cb3509f --- /dev/null +++ b/tests/laravel/RmqCleanupCommandTest.php @@ -0,0 +1,25 @@ +signature; + +test($signature, function () use ($signature) { + /** @var OrchestraTestCase $this */ + $files = populateFiles(); + + RmQ::stage($files[0]); + Rmq::delete(); + + $this->assertDatabaseHas(RmqFile::tableName(), [ + 'path' => $files[0], + 'status' => RmqFile::DELETED, + ]); + + $this->artisan($signature)->assertExitCode(0); + + $this->assertDatabaseCount(RmqFile::tableName(), 0); +}); diff --git a/tests/laravel/CommandTest.php b/tests/laravel/RmqDeleteCommandTest.php similarity index 100% rename from tests/laravel/CommandTest.php rename to tests/laravel/RmqDeleteCommandTest.php diff --git a/tests/laravel/RmqStatsCommandTest.php b/tests/laravel/RmqStatsCommandTest.php new file mode 100644 index 0000000..199df85 --- /dev/null +++ b/tests/laravel/RmqStatsCommandTest.php @@ -0,0 +1,34 @@ +signature; + +test($signature, function () use ($signature) { + /** @var OrchestraTestCase $this */ + $files = populateFiles(2); + $filesCount = count($files); + + RmQ::stage($files); + Rmq::delete(); + + $this->assertDatabaseCount(RmqFile::tableName(), $filesCount) + ->assertDatabaseHas(RmqFile::tableName(), [ + 'path' => $files[0], + 'status' => RmqFile::DELETED, + ]); + + RmQ::stage($files[1]); + + $this->assertDatabaseHas(RmqFile::tableName(), [ + 'path' => $files[1], + 'status' => RmqFile::STAGED, + ]); + + $this->artisan($signature)->assertExitCode(0); + + depopulateFiles($files); +});