SlideShare une entreprise Scribd logo
1  sur  54
Télécharger pour lire hors ligne
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

Contenu connexe

Tendances

Object Oriented Programming with Laravel - Session 1
Object Oriented Programming with Laravel - Session 1Object Oriented Programming with Laravel - Session 1
Object Oriented Programming with Laravel - Session 1
Shahrzad Peyman
 
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration PlatformKubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Michael O'Sullivan
 

Tendances (20)

How to Build a Platform Team
How to Build a Platform TeamHow to Build a Platform Team
How to Build a Platform Team
 
Intro to docker
Intro to dockerIntro to docker
Intro to docker
 
Docker & kubernetes
Docker & kubernetesDocker & kubernetes
Docker & kubernetes
 
Object Oriented Programming with Laravel - Session 1
Object Oriented Programming with Laravel - Session 1Object Oriented Programming with Laravel - Session 1
Object Oriented Programming with Laravel - Session 1
 
Docker 101 - Nov 2016
Docker 101 - Nov 2016Docker 101 - Nov 2016
Docker 101 - Nov 2016
 
Introduction to docker
Introduction to dockerIntroduction to docker
Introduction to docker
 
Docker
DockerDocker
Docker
 
Kubernetes 101
Kubernetes 101Kubernetes 101
Kubernetes 101
 
쿠버네티스 ( Kubernetes ) 소개 자료
쿠버네티스 ( Kubernetes ) 소개 자료쿠버네티스 ( Kubernetes ) 소개 자료
쿠버네티스 ( Kubernetes ) 소개 자료
 
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration PlatformKubernetes: An Introduction to the Open Source Container Orchestration Platform
Kubernetes: An Introduction to the Open Source Container Orchestration Platform
 
Introduction to Docker - VIT Campus
Introduction to Docker - VIT CampusIntroduction to Docker - VIT Campus
Introduction to Docker - VIT Campus
 
Laravel introduction
Laravel introductionLaravel introduction
Laravel introduction
 
Introduction to Docker
Introduction to DockerIntroduction to Docker
Introduction to Docker
 
Projects In Laravel : Learn Laravel Building 10 Projects
Projects In Laravel : Learn Laravel Building 10 ProjectsProjects In Laravel : Learn Laravel Building 10 Projects
Projects In Laravel : Learn Laravel Building 10 Projects
 
Docker Basics
Docker BasicsDocker Basics
Docker Basics
 
Docker intro
Docker introDocker intro
Docker intro
 
Distributed Caching in Kubernetes with Hazelcast
Distributed Caching in Kubernetes with HazelcastDistributed Caching in Kubernetes with Hazelcast
Distributed Caching in Kubernetes with Hazelcast
 
Intro to Helm for Kubernetes
Intro to Helm for KubernetesIntro to Helm for Kubernetes
Intro to Helm for Kubernetes
 
Introduction to Docker Compose
Introduction to Docker ComposeIntroduction to Docker Compose
Introduction to Docker Compose
 
Vulgarisation de la technologie de containers Docker
Vulgarisation de la technologie de containers DockerVulgarisation de la technologie de containers Docker
Vulgarisation de la technologie de containers Docker
 

Similaire à Symfony Messenger (Symfony Live San Francisco)

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
Fabien Potencier
 

Similaire à 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
 
Use Symfony Messenger Component and CQRS!
Use Symfony Messenger Component and CQRS!Use Symfony Messenger Component and CQRS!
Use Symfony Messenger Component and CQRS!
 
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
 

Plus de Samuel ROZE

Plus de 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
 

Dernier

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
masabamasaba
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
masabamasaba
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
masabamasaba
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
masabamasaba
 

Dernier (20)

%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
%+27788225528 love spells in new york Psychic Readings, Attraction spells,Bri...
 
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
%+27788225528 love spells in Boston Psychic Readings, Attraction spells,Bring...
 
Announcing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK SoftwareAnnouncing Codolex 2.0 from GDK Software
Announcing Codolex 2.0 from GDK Software
 
What Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the SituationWhat Goes Wrong with Language Definitions and How to Improve the Situation
What Goes Wrong with Language Definitions and How to Improve the Situation
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
WSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go PlatformlessWSO2CON2024 - It's time to go Platformless
WSO2CON2024 - It's time to go Platformless
 
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Knoxville Psychic Readings, Attraction spells,Br...
 
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
Direct Style Effect Systems -The Print[A] Example- A Comprehension AidDirect Style Effect Systems -The Print[A] Example- A Comprehension Aid
Direct Style Effect Systems - The Print[A] Example - A Comprehension Aid
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
%in Stilfontein+277-882-255-28 abortion pills for sale in Stilfontein
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
%+27788225528 love spells in Toronto Psychic Readings, Attraction spells,Brin...
 
tonesoftg
tonesoftgtonesoftg
tonesoftg
 
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
WSO2CON 2024 - Building the API First Enterprise – Running an API Program, fr...
 
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
WSO2CON 2024 - Navigating API Complexity: REST, GraphQL, gRPC, Websocket, Web...
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand%in Midrand+277-882-255-28 abortion pills for sale in midrand
%in Midrand+277-882-255-28 abortion pills for sale in midrand
 
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital TransformationWSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
WSO2Con2024 - WSO2's IAM Vision: Identity-Led Digital Transformation
 
WSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - KeynoteWSO2Con204 - Hard Rock Presentation - Keynote
WSO2Con204 - Hard Rock Presentation - Keynote
 

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.