diff --git a/src/ActivityStub.php b/src/ActivityStub.php index 2ebf41e..ed8f2ca 100644 --- a/src/ActivityStub.php +++ b/src/ActivityStub.php @@ -9,6 +9,7 @@ use React\Promise\Deferred; use React\Promise\PromiseInterface; use function React\Promise\resolve; +use RuntimeException; use Throwable; use Workflow\Serializers\Serializer; @@ -58,7 +59,17 @@ public static function make($activity, ...$arguments): PromiseInterface array_key_exists('class', $result) && is_subclass_of($result['class'], Throwable::class) ) { - throw new $result['class']($result['message'], (int) $result['code']); + try { + $throwable = new $result['class']($result['message'] ?? '', (int) ($result['code'] ?? 0)); + } catch (Throwable $throwable) { + throw new RuntimeException( + sprintf('[%s] %s', $result['class'], (string) ($result['message'] ?? '')), + (int) ($result['code'] ?? 0), + $throwable + ); + } + + throw $throwable; } return resolve($result); } diff --git a/tests/Unit/ActivityStubTest.php b/tests/Unit/ActivityStubTest.php index fff31e8..af6cee9 100644 --- a/tests/Unit/ActivityStubTest.php +++ b/tests/Unit/ActivityStubTest.php @@ -5,6 +5,7 @@ namespace Tests\Unit; use Exception; +use RuntimeException; use Tests\Fixtures\TestActivity; use Tests\Fixtures\TestWorkflow; use Tests\TestCase; @@ -92,6 +93,36 @@ public function testLoadsStoredException(): void $this->assertSame('test', $result['message']); } + public function testLoadsStoredExceptionWithNonStandardConstructor(): void + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage( + '[' . ActivityStubNonStandardConstructorException::class . '] test from context (1)' + ); + $this->expectExceptionCode(123); + + $workflow = WorkflowStub::load(WorkflowStub::make(TestWorkflow::class)->id()); + $storedWorkflow = StoredWorkflow::findOrFail($workflow->id()); + $storedWorkflow->update([ + 'arguments' => Serializer::serialize([]), + 'status' => WorkflowPendingStatus::$name, + ]); + $storedWorkflow->logs() + ->create([ + 'index' => 0, + 'now' => WorkflowStub::now(), + 'class' => TestActivity::class, + 'result' => Serializer::serialize( + new ActivityStubNonStandardConstructorException('context', 'test', ['binding'], 123) + ), + ]); + + ActivityStub::make(TestActivity::class) + ->then(static function ($value) use (&$result) { + $result = $value; + }); + } + public function testAll(): void { $workflow = WorkflowStub::load(WorkflowStub::make(TestWorkflow::class)->id()); @@ -142,3 +173,11 @@ public function testAsync(): void $this->assertSame('test', $result); } } + +final class ActivityStubNonStandardConstructorException extends Exception +{ + public function __construct(string $connection, string $message, array $bindings, int $code) + { + parent::__construct($message . ' from ' . $connection . ' (' . count($bindings) . ')', $code); + } +}