diff --git a/src/ExternalEvents.php b/src/ExternalEvents.php index c472e59..3aa305f 100644 --- a/src/ExternalEvents.php +++ b/src/ExternalEvents.php @@ -13,7 +13,7 @@ class ExternalEvents { private const CAMEL_CASE_LETTERS_DETECTION = '#(?!(?<=^)|(?<=\\\))[A-Z]#'; - public static function publish(Message $class): void + public static function publish(Message $class, array $headers = []): void { $routingKey = str_replace( '\\', @@ -26,40 +26,31 @@ public static function publish(Message $class): void ) ) ); - $message = [ - 'data' => $class->serializeToJsonString(), + + $message = [ + 'data' => $class->serializeToJsonString(), + 'headers' => $headers, ]; publish($routingKey, $message); } - /** - * @throws InvalidMessageException - */ - public static function decode(string $expectedEvent, string $message): mixed - { - try { - $event = new $expectedEvent(); - $event->mergeFromJsonString($message); - - return $event; - } catch (Exception) { - throw new InvalidMessageException( - "The message is not a valid {$expectedEvent} message" - ); - } - } - public static function decorateListener(string $listenerClass): \Closure { return static function (string $event, array $message) use ($listenerClass) { try { + $listener = resolve($listenerClass); + + if (method_exists($listener, 'setHeaders')) { + $listener->setHeaders($message[0]['headers']); + } + $eventParameter = new ReflectionParameter([$listenerClass, 'handle'], 0); $className = $eventParameter->getType()->getName(); $payload = ExternalEvents::decode($className, $message[0]['data']); - return resolve($listenerClass)->handle($payload); + return $listener->handle($payload); } catch (ReflectionException $e) { throw new BadMethodCallException( "$listenerClass must have a handle method with a single parameter of type object child of \Google\Protobuf\Internal\Message" @@ -67,4 +58,19 @@ public static function decorateListener(string $listenerClass): \Closure } }; } + + /** + * @throws InvalidMessageException + */ + public static function decode(string $expectedEvent, string $message): mixed + { + try { + $event = new $expectedEvent(); + $event->mergeFromJsonString($message); + + return $event; + } catch (Exception $e) { + throw new InvalidMessageException("The message is not a valid {$expectedEvent} message", 0, $e); + } + } } diff --git a/tests/ExternalEventsTest.php b/tests/ExternalEventsTest.php index 9489544..ba00132 100644 --- a/tests/ExternalEventsTest.php +++ b/tests/ExternalEventsTest.php @@ -11,7 +11,19 @@ function publish($routingKey, $message) { assertSame('softonic.laravel_protobuf_events.fake_proto.fake_message', $routingKey); - assertSame(['data' => '{"content":":content:"}'], $message); + + if (empty($message['headers'])) { + $expectedMessage = [ + 'data' => '{"content":":content:"}', + 'headers' => [], + ]; + } else { + $expectedMessage = [ + 'data' => '{"content":":content:"}', + 'headers' => ['xRequestId' => '7b15d663-8d55-4e2f-82cc-4473576a4a17'], + ]; + } + assertSame($expectedMessage, $message); } class ExternalEventsTest extends TestCase @@ -26,6 +38,7 @@ public function whenDecodeMessageItShouldReturnTheMessageObject(): void $codedMessage = $message->serializeToJsonString(); $decodedMessage = ExternalEvents::decode(FakeMessage::class, $codedMessage); + self::assertSame(':content:', $decodedMessage->getContent()); } @@ -45,7 +58,7 @@ public function whenDecodeAnInvalidMessageItShouldThrowAnException(): void /** * @test */ - public function whenPublishMessageItShouldPublishIt(): void + public function whenPublishMessageWithoutHeadersItShouldPublishIt(): void { $message = new FakeMessage(); $message->setContent(':content:'); @@ -53,6 +66,19 @@ public function whenPublishMessageItShouldPublishIt(): void ExternalEvents::publish($message); } + /** + * @test + */ + public function whenPublishMessageWithHeadersItShouldPublishIt(): void + { + $headers = ['xRequestId' => '7b15d663-8d55-4e2f-82cc-4473576a4a17']; + + $message = new FakeMessage(); + $message->setContent(':content:'); + + ExternalEvents::publish($message, $headers); + } + /** * @test */ @@ -63,7 +89,7 @@ public function process() { } }; - $class = $invalidListener::class; + $class = $invalidListener::class; $this->expectException(BadMethodCallException::class); $this->expectErrorMessage( @@ -76,7 +102,7 @@ public function process() /** * @test */ - public function whenDecoratingAListenerItShouldExecuteIt(): void + public function whenDecoratingAListenerWithoutHeadersItShouldExecuteIt(): void { $listener = new class() { public function handle(FakeMessage $message) @@ -90,4 +116,35 @@ public function handle(FakeMessage $message) ExternalEvents::decorateListener($listener::class)(':event:', [['data' => $message->serializeToJsonString()]]); } + + /** + * @test + */ + public function whenDecoratingAListenerWithHeadersItShouldExecuteIt(): void + { + $listener = new class() { + public function setHeaders(array $headers) + { + assertSame(['xRequestId' => '7b15d663-8d55-4e2f-82cc-4473576a4a17'], $headers); + } + + public function handle(FakeMessage $message) + { + assertSame(':content:', $message->getContent()); + } + }; + + $message = new FakeMessage(); + $message->setContent(':content:'); + + ExternalEvents::decorateListener($listener::class)( + ':event:', + [ + [ + 'data' => $message->serializeToJsonString(), + 'headers' => ['xRequestId' => '7b15d663-8d55-4e2f-82cc-4473576a4a17'], + ], + ] + ); + } }