bnzo/livewire-tmp-cleanup
Schedules automatic cleanup of Livewire temporary uploads on S3-compatible disks. Adds the livewire-tmp:clean Artisan command to delete files older than a configurable age, with optional dry-run. Auto-scheduled daily, safe for multi-server deployments.
Installation:
composer require bnzo/livewire-tmp-cleanup
Publish the config (optional):
php artisan vendor:publish --provider="Bnzo\LivewireTmpCleanup\LivewireTmpCleanupServiceProvider"
First Use Case: Run the cleanup manually to test:
php artisan livewire-tmp:clean --dry-run
Verify output shows files that would be deleted (no actual deletions occur in dry-run mode).
Where to Look First:
config/livewire-tmp-cleanup.php (default: temporary_file_upload disk, 72-hour cleanup).app/Console/Kernel.php (auto-registered LivewireTmpCleanupCommand).php artisan livewire-tmp:clean --help.Configuration:
Override defaults in config/livewire-tmp-cleanup.php:
'disk' => 's3', // Custom disk name
'directory' => 'livewire-tmp', // Custom path prefix
'hours' => 24, // Cleanup threshold
'dry_run' => env('APP_ENV') === 'production' ? false : true, // Force dry-run in staging
Scheduling:
The package auto-registers a daily cleanup at 03:00 (adjust via schedule() in Kernel.php):
$schedule->command('livewire-tmp:clean')->dailyAt('03:00')->onOneServer()->withoutOverlapping();
Integration with Livewire: Ensure your Livewire components use the same disk for temporary uploads:
use Livewire\WithFileUploads;
class MyComponent extends Component {
use WithFileUploads;
public function store() {
$this->validate([
'file' => 'required|file',
]);
$this->storeFile('file'); // Uses `temporary_file_upload` disk by default
}
}
Custom Disks:
For non-default disks (e.g., r2), configure in config/filesystems.php and update the package config:
'disks' => [
'r2' => [
'driver' => 's3',
'key' => env('R2_KEY'),
'secret' => env('R2_SECRET'),
'endpoint' => env('R2_ENDPOINT'),
'bucket' => env('R2_BUCKET'),
'region' => 'auto',
],
],
Monitoring: Log cleanup results by extending the command (see Gotchas for logging hooks).
Dry-Run Misuse:
--dry-run) shows what would be deleted but doesn’t log actual files. For debugging, add logging to the command:
// app/Console/Commands/LivewireTmpCleanupCommand.php
protected function logCleanup(array $deletedFiles) {
if ($deletedFiles) {
Log::info('Deleted ' . count($deletedFiles) . ' files', [
'files' => $deletedFiles,
'command' => 'livewire-tmp:clean',
]);
}
}
Overlapping Runs:
onOneServer() + withoutOverlapping() guards prevent race conditions in multi-server setups. Disable only if you’re certain the cleanup is safe to run concurrently.S3 Lifecycle Rules:
Directory Mismatch:
temporary_file_upload directory is livewire-tmp. If you change this in config/filesystems.php, update the package config to match:
'directory' => 'custom-livewire-tmp', // Must match your disk config
Large Buckets:
--limit=1000 to simulate batch processing:
php artisan livewire-tmp:clean --limit=1000
Verify Disk Connection: Test your S3 disk manually:
php artisan storage:link --force
php artisan tinker
>>> \Storage::disk('s3')->files('livewire-tmp');
Check File Ages:
Use aws s3api list-objects (AWS) or R2 CLI to confirm file timestamps match your hours threshold.
Permissions:
Ensure your IAM/R2 user has s3:DeleteObject permissions for the target bucket.
Custom Cleanup Logic: Extend the command to add filters (e.g., skip files with specific prefixes):
// app/Console/Commands/LivewireTmpCleanupCommand.php
protected function shouldDelete(File $file) {
return $file->lastModified() < now()->subHours($this->hours)
&& ! Str::startsWith($file->path(), 'livewire-tmp/protected/');
}
Event-Based Cleanup: Trigger cleanup after specific actions (e.g., user logout) via a listener:
// app/Providers/EventServiceProvider.php
public function boot() {
UserLoggedOut::listen(function () {
Artisan::call('livewire-tmp:clean', ['--force' => true]);
});
}
Slack/Email Notifications: Add alerts for cleanup failures:
// In the command's handle() method
try {
$this->clean();
} catch (\Exception $e) {
Notification::route('slack', config('services.slack.webhook'))
->notify(new CleanupFailed($e));
}
How can I help you explore Laravel packages today?