๐ Enjoying this package? Consider sponsoring me on GitHub or buying me a beer.
Events
Laravel Patches dispatches events throughout the patch lifecycle, allowing you to hook into the execution process for logging, notifications, monitoring, or custom behavior.
Available Events
PatchExecuting
Dispatched before a patch's up() method runs.
Properties:
string $patch- The patch nameint $batch- The batch numberobject $instance- The patch instance
Example:
1use Rappasoft\LaravelPatches\Events\PatchExecuting;2 3Event::listen(PatchExecuting::class, function (PatchExecuting $event) {4 Log::info("About to run patch: {$event->patch} in batch {$event->batch}");5 6 // Send notification7 Notification::send($admins, new PatchStarting($event->patch));8});
PatchExecuted
Dispatched after a patch successfully executes.
Properties:
string $patch- The patch nameint $batch- The batch number?array $log- The patch logsint $executionTime- Execution time in millisecondsfloat $memoryUsed- Memory used in MB
Example:
1use Rappasoft\LaravelPatches\Events\PatchExecuted; 2 3Event::listen(PatchExecuted::class, function (PatchExecuted $event) { 4 Log::info("Patch {$event->patch} completed in {$event->executionTime}ms"); 5 6 // Alert if patch took too long 7 if ($event->executionTime > 30000) { // 30 seconds 8 Slack::send("Slow patch detected: {$event->patch} took {$event->executionTime}ms"); 9 }10 11 // Log metrics to monitoring service12 Metrics::timing('patch.execution_time', $event->executionTime, [13 'patch' => $event->patch,14 'batch' => $event->batch,15 ]);16});
PatchFailed
Dispatched when a patch throws an exception.
Properties:
string $patch- The patch nameint $batch- The batch numberThrowable $exception- The exception that was thrownint $executionTime- Time before failure in milliseconds
Example:
1use Rappasoft\LaravelPatches\Events\PatchFailed; 2 3Event::listen(PatchFailed::class, function (PatchFailed $event) { 4 Log::error("Patch {$event->patch} failed", [ 5 'exception' => $event->exception->getMessage(), 6 'trace' => $event->exception->getTraceAsString(), 7 'batch' => $event->batch, 8 ]); 9 10 // Send urgent notification11 Notification::send($admins, new PatchFailedNotification($event));12 13 // Create rollback plan14 IssueTracker::create([15 'title' => "Patch failed: {$event->patch}",16 'description' => $event->exception->getMessage(),17 'severity' => 'critical',18 ]);19});
PatchRollingBack
Dispatched before a patch's down() method runs.
Properties:
string $patch- The patch nameobject $instance- The patch instance
Example:
1use Rappasoft\LaravelPatches\Events\PatchRollingBack; 2 3Event::listen(PatchRollingBack::class, function (PatchRollingBack $event) { 4 Log::warning("Rolling back patch: {$event->patch}"); 5 6 // Backup data if needed 7 if ($event->instance instanceof CriticalPatch) { 8 BackupService::createSnapshot(); 9 }10});
PatchRolledBack
Dispatched after a patch successfully rolls back.
Properties:
string $patch- The patch nameint $executionTime- Rollback time in milliseconds
Example:
1use Rappasoft\LaravelPatches\Events\PatchRolledBack;2 3Event::listen(PatchRolledBack::class, function (PatchRolledBack $event) {4 Log::info("Rolled back patch: {$event->patch} in {$event->executionTime}ms");5 6 Cache::tags('patches')->flush();7});
Registering Event Listeners
In EventServiceProvider
1use Rappasoft\LaravelPatches\Events\{ 2 PatchExecuting, 3 PatchExecuted, 4 PatchFailed, 5 PatchRollingBack, 6 PatchRolledBack 7}; 8 9protected $listen = [10 PatchExecuting::class => [11 LogPatchExecution::class,12 NotifyAdministrators::class,13 ],14 PatchExecuted::class => [15 RecordMetrics::class,16 ClearCache::class,17 ],18 PatchFailed::class => [19 AlertTeam::class,20 LogFailure::class,21 ],22];
Using Closures
1// In AppServiceProvider boot() method2Event::listen(PatchExecuted::class, function ($event) {3 // Handle event4});
Using Event Subscribers
1class PatchEventSubscriber 2{ 3 public function handlePatchExecuting(PatchExecuting $event): void 4 { 5 // ... 6 } 7 8 public function handlePatchExecuted(PatchExecuted $event): void 9 {10 // ...11 }12 13 public function handlePatchFailed(PatchFailed $event): void14 {15 // ...16 }17 18 public function subscribe(Dispatcher $events): array19 {20 return [21 PatchExecuting::class => 'handlePatchExecuting',22 PatchExecuted::class => 'handlePatchExecuted',23 PatchFailed::class => 'handlePatchFailed',24 ];25 }26}
Common Use Cases
1. Performance Monitoring
1Event::listen(PatchExecuted::class, function ($event) {2 Metrics::histogram('patch.duration', $event->executionTime);3 Metrics::histogram('patch.memory', $event->memoryUsed);4});
2. Slack Notifications
1Event::listen(PatchExecuted::class, function ($event) {2 Slack::send("โ
Patch completed: {$event->patch} ({$event->executionTime}ms)");3});4 5Event::listen(PatchFailed::class, function ($event) {6 Slack::send("โ Patch failed: {$event->patch}\n{$event->exception->getMessage()}");7});
3. Audit Logging
1Event::listen([PatchExecuted::class, PatchFailed::class], function ($event) { 2 AuditLog::create([ 3 'action' => 'patch_executed', 4 'patch' => $event->patch, 5 'batch' => $event->batch, 6 'status' => $event instanceof PatchFailed ? 'failed' : 'success', 7 'user' => auth()->user()?->email, 8 'timestamp' => now(), 9 ]);10});
4. Cache Invalidation
1Event::listen(PatchExecuted::class, function ($event) {2 // Clear specific cache after certain patches3 if (str_contains($event->patch, 'cache')) {4 Cache::flush();5 }6});
5. Database Backups
1Event::listen(PatchExecuting::class, function ($event) {2 // Backup before critical patches3 if ($event->instance->isCritical()) {4 Artisan::call('snapshot:create');5 }6});
Event Data Access
All events are serializable and can be queued:
1Event::listen(PatchExecuted::class, function ($event) {2 ProcessPatchMetrics::dispatch($event)->onQueue('metrics');3});
Disabling Events
If you need to run patches without triggering events:
1Event::fake([2 PatchExecuting::class,3 PatchExecuted::class,4]);5 6Artisan::call('patch');
Or in tests:
1Event::fake();2// Run patches3Event::assertDispatched(PatchExecuted::class);