diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 578bb29..6874790 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -57,7 +57,7 @@ jobs: run: vendor/bin/ecs check - name: Run static analysis via PHPStan - run: vendor/bin/phpstan --xdebug analyse src tests + run: vendor/bin/phpstan analyse src tests - name: Create databases run: | diff --git a/.gitignore b/.gitignore index 50e6f7f..271eb9a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ composer.lock vendor coverage .env +.phpunit.cache .phpunit.result.cache .php_cs.cache .php-cs-fixer.cache diff --git a/src/Traits/Timers.php b/src/Traits/Timers.php index 88fa010..2b2a324 100644 --- a/src/Traits/Timers.php +++ b/src/Traits/Timers.php @@ -5,7 +5,6 @@ namespace Workflow\Traits; use Carbon\CarbonInterval; -use Illuminate\Database\QueryException; use React\Promise\Deferred; use React\Promise\PromiseInterface; use function React\Promise\resolve; @@ -64,7 +63,7 @@ public static function timer($seconds): PromiseInterface 'class' => Signal::class, 'result' => Serializer::serialize(true), ]); - } catch (QueryException $exception) { + } catch (\Illuminate\Database\UniqueConstraintViolationException $exception) { // already logged } } diff --git a/src/WorkflowStub.php b/src/WorkflowStub.php index 54e7b09..9e61c5e 100644 --- a/src/WorkflowStub.php +++ b/src/WorkflowStub.php @@ -4,7 +4,6 @@ namespace Workflow; -use Illuminate\Database\QueryException; use Illuminate\Support\Arr; use Illuminate\Support\Carbon; use Illuminate\Support\Traits\Macroable; @@ -220,15 +219,11 @@ public function startAsChild(StoredWorkflow $parentWorkflow, int $index, $now, . public function fail($exception): void { - try { - $this->storedWorkflow->exceptions() - ->create([ - 'class' => $this->storedWorkflow->class, - 'exception' => Serializer::serialize($exception), - ]); - } catch (QueryException) { - // already logged - } + $this->storedWorkflow->exceptions() + ->create([ + 'class' => $this->storedWorkflow->class, + 'exception' => Serializer::serialize($exception), + ]); $this->storedWorkflow->status->transitionTo(WorkflowFailedStatus::class); @@ -267,7 +262,7 @@ public function next($index, $now, $class, $result): void 'class' => $class, 'result' => Serializer::serialize($result), ]); - } catch (QueryException) { + } catch (\Illuminate\Database\UniqueConstraintViolationException $exception) { // already logged } diff --git a/tests/TestCase.php b/tests/TestCase.php index 901d0e9..804f923 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -25,11 +25,7 @@ public static function setUpBeforeClass(): void } for ($i = 0; $i < self::NUMBER_OF_WORKERS; $i++) { - self::$workers[$i] = new Process([ - 'php', - __DIR__ . '/../vendor/orchestra/testbench-core/laravel/artisan', - 'queue:work', - ]); + self::$workers[$i] = new Process(['php', __DIR__ . '/../vendor/bin/testbench', 'queue:work']); self::$workers[$i]->start(); } } diff --git a/tests/Unit/Listeners/MonitorActivityCompletedTest.php b/tests/Unit/Listeners/MonitorActivityCompletedTest.php index ee2a4b6..0e09da2 100644 --- a/tests/Unit/Listeners/MonitorActivityCompletedTest.php +++ b/tests/Unit/Listeners/MonitorActivityCompletedTest.php @@ -15,6 +15,10 @@ final class MonitorActivityCompletedTest extends TestCase { public function testHandle(): void { + $this->app->make('cache') + ->store() + ->clear(); + config([ 'workflows.monitor_url' => 'http://test', ]); diff --git a/tests/Unit/Listeners/MonitorActivityFailedTest.php b/tests/Unit/Listeners/MonitorActivityFailedTest.php index 78b1dd9..994ad6d 100644 --- a/tests/Unit/Listeners/MonitorActivityFailedTest.php +++ b/tests/Unit/Listeners/MonitorActivityFailedTest.php @@ -15,6 +15,10 @@ final class MonitorActivityFailedTest extends TestCase { public function testHandle(): void { + $this->app->make('cache') + ->store() + ->clear(); + config([ 'workflows.monitor_url' => 'http://test', ]); diff --git a/tests/Unit/Listeners/MonitorActivityStartedTest.php b/tests/Unit/Listeners/MonitorActivityStartedTest.php index f11213f..6c44307 100644 --- a/tests/Unit/Listeners/MonitorActivityStartedTest.php +++ b/tests/Unit/Listeners/MonitorActivityStartedTest.php @@ -15,6 +15,10 @@ final class MonitorActivityStartedTest extends TestCase { public function testHandle(): void { + $this->app->make('cache') + ->store() + ->clear(); + config([ 'workflows.monitor_url' => 'http://test', ]); diff --git a/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php b/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php index c17baee..3e1159d 100644 --- a/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php +++ b/tests/Unit/Listeners/MonitorWorkflowCompletedTest.php @@ -14,6 +14,10 @@ final class MonitorWorkflowCompletedTest extends TestCase { public function testHandle(): void { + $this->app->make('cache') + ->store() + ->clear(); + config([ 'workflows.monitor_url' => 'http://test', ]); diff --git a/tests/Unit/Listeners/MonitorWorkflowFailedTest.php b/tests/Unit/Listeners/MonitorWorkflowFailedTest.php index ff07608..ffd5e5a 100644 --- a/tests/Unit/Listeners/MonitorWorkflowFailedTest.php +++ b/tests/Unit/Listeners/MonitorWorkflowFailedTest.php @@ -14,6 +14,10 @@ final class MonitorWorkflowFailedTest extends TestCase { public function testHandle(): void { + $this->app->make('cache') + ->store() + ->clear(); + config([ 'workflows.monitor_url' => 'http://test', ]); diff --git a/tests/Unit/Listeners/MonitorWorkflowStartedTest.php b/tests/Unit/Listeners/MonitorWorkflowStartedTest.php index f57f1e3..6c2a24e 100644 --- a/tests/Unit/Listeners/MonitorWorkflowStartedTest.php +++ b/tests/Unit/Listeners/MonitorWorkflowStartedTest.php @@ -14,6 +14,10 @@ final class MonitorWorkflowStartedTest extends TestCase { public function testHandle(): void { + $this->app->make('cache') + ->store() + ->clear(); + config([ 'workflows.monitor_url' => 'http://test', ]); diff --git a/tests/Unit/Middleware/WithoutOverlappingMiddlewareTest.php b/tests/Unit/Middleware/WithoutOverlappingMiddlewareTest.php index 10b1754..c0502a2 100644 --- a/tests/Unit/Middleware/WithoutOverlappingMiddlewareTest.php +++ b/tests/Unit/Middleware/WithoutOverlappingMiddlewareTest.php @@ -15,6 +15,10 @@ final class WithoutOverlappingMiddlewareTest extends TestCase { public function testMiddleware(): void { + $this->app->make('cache') + ->store() + ->clear(); + $middleware = new WithoutOverlappingMiddleware(1, WithoutOverlappingMiddleware::WORKFLOW); $this->assertSame($middleware->getLockKey(), 'laravel-workflow-overlap:1'); $this->assertSame($middleware->getWorkflowSemaphoreKey(), 'laravel-workflow-overlap:1:workflow'); @@ -28,6 +32,10 @@ public function testMiddleware(): void public function testAllowsOnlyOneWorkflowInstance(): void { + $this->app->make('cache') + ->store() + ->clear(); + $workflow1 = $this->mock(TestWorkflow::class); $middleware1 = new WithoutOverlappingMiddleware(1, WithoutOverlappingMiddleware::WORKFLOW); @@ -65,6 +73,10 @@ public function testAllowsOnlyOneWorkflowInstance(): void public function testAllowsMultipleActivityInstances(): void { + $this->app->make('cache') + ->store() + ->clear(); + $activity1 = $this->mock(TestActivity::class); $middleware1 = new WithoutOverlappingMiddleware(1, WithoutOverlappingMiddleware::ACTIVITY); diff --git a/tests/Unit/Traits/TimersTest.php b/tests/Unit/Traits/TimersTest.php index cc03893..cb92d77 100644 --- a/tests/Unit/Traits/TimersTest.php +++ b/tests/Unit/Traits/TimersTest.php @@ -4,6 +4,10 @@ namespace Tests\Unit\Traits; +use Exception; +use Illuminate\Database\Eloquent\Relations\HasMany; +use Illuminate\Database\UniqueConstraintViolationException; +use Mockery; use Tests\Fixtures\TestWorkflow; use Tests\TestCase; use Workflow\Models\StoredWorkflow; @@ -138,4 +142,56 @@ public function testLoadsStoredResult(): void ]); $this->assertSame(true, Serializer::unserialize($workflow->logs()->firstWhere('index', 0)->result)); } + + public function testHandlesDuplicateLogInsertionProperly(): void + { + $workflow = WorkflowStub::load(WorkflowStub::make(TestWorkflow::class)->id()); + $storedWorkflow = StoredWorkflow::findOrFail($workflow->id()); + $storedWorkflow->timers() + ->create([ + 'index' => 0, + 'stop_at' => now(), + ]); + $storedWorkflow->logs() + ->create([ + 'index' => 0, + 'now' => now(), + 'class' => Signal::class, + 'result' => Serializer::serialize(true), + ]); + + $mockLogs = Mockery::mock(HasMany::class) + ->shouldReceive('whereIndex') + ->once() + ->andReturnSelf() + ->shouldReceive('first') + ->once() + ->andReturn(null) + ->shouldReceive('create') + ->andThrow(new UniqueConstraintViolationException('', '', [], new Exception())) + ->getMock(); + + $mockStoredWorkflow = Mockery::spy($storedWorkflow); + + $mockStoredWorkflow->shouldReceive('logs') + ->andReturnUsing(static function () use ($mockLogs) { + return $mockLogs; + }); + + WorkflowStub::setContext([ + 'storedWorkflow' => $mockStoredWorkflow, + 'index' => 0, + 'now' => now(), + 'replaying' => false, + ]); + + WorkflowStub::timer('1 minute') + ->then(static function ($value) use (&$result) { + $result = $value; + }); + + Mockery::close(); + + $this->assertSame(true, $result); + } } diff --git a/tests/Unit/WorkflowStubTest.php b/tests/Unit/WorkflowStubTest.php index 0d03098..20bd90a 100644 --- a/tests/Unit/WorkflowStubTest.php +++ b/tests/Unit/WorkflowStubTest.php @@ -6,6 +6,7 @@ use Exception; use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Queue; use Tests\Fixtures\TestAwaitWorkflow; use Tests\Fixtures\TestBadConnectionWorkflow; use Tests\Fixtures\TestWorkflow; @@ -14,6 +15,7 @@ use Workflow\Serializers\Serializer; use Workflow\Signal; use Workflow\States\WorkflowCompletedStatus; +use Workflow\States\WorkflowCreatedStatus; use Workflow\States\WorkflowPendingStatus; use Workflow\WorkflowStub; @@ -207,4 +209,38 @@ public function testConnection(): void $this->assertSame('redis', WorkflowStub::connection()); $this->assertSame('default', WorkflowStub::queue()); } + + public function testHandlesDuplicateLogInsertionProperly(): void + { + Queue::fake(); + + $workflow = WorkflowStub::load(WorkflowStub::make(TestWorkflow::class)->id()); + $storedWorkflow = StoredWorkflow::findOrFail($workflow->id()); + $storedWorkflow->update([ + 'arguments' => Serializer::serialize([]), + 'status' => WorkflowCreatedStatus::$name, + ]); + + $storedWorkflow->timers() + ->create([ + 'index' => 0, + 'stop_at' => now(), + ]); + $storedWorkflow->logs() + ->create([ + 'index' => 0, + 'now' => now(), + 'class' => Signal::class, + 'result' => Serializer::serialize(true), + ]); + + $workflow = $storedWorkflow->toWorkflow(); + + $workflow->next(0, now(), Signal::class, true); + + $this->assertSame(WorkflowPendingStatus::class, $workflow->status()); + $this->assertSame(1, $workflow->logs()->count()); + + Queue::assertPushed(TestWorkflow::class, 1); + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy