diff --git a/src/Illuminate/Queue/Attributes/DeleteWhenMissingModels.php b/src/Illuminate/Queue/Attributes/DeleteWhenMissingModels.php new file mode 100644 index 000000000000..d4c10261a512 --- /dev/null +++ b/src/Illuminate/Queue/Attributes/DeleteWhenMissingModels.php @@ -0,0 +1,11 @@ +resolveName(); try { - $shouldDelete = (new ReflectionClass($class)) - ->getDefaultProperties()['deleteWhenMissingModels'] ?? false; + $reflectionClass = new ReflectionClass($class); + + $shouldDelete = $reflectionClass->getDefaultProperties()['deleteWhenMissingModels'] + ?? count($reflectionClass->getAttributes(DeleteWhenMissingModels::class)) !== 0; } catch (Exception) { $shouldDelete = false; } diff --git a/tests/Integration/Queue/CallQueuedHandlerTest.php b/tests/Integration/Queue/CallQueuedHandlerTest.php index bd4a179322ac..8afa8fe9e025 100644 --- a/tests/Integration/Queue/CallQueuedHandlerTest.php +++ b/tests/Integration/Queue/CallQueuedHandlerTest.php @@ -6,6 +6,7 @@ use Illuminate\Bus\Queueable; use Illuminate\Contracts\Queue\Job; use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Queue\Attributes\DeleteWhenMissingModels; use Illuminate\Queue\CallQueuedHandler; use Illuminate\Queue\Events\JobFailed; use Illuminate\Queue\InteractsWithQueue; @@ -117,6 +118,27 @@ public function testJobIsDeletedIfHasDeleteProperty() Event::assertNotDispatched(JobFailed::class); } + + public function testJobIsDeletedIfHasDeleteAttribute() + { + Event::fake(); + + $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); + + $job = m::mock(Job::class); + $job->shouldReceive('getConnectionName')->andReturn('connection'); + $job->shouldReceive('resolveName')->andReturn(CallQueuedHandlerAttributeExceptionThrower::class); + $job->shouldReceive('markAsFailed')->never(); + $job->shouldReceive('isDeleted')->andReturn(false); + $job->shouldReceive('delete')->once(); + $job->shouldReceive('failed')->never(); + + $instance->call($job, [ + 'command' => serialize(new CallQueuedHandlerAttributeExceptionThrower()), + ]); + + Event::assertNotDispatched(JobFailed::class); + } } class CallQueuedHandlerTestJob @@ -179,6 +201,20 @@ public function __wakeup() } } +#[DeleteWhenMissingModels] +class CallQueuedHandlerAttributeExceptionThrower +{ + public function handle() + { + // + } + + public function __wakeup() + { + throw new ModelNotFoundException('Foo'); + } +} + class TestJobMiddleware { public function handle($command, $next)