diff --git a/src/Queue/src/Interceptor/Consume/RetryPolicyInterceptor.php b/src/Queue/src/Interceptor/Consume/RetryPolicyInterceptor.php index bdecd6010..287dc2641 100644 --- a/src/Queue/src/Interceptor/Consume/RetryPolicyInterceptor.php +++ b/src/Queue/src/Interceptor/Consume/RetryPolicyInterceptor.php @@ -26,13 +26,12 @@ public function process(string $controller, string $action, array $parameters, C try { return $core->callAction($controller, $action, $parameters); } catch (\Throwable $e) { - $attribute = $this->reader->firstClassMetadata(new \ReflectionClass($controller), Attribute::class); - if ($attribute === null) { + $policy = $this->getRetryPolicy($e, new \ReflectionClass($controller)); + + if ($policy === null) { throw $e; } - $policy = $this->getRetryPolicy($e, $attribute); - $headers = $parameters['headers'] ?? []; $attempts = (int)($headers['attempts'][0] ?? 0); @@ -49,14 +48,16 @@ public function process(string $controller, string $action, array $parameters, C } } - private function getRetryPolicy(\Throwable $exception, Attribute $attribute): RetryPolicy + private function getRetryPolicy(\Throwable $exception, \ReflectionClass $handler): ?RetryPolicy { + $attribute = $this->reader->firstClassMetadata($handler, Attribute::class); + if ($exception instanceof JobException && $exception->getPrevious() !== null) { $exception = $exception->getPrevious(); } $policy = $exception instanceof RetryableExceptionInterface ? $exception->getRetryPolicy() : null; - return $policy ?? $attribute->getRetryPolicy(); + return $policy ?? $attribute?->getRetryPolicy() ?? null; } } diff --git a/src/Queue/tests/Interceptor/Consume/RetryPolicyInterceptorTest.php b/src/Queue/tests/Interceptor/Consume/RetryPolicyInterceptorTest.php index 1d4a7c934..86213f9b5 100644 --- a/src/Queue/tests/Interceptor/Consume/RetryPolicyInterceptorTest.php +++ b/src/Queue/tests/Interceptor/Consume/RetryPolicyInterceptorTest.php @@ -87,6 +87,26 @@ public function testWithDefaultRetryPolicy(): void } } + public function testWithoutRetryPolicyAttribute(): void + { + $this->reader->expects($this->once())->method('firstClassMetadata')->willReturn(null); + + $this->core + ->expects($this->once()) + ->method('callAction') + ->with(self::class, 'bar', []) + ->willThrowException(new TestRetryException( + retryPolicy: new \Spiral\Queue\RetryPolicy(maxAttempts: 2, delay: 4) + )); + + try { + $this->interceptor->process(self::class, 'bar', [], $this->core); + } catch (RetryException $e) { + $this->assertSame(4, $e->getOptions()->getDelay()); + $this->assertSame(['attempts' => ['1']], $e->getOptions()->getHeaders()); + } + } + public function testWithRetryPolicyInAttribute(): void { $this->reader->expects($this->once())->method('firstClassMetadata')->willReturn(