From b7c628776754a7d861dd48ff18768e1c1f2d5f5f Mon Sep 17 00:00:00 2001 From: Kennedy Tedesco Date: Fri, 6 Sep 2024 17:53:25 -0300 Subject: [PATCH] [11.x] Add `Skip` middleware for Queue Jobs (#52645) * [11.x] Add `Skip` middleware for Queue Jobs * CS Fixes * formatting --------- Co-authored-by: Taylor Otwell --- src/Illuminate/Queue/Middleware/Skip.php | 44 ++++++ .../Integration/Queue/SkipMiddlewareTest.php | 132 ++++++++++++++++++ 2 files changed, 176 insertions(+) create mode 100644 src/Illuminate/Queue/Middleware/Skip.php create mode 100644 tests/Integration/Queue/SkipMiddlewareTest.php diff --git a/src/Illuminate/Queue/Middleware/Skip.php b/src/Illuminate/Queue/Middleware/Skip.php new file mode 100644 index 000000000000..37fc91d5949f --- /dev/null +++ b/src/Illuminate/Queue/Middleware/Skip.php @@ -0,0 +1,44 @@ +skip) { + return false; + } + + return $next($job); + } +} diff --git a/tests/Integration/Queue/SkipMiddlewareTest.php b/tests/Integration/Queue/SkipMiddlewareTest.php new file mode 100644 index 000000000000..14bd1809b194 --- /dev/null +++ b/tests/Integration/Queue/SkipMiddlewareTest.php @@ -0,0 +1,132 @@ +assertJobWasSkipped($job); + } + + public function testJobIsSkippedWhenConditionIsTrueUsingClosure() + { + $job = new SkipTestJob(skip: new SerializableClosure(fn () => true)); + + $this->assertJobWasSkipped($job); + } + + public function testJobIsNotSkippedWhenConditionIsFalse() + { + $job = new SkipTestJob(skip: false); + + $this->assertJobRanSuccessfully($job); + } + + public function testJobIsNotSkippedWhenConditionIsFalseUsingClosure() + { + $job = new SkipTestJob(skip: new SerializableClosure(fn () => false)); + + $this->assertJobRanSuccessfully($job); + } + + public function testJobIsNotSkippedWhenConditionIsTrueWithUnless() + { + $job = new SkipTestJob(skip: true, useUnless: true); + + $this->assertJobRanSuccessfully($job); + } + + public function testJobIsNotSkippedWhenConditionIsTrueWithUnlessUsingClosure() + { + $job = new SkipTestJob(skip: new SerializableClosure(fn () => true), useUnless: true); + + $this->assertJobRanSuccessfully($job); + } + + public function testJobIsSkippedWhenConditionIsFalseWithUnless() + { + $job = new SkipTestJob(skip: false, useUnless: true); + + $this->assertJobWasSkipped($job); + } + + public function testJobIsSkippedWhenConditionIsFalseWithUnlessUsingClosure() + { + $job = new SkipTestJob(skip: new SerializableClosure(fn () => false), useUnless: true); + + $this->assertJobWasSkipped($job); + } + + protected function assertJobRanSuccessfully(SkipTestJob $class) + { + $this->assertJobHandled(class: $class, expectedHandledValue: true); + } + + protected function assertJobWasSkipped(SkipTestJob $class) + { + $this->assertJobHandled(class: $class, expectedHandledValue: false); + } + + protected function assertJobHandled(SkipTestJob $class, bool $expectedHandledValue) + { + $class::$handled = false; + $instance = new CallQueuedHandler(new Dispatcher($this->app), $this->app); + + $job = m::mock(Job::class); + + $job->shouldReceive('hasFailed')->andReturn(false); + $job->shouldReceive('isReleased')->andReturn(false); + $job->shouldReceive('isDeletedOrReleased')->andReturn(false); + $job->shouldReceive('delete')->once(); + + $instance->call($job, [ + 'command' => serialize($class), + ]); + + $this->assertEquals($expectedHandledValue, $class::$handled); + } +} + +class SkipTestJob +{ + use InteractsWithQueue, Queueable; + + public static $handled = false; + + public function __construct( + protected bool|SerializableClosure $skip, + protected bool $useUnless = false, + ) { + } + + public function handle(): void + { + static::$handled = true; + } + + public function middleware(): array + { + $skip = $this->skip instanceof SerializableClosure + ? $this->skip->getClosure() + : $this->skip; + + if ($this->useUnless) { + return [Skip::unless($skip)]; + } + + return [Skip::when($skip)]; + } +}