SlideShare a Scribd company logo
1 of 54
Download to read offline
Symfony Messenger
Bus, Queues, workers and more !
Samuel Rozé
VP Engineering @ Birdie
Symfony
Con(nuousPipe
Tolerance
What's Symfony Messenger about?
1. Messages. Any serialisable PHP object.
2. Message bus. Where you dispatch your messages.
3. Message handlers. Will execute your business logic when the
message arrives to them.
4. Transports. Allow to send and receive messages through 3rd
party systems.
5. Worker. To consume messages from transports.
$ composer req symfony/messenger
or composer req messenger
A message
No specific requirement.
namespace AppMessage;
class SendNotification
{
// ...properties
public function __construct(string $message, array $users)
{
$this->message = $message;
$this->users = $users;
}
// ...getters
}
As a component
use SymfonyComponentMessengerMessageBus;
use SymfonyComponentMessengerHandlerLocator;
use SymfonyComponentMessengerMiddlewareHandleMessageMiddleware;
$handler = function(SendNotification $message) {
// ...
};
$messageBus = new MessageBus([
new HandleMessageMiddleware(new HandlerLocator([
SendNotification::class => $handler,
])),
]);
In your Symfony applica0on
Nothing to do...
Dispatching a message
namespace AppController;
use AppMessageSendNotification;
// ...
use SymfonyComponentMessengerMessageBusInterface;
class DefaultController
{
public function index(MessageBusInterface $bus, Request $request)
{
$users = ['samuel', 'christelle'];
$bus->dispatch(new SendNotification(
$request->query->get('message', 'Hello London.'),
$users
));
return new Response('<html><body>OK.</body></html>');
}
}
Dispatching a message
namespace AppController;
use AppMessageSendNotification;
// ...
use SymfonyComponentMessengerMessageBusInterface;
class DefaultController
{
public function index(MessageBusInterface $bus, Request $request)
{
$users = ['samuel', 'christelle'];
$bus->dispatch(new SendNotification(
$request->query->get('message', 'Hello London.'),
$users
));
return new Response('<html><body>OK.</body></html>');
}
}
A message handler
namespace AppMessageHandler;
use AppMessageSendNotification;
class SendNotificationHandler
{
public function __invoke(SendNotification $message)
{
foreach ($message->getUsers() as $user) {
echo "Send notification to... ".$user."n";
}
}
}
Register your handler
# config/services.yaml
services:
AppMessageHandlerSendNotificationHandler:
tags: ['messenger.message_handler']
Register your handlers (op3on 2)
# config/services.yaml
services:
AppMessageHandler:
resource: '../src/MessageHandler/*'
tags: ['messenger.message_handler']
Register your handlers (op3on 3)
namespace AppMessageHandler;
use AppMessageSendNotification;
use SymfonyComponentMessengerHandlerMessageHandlerInterface;
class SendNotificationHandler implements MessageHandlerInterface
{
public function __invoke(SendNotification $message)
{
foreach ($message->getUsers() as $user) {
echo "Send notification to... ".$user."n";
}
}
}
Yay, dispatched !
Handler is called. Done.
Now, imagine your handler takes
ages to run.
What's a transport?
1. Has a sender & receiver
Guess what. They send and receive messages.
2. Is configurable via a DSN
So we have a unique and common way of configuring them.
3. Use a Messenger Serializer
By defaut, uses Symfony Serializer. Replace as you wish.
Transports
1. Built-in AMQP.
You don't need anything more than the component and the PHP
extension.
2. More with Enqueue. (10+ other transports)
h>ps://github.com/php-enqueue/messenger-adapter
3. Fully extensible.
Create your own very easily by registering your implementaIon
of the TransportFactory interface.
Configure your transport(s)
# config/packages/messenger.yaml
framework:
messenger:
transports:
default: '%env(MESSENGER_DSN)%'
# .env
MESSENGER_DSN=amqp://guest:guest@localhost:5672/%2f/messages
Route your message(s)
framework:
messenger:
routing:
'AppMessageSendNotification': default
$ bin/console messenger:consume-messages
Mul$ple buses?
framework:
messenger:
default_bus: command_bus
buses:
command_bus: ~
event_bus: ~
Auto-wiring trick
# config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
bind:
$eventBus: '@event_bus'
Auto-wiring trick
use SymfonyComponentMessengerMessageBusInterface;
class MyController
{
public function __construct(
MessageBusInterface $commandBus,
MessageBusInterface $eventBus
) {
// ...
}
// ...
}
Register your handlers (op3on 4)
namespace AppMessageHandler;
use AppMessageSendNotification;
use SymfonyComponentMessengerHandlerMessageSubscriberInterface;
class SendNotificationHandler implements MessageSubscriberInterface
{
public static function getHandledMessages(): iterable
{
yield SendNotification::class => [
'method' => 'doSomething',
'bus' => 'command_bus'
];
}
public function doSomething(SendNotification $message)
{
// ...
}
}
Register your handlers (yield !!)
namespace AppMessageHandler;
use SymfonyComponentMessengerHandlerMessageSubscriberInterface;
class SendNotificationHandler implements MessageSubscriberInterface
{
public static function getHandledMessages(): iterable
{
yield MyMessage::class => ['bus' => 'first_bus'];
yield MyMessage::class => ['bus' => 'second_bus'];
}
public function __invoke(MyMessage $message)
{
// ...
}
}
Middleware(s)
Middleware
namespace AppMiddleware;
use SymfonyComponentMessengerMiddlewareMiddlewareInterface;
class AuditMiddleware implements MiddlewareInterface
{
public function handle($message, callable $next)
{
try {
echo sprintf('Started with message "%s"'."n", get_class($message));
return $next($message);
} finally {
echo sprintf('Ended with message "%s"'."n", get_class($message));
}
}
}
Add your middleware
framework:
messenger:
buses:
command_bus:
middleware:
- 'AppMiddlewareAuditMiddleware'
event_bus: ~
Envelopes
For non-domain logic...
Envelopes
namespace AppMiddleware;
use SymfonyComponentMessengerMiddlewareMiddlewareInterface;
use SymfonyComponentMessengerEnvelopeAwareInterface;
use SymfonyComponentMessengerAsynchronousTransportReceivedMessage;
class AuditMiddleware implements MiddlewareInterface,
EnvelopeAwareInterface
{
public function handle($envelope, callable $next)
{
try {
if (null !== $envelope->get(ReceivedMessage::class)) {
echo sprintf('Consumed message "%s"'."n", get_class($message));
} else {
echo sprintf('Dispatched message "%s"'."n", get_class($message));
}
return $next($envelope);
} finally {
echo sprintf('Ended with message "%s"'."n", get_class($message));
}
}
}
Envelopes
namespace AppMiddleware;
use SymfonyComponentMessengerMiddlewareMiddlewareInterface;
use SymfonyComponentMessengerEnvelopeAwareInterface;
use SymfonyComponentMessengerAsynchronousTransportReceivedMessage;
class AuditMiddleware implements MiddlewareInterface,
EnvelopeAwareInterface
{
public function handle($envelope, callable $next)
{
try {
if (null !== $envelope->get(ReceivedMessage::class)) {
echo sprintf('Consumed message "%s"'."n", get_class($message));
} else {
echo sprintf('Dispatched message "%s"'."n", get_class($message));
}
return $next($envelope);
} finally {
echo sprintf('Ended with message "%s"'."n", get_class($message));
}
}
}
Your own Envelope item
use SymfonyComponentMessengerEnvelopeAwareInterface;
use SymfonyComponentMessengerMiddlewareMiddlewareInterface;
class AuditMiddleware implements MiddlewareInterface,
EnvelopeAwareInterface
{
public function handle($envelope, callable $next)
{
$message = $envelope->getMessage();
if (null === $auditEnvelope = $envelope->get(AuditEnvelopeItem::class)) {
$envelope = $envelope->with(
$auditEnvelope = new AuditEnvelopeItem(uniqid())
);
}
try {
echo sprintf('[%s] Started with message "%s"' . "n", $auditEnvelope->getUuid(), get_class($message));
return $next($envelope);
} finally {
echo sprintf('[%s] Ended with message "%s"'."n", $auditEnvelope->getUuid(), get_class($message));
}
}
}
Your own Envelope item
use SymfonyComponentMessengerEnvelopeItemInterface;
class AuditEnvelopeItem implements EnvelopeItemInterface
{
private $uuid;
public function __construct(string $uuid)
{
$this->uuid = $uuid;
}
public function getUuid()
{
return $this->uuid;
}
}
Envelopes: also for "configura3on"
use SymfonyComponentMessengerEnvelope;
use SymfonyComponentMessengerTransport
SerializationSerializerConfiguration;
$bus->dispatch(
(new Envelope($message))->with(new SerializerConfiguration([
'groups' => ['my_serialization_groups'],
]))
);
What can you do?
1. Try it!
It has arrived in Symfony 4.1. Stable in 4.2.
2. Help us make it great again.
Open an issue, a pull-request, create another transport, a set of
middleware, ...
3. Enjoy.
Thank you.
h"ps://symfony.com/messenger
@samuelroze

More Related Content

What's hot

Node JS Crash Course
Node JS Crash CourseNode JS Crash Course
Node JS Crash CourseHaim Michael
 
HTL(Sightly) - All you need to know
HTL(Sightly) - All you need to knowHTL(Sightly) - All you need to know
HTL(Sightly) - All you need to knowPrabhdeep Singh
 
Php Error Handling
Php Error HandlingPhp Error Handling
Php Error Handlingmussawir20
 
Node.js File system & Streams
Node.js File system & StreamsNode.js File system & Streams
Node.js File system & StreamsEyal Vardi
 
Node.js Event Emitter
Node.js Event EmitterNode.js Event Emitter
Node.js Event EmitterEyal Vardi
 
base de données -note de cours
base de données -note de cours base de données -note de cours
base de données -note de cours Yassine Badri
 
[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어
[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어
[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어CONNECT FOUNDATION
 
HTML5 Local Storage
HTML5 Local StorageHTML5 Local Storage
HTML5 Local StorageLior Zamir
 
Apache Server Tutorial
Apache Server TutorialApache Server Tutorial
Apache Server TutorialJagat Kothari
 
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPTBài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPTMasterCode.vn
 
Web Components
Web ComponentsWeb Components
Web ComponentsFITC
 

What's hot (20)

Files in php
Files in phpFiles in php
Files in php
 
Node JS Crash Course
Node JS Crash CourseNode JS Crash Course
Node JS Crash Course
 
Langage HTML
Langage HTMLLangage HTML
Langage HTML
 
HTL(Sightly) - All you need to know
HTL(Sightly) - All you need to knowHTL(Sightly) - All you need to know
HTL(Sightly) - All you need to know
 
Php Error Handling
Php Error HandlingPhp Error Handling
Php Error Handling
 
Initiation au html
Initiation au htmlInitiation au html
Initiation au html
 
Node.js File system & Streams
Node.js File system & StreamsNode.js File system & Streams
Node.js File system & Streams
 
Node.js Event Emitter
Node.js Event EmitterNode.js Event Emitter
Node.js Event Emitter
 
Php Presentation
Php PresentationPhp Presentation
Php Presentation
 
Cookie and session
Cookie and sessionCookie and session
Cookie and session
 
base de données -note de cours
base de données -note de cours base de données -note de cours
base de données -note de cours
 
Node ppt
Node pptNode ppt
Node ppt
 
[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어
[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어
[부스트캠퍼세미나]조성동_야_너두_TDD_할_수_있어
 
HTML5 Local Storage
HTML5 Local StorageHTML5 Local Storage
HTML5 Local Storage
 
Apache Server Tutorial
Apache Server TutorialApache Server Tutorial
Apache Server Tutorial
 
Polymorphisme
PolymorphismePolymorphisme
Polymorphisme
 
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPTBài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
Bài 6 Lập trình PHP (phần 4) Làm việc với cookie và session - Giáo trình FPT
 
Web Components
Web ComponentsWeb Components
Web Components
 
Soap vs rest
Soap vs restSoap vs rest
Soap vs rest
 
flask.pptx
flask.pptxflask.pptx
flask.pptx
 

Similar to Symfony Messenger (Symfony Live San Francisco)

Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Michał Kurzeja
 
Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"Fwdays
 
From Ruby to Node.js
From Ruby to Node.jsFrom Ruby to Node.js
From Ruby to Node.jsjubilem
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018Юлия Коваленко
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Fabien Potencier
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupKacper Gunia
 
Symfony finally swiped right on envvars
Symfony finally swiped right on envvarsSymfony finally swiped right on envvars
Symfony finally swiped right on envvarsSam Marley-Jarrett
 
PHP, RabbitMQ, and You
PHP, RabbitMQ, and YouPHP, RabbitMQ, and You
PHP, RabbitMQ, and YouJason Lotito
 
A Docker-based Development Environment Even I Can Understand
A Docker-based Development Environment Even I Can UnderstandA Docker-based Development Environment Even I Can Understand
A Docker-based Development Environment Even I Can UnderstandJeremy Gimbel
 
Mastering message queues | Tobias Nyholm | CODEiD
Mastering message queues | Tobias Nyholm | CODEiDMastering message queues | Tobias Nyholm | CODEiD
Mastering message queues | Tobias Nyholm | CODEiDCODEiD PHP Community
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiJérémy Derussé
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发shaokun
 
Taming Cloud APIs with Swift
Taming Cloud APIs with SwiftTaming Cloud APIs with Swift
Taming Cloud APIs with SwiftTim Burks
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkRyan Weaver
 
Docker serverless v1.0
Docker serverless v1.0Docker serverless v1.0
Docker serverless v1.0Thomas Chacko
 
Symfony 4: A new way to develop applications #phpsrb
 Symfony 4: A new way to develop applications #phpsrb Symfony 4: A new way to develop applications #phpsrb
Symfony 4: A new way to develop applications #phpsrbAntonio Peric-Mazar
 
Intro to MPI
Intro to MPIIntro to MPI
Intro to MPIjbp4444
 

Similar to Symfony Messenger (Symfony Live San Francisco) (20)

Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019Symfony messenger - PHPers Summit 2019
Symfony messenger - PHPers Summit 2019
 
Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"Fabien Potencier "Symfony 4 in action"
Fabien Potencier "Symfony 4 in action"
 
From Ruby to Node.js
From Ruby to Node.jsFrom Ruby to Node.js
From Ruby to Node.js
 
Filesystem abstractions and msg queue sergeev - symfony camp 2018
Filesystem abstractions and msg queue   sergeev - symfony camp 2018Filesystem abstractions and msg queue   sergeev - symfony camp 2018
Filesystem abstractions and msg queue sergeev - symfony camp 2018
 
Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3Symfony Components 2.0 on PHP 5.3
Symfony Components 2.0 on PHP 5.3
 
Symfony2 revealed
Symfony2 revealedSymfony2 revealed
Symfony2 revealed
 
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK MeetupScaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
Scaling Symfony2 apps with RabbitMQ - Symfony UK Meetup
 
Symfony finally swiped right on envvars
Symfony finally swiped right on envvarsSymfony finally swiped right on envvars
Symfony finally swiped right on envvars
 
Test driven infrastructure
Test driven infrastructureTest driven infrastructure
Test driven infrastructure
 
PHP, RabbitMQ, and You
PHP, RabbitMQ, and YouPHP, RabbitMQ, and You
PHP, RabbitMQ, and You
 
Fabric Python Lib
Fabric Python LibFabric Python Lib
Fabric Python Lib
 
A Docker-based Development Environment Even I Can Understand
A Docker-based Development Environment Even I Can UnderstandA Docker-based Development Environment Even I Can Understand
A Docker-based Development Environment Even I Can Understand
 
Mastering message queues | Tobias Nyholm | CODEiD
Mastering message queues | Tobias Nyholm | CODEiDMastering message queues | Tobias Nyholm | CODEiD
Mastering message queues | Tobias Nyholm | CODEiD
 
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry PiGrâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
Grâce aux tags Varnish, j'ai switché ma prod sur Raspberry Pi
 
Rails web api 开发
Rails web api 开发Rails web api 开发
Rails web api 开发
 
Taming Cloud APIs with Swift
Taming Cloud APIs with SwiftTaming Cloud APIs with Swift
Taming Cloud APIs with Swift
 
Hands-on with the Symfony2 Framework
Hands-on with the Symfony2 FrameworkHands-on with the Symfony2 Framework
Hands-on with the Symfony2 Framework
 
Docker serverless v1.0
Docker serverless v1.0Docker serverless v1.0
Docker serverless v1.0
 
Symfony 4: A new way to develop applications #phpsrb
 Symfony 4: A new way to develop applications #phpsrb Symfony 4: A new way to develop applications #phpsrb
Symfony 4: A new way to develop applications #phpsrb
 
Intro to MPI
Intro to MPIIntro to MPI
Intro to MPI
 

More from Samuel ROZE

Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)Samuel ROZE
 
Living documentation
Living documentationLiving documentation
Living documentationSamuel ROZE
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
Micro services may not be the best idea
Micro services may not be the best ideaMicro services may not be the best idea
Micro services may not be the best ideaSamuel ROZE
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingSamuel ROZE
 
CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationSamuel ROZE
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patternsSamuel ROZE
 
Take care of our micro services
Take care of our micro servicesTake care of our micro services
Take care of our micro servicesSamuel ROZE
 
(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et ToleranceSamuel ROZE
 
Using continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflowsUsing continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflowsSamuel ROZE
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form componentSamuel ROZE
 
Behat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than thatBehat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than thatSamuel ROZE
 
Docker orchestration with Kubernetes
Docker orchestration with KubernetesDocker orchestration with Kubernetes
Docker orchestration with KubernetesSamuel ROZE
 
Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer Samuel ROZE
 

More from Samuel ROZE (14)

Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)Event streaming: what will go wrong? (Symfony World 2020)
Event streaming: what will go wrong? (Symfony World 2020)
 
Living documentation
Living documentationLiving documentation
Living documentation
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Micro services may not be the best idea
Micro services may not be the best ideaMicro services may not be the best idea
Micro services may not be the best idea
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event Sourcing
 
CQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony applicationCQRS and Event Sourcing in a Symfony application
CQRS and Event Sourcing in a Symfony application
 
How I started to love design patterns
How I started to love design patternsHow I started to love design patterns
How I started to love design patterns
 
Take care of our micro services
Take care of our micro servicesTake care of our micro services
Take care of our micro services
 
(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance(micro)services avec Symfony et Tolerance
(micro)services avec Symfony et Tolerance
 
Using continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflowsUsing continuouspipe to speed up our workflows
Using continuouspipe to speed up our workflows
 
Symfony CoP: Form component
Symfony CoP: Form componentSymfony CoP: Form component
Symfony CoP: Form component
 
Behat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than thatBehat c'est plus que ça | Behat is more than that
Behat c'est plus que ça | Behat is more than that
 
Docker orchestration with Kubernetes
Docker orchestration with KubernetesDocker orchestration with Kubernetes
Docker orchestration with Kubernetes
 
Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer Symfony et serialization avec JMS serializer
Symfony et serialization avec JMS serializer
 

Recently uploaded

Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Cizo Technology Services
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtimeandrehoraa
 
Innovate and Collaborate- Harnessing the Power of Open Source Software.pdf
Innovate and Collaborate- Harnessing the Power of Open Source Software.pdfInnovate and Collaborate- Harnessing the Power of Open Source Software.pdf
Innovate and Collaborate- Harnessing the Power of Open Source Software.pdfYashikaSharma391629
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Velvetech LLC
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceBrainSell Technologies
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringHironori Washizaki
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprisepreethippts
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Mater
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commercemanigoyal112
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxRTS corp
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...Akihiro Suda
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsChristian Birchler
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 

Recently uploaded (20)

2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva2.pdf Ejercicios de programación competitiva
2.pdf Ejercicios de programación competitiva
 
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
Global Identity Enrolment and Verification Pro Solution - Cizo Technology Ser...
 
SpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at RuntimeSpotFlow: Tracking Method Calls and States at Runtime
SpotFlow: Tracking Method Calls and States at Runtime
 
Innovate and Collaborate- Harnessing the Power of Open Source Software.pdf
Innovate and Collaborate- Harnessing the Power of Open Source Software.pdfInnovate and Collaborate- Harnessing the Power of Open Source Software.pdf
Innovate and Collaborate- Harnessing the Power of Open Source Software.pdf
 
Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...Software Project Health Check: Best Practices and Techniques for Your Product...
Software Project Health Check: Best Practices and Techniques for Your Product...
 
CRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. SalesforceCRM Contender Series: HubSpot vs. Salesforce
CRM Contender Series: HubSpot vs. Salesforce
 
Machine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their EngineeringMachine Learning Software Engineering Patterns and Their Engineering
Machine Learning Software Engineering Patterns and Their Engineering
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Odoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 EnterpriseOdoo 14 - eLearning Module In Odoo 14 Enterprise
Odoo 14 - eLearning Module In Odoo 14 Enterprise
 
Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)Ahmed Motair CV April 2024 (Senior SW Developer)
Ahmed Motair CV April 2024 (Senior SW Developer)
 
Cyber security and its impact on E commerce
Cyber security and its impact on E commerceCyber security and its impact on E commerce
Cyber security and its impact on E commerce
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptxReal-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
Real-time Tracking and Monitoring with Cargo Cloud Solutions.pptx
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
 
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving CarsSensoDat: Simulation-based Sensor Dataset of Self-driving Cars
SensoDat: Simulation-based Sensor Dataset of Self-driving Cars
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 

Symfony Messenger (Symfony Live San Francisco)

  • 1. Symfony Messenger Bus, Queues, workers and more !
  • 2. Samuel Rozé VP Engineering @ Birdie Symfony Con(nuousPipe Tolerance
  • 3.
  • 4. What's Symfony Messenger about? 1. Messages. Any serialisable PHP object. 2. Message bus. Where you dispatch your messages. 3. Message handlers. Will execute your business logic when the message arrives to them. 4. Transports. Allow to send and receive messages through 3rd party systems. 5. Worker. To consume messages from transports.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10. $ composer req symfony/messenger or composer req messenger
  • 11. A message No specific requirement. namespace AppMessage; class SendNotification { // ...properties public function __construct(string $message, array $users) { $this->message = $message; $this->users = $users; } // ...getters }
  • 12. As a component use SymfonyComponentMessengerMessageBus; use SymfonyComponentMessengerHandlerLocator; use SymfonyComponentMessengerMiddlewareHandleMessageMiddleware; $handler = function(SendNotification $message) { // ... }; $messageBus = new MessageBus([ new HandleMessageMiddleware(new HandlerLocator([ SendNotification::class => $handler, ])), ]);
  • 13. In your Symfony applica0on Nothing to do...
  • 14. Dispatching a message namespace AppController; use AppMessageSendNotification; // ... use SymfonyComponentMessengerMessageBusInterface; class DefaultController { public function index(MessageBusInterface $bus, Request $request) { $users = ['samuel', 'christelle']; $bus->dispatch(new SendNotification( $request->query->get('message', 'Hello London.'), $users )); return new Response('<html><body>OK.</body></html>'); } }
  • 15. Dispatching a message namespace AppController; use AppMessageSendNotification; // ... use SymfonyComponentMessengerMessageBusInterface; class DefaultController { public function index(MessageBusInterface $bus, Request $request) { $users = ['samuel', 'christelle']; $bus->dispatch(new SendNotification( $request->query->get('message', 'Hello London.'), $users )); return new Response('<html><body>OK.</body></html>'); } }
  • 16.
  • 17. A message handler namespace AppMessageHandler; use AppMessageSendNotification; class SendNotificationHandler { public function __invoke(SendNotification $message) { foreach ($message->getUsers() as $user) { echo "Send notification to... ".$user."n"; } } }
  • 18. Register your handler # config/services.yaml services: AppMessageHandlerSendNotificationHandler: tags: ['messenger.message_handler']
  • 19. Register your handlers (op3on 2) # config/services.yaml services: AppMessageHandler: resource: '../src/MessageHandler/*' tags: ['messenger.message_handler']
  • 20. Register your handlers (op3on 3) namespace AppMessageHandler; use AppMessageSendNotification; use SymfonyComponentMessengerHandlerMessageHandlerInterface; class SendNotificationHandler implements MessageHandlerInterface { public function __invoke(SendNotification $message) { foreach ($message->getUsers() as $user) { echo "Send notification to... ".$user."n"; } } }
  • 21.
  • 22. Yay, dispatched ! Handler is called. Done.
  • 23.
  • 24. Now, imagine your handler takes ages to run.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29. What's a transport? 1. Has a sender & receiver Guess what. They send and receive messages. 2. Is configurable via a DSN So we have a unique and common way of configuring them. 3. Use a Messenger Serializer By defaut, uses Symfony Serializer. Replace as you wish.
  • 30. Transports 1. Built-in AMQP. You don't need anything more than the component and the PHP extension. 2. More with Enqueue. (10+ other transports) h>ps://github.com/php-enqueue/messenger-adapter 3. Fully extensible. Create your own very easily by registering your implementaIon of the TransportFactory interface.
  • 31. Configure your transport(s) # config/packages/messenger.yaml framework: messenger: transports: default: '%env(MESSENGER_DSN)%' # .env MESSENGER_DSN=amqp://guest:guest@localhost:5672/%2f/messages
  • 33.
  • 34.
  • 35.
  • 37.
  • 38.
  • 40. Auto-wiring trick # config/services.yaml services: _defaults: autowire: true autoconfigure: true public: false bind: $eventBus: '@event_bus'
  • 41. Auto-wiring trick use SymfonyComponentMessengerMessageBusInterface; class MyController { public function __construct( MessageBusInterface $commandBus, MessageBusInterface $eventBus ) { // ... } // ... }
  • 42. Register your handlers (op3on 4) namespace AppMessageHandler; use AppMessageSendNotification; use SymfonyComponentMessengerHandlerMessageSubscriberInterface; class SendNotificationHandler implements MessageSubscriberInterface { public static function getHandledMessages(): iterable { yield SendNotification::class => [ 'method' => 'doSomething', 'bus' => 'command_bus' ]; } public function doSomething(SendNotification $message) { // ... } }
  • 43. Register your handlers (yield !!) namespace AppMessageHandler; use SymfonyComponentMessengerHandlerMessageSubscriberInterface; class SendNotificationHandler implements MessageSubscriberInterface { public static function getHandledMessages(): iterable { yield MyMessage::class => ['bus' => 'first_bus']; yield MyMessage::class => ['bus' => 'second_bus']; } public function __invoke(MyMessage $message) { // ... } }
  • 45. Middleware namespace AppMiddleware; use SymfonyComponentMessengerMiddlewareMiddlewareInterface; class AuditMiddleware implements MiddlewareInterface { public function handle($message, callable $next) { try { echo sprintf('Started with message "%s"'."n", get_class($message)); return $next($message); } finally { echo sprintf('Ended with message "%s"'."n", get_class($message)); } } }
  • 48. Envelopes namespace AppMiddleware; use SymfonyComponentMessengerMiddlewareMiddlewareInterface; use SymfonyComponentMessengerEnvelopeAwareInterface; use SymfonyComponentMessengerAsynchronousTransportReceivedMessage; class AuditMiddleware implements MiddlewareInterface, EnvelopeAwareInterface { public function handle($envelope, callable $next) { try { if (null !== $envelope->get(ReceivedMessage::class)) { echo sprintf('Consumed message "%s"'."n", get_class($message)); } else { echo sprintf('Dispatched message "%s"'."n", get_class($message)); } return $next($envelope); } finally { echo sprintf('Ended with message "%s"'."n", get_class($message)); } } }
  • 49. Envelopes namespace AppMiddleware; use SymfonyComponentMessengerMiddlewareMiddlewareInterface; use SymfonyComponentMessengerEnvelopeAwareInterface; use SymfonyComponentMessengerAsynchronousTransportReceivedMessage; class AuditMiddleware implements MiddlewareInterface, EnvelopeAwareInterface { public function handle($envelope, callable $next) { try { if (null !== $envelope->get(ReceivedMessage::class)) { echo sprintf('Consumed message "%s"'."n", get_class($message)); } else { echo sprintf('Dispatched message "%s"'."n", get_class($message)); } return $next($envelope); } finally { echo sprintf('Ended with message "%s"'."n", get_class($message)); } } }
  • 50. Your own Envelope item use SymfonyComponentMessengerEnvelopeAwareInterface; use SymfonyComponentMessengerMiddlewareMiddlewareInterface; class AuditMiddleware implements MiddlewareInterface, EnvelopeAwareInterface { public function handle($envelope, callable $next) { $message = $envelope->getMessage(); if (null === $auditEnvelope = $envelope->get(AuditEnvelopeItem::class)) { $envelope = $envelope->with( $auditEnvelope = new AuditEnvelopeItem(uniqid()) ); } try { echo sprintf('[%s] Started with message "%s"' . "n", $auditEnvelope->getUuid(), get_class($message)); return $next($envelope); } finally { echo sprintf('[%s] Ended with message "%s"'."n", $auditEnvelope->getUuid(), get_class($message)); } } }
  • 51. Your own Envelope item use SymfonyComponentMessengerEnvelopeItemInterface; class AuditEnvelopeItem implements EnvelopeItemInterface { private $uuid; public function __construct(string $uuid) { $this->uuid = $uuid; } public function getUuid() { return $this->uuid; } }
  • 52. Envelopes: also for "configura3on" use SymfonyComponentMessengerEnvelope; use SymfonyComponentMessengerTransport SerializationSerializerConfiguration; $bus->dispatch( (new Envelope($message))->with(new SerializerConfiguration([ 'groups' => ['my_serialization_groups'], ])) );
  • 53. What can you do? 1. Try it! It has arrived in Symfony 4.1. Stable in 4.2. 2. Help us make it great again. Open an issue, a pull-request, create another transport, a set of middleware, ... 3. Enjoy.