Skip to main content

Displaying notifications when Messages for Symfony Messenger are processed

A trio of modules provide a unique experience for sites utilising SM and Symfony Messenger messages: Common Stamps, Pusher Mini, and Toasty. This combination ultimately shows UI toasts in the browser when Symfony messages relevant to the user are processed.

by daniel.phin /

This post is part 7 in a series about Symfony Messenger.

  1. Introducing Symfony Messenger integrations with Drupal
  2. Symfony Messenger’ message and message handlers, and comparison with @QueueWorker
  3. Real-time: Symfony Messenger’ Consume command and prioritised messages
  4. Automatic message scheduling and replacing hook_cron
  5. Adding real-time processing to QueueWorker plugins
  6. Making Symfony Mailer asynchronous: integration with Symfony Messenger
  7. Displaying notifications when Symfony Messenger messages are processed
  8. Future of Symfony Messenger in Drupal

toast

The full picture

From beginning to end, when a message is dispatched additional metadata is applied to the message. Later, after the message has been successfully processed, the message is captured. Metadata is extracted from the message and transformed. Recipients for the message are determined, usually based on the user who was logged in when the message was dispatched. The processed metadata is dispatched to a Pusher-compatible websocket server, which pushes the processed metadata to web browser sessions of the message recipients.

The message

A message is constructed and dispatched as usual, though to utilise the UI the Description , Action , and Link stamps provided by the Common Stamps module are applied. These stamps provide additional user-friendly context describing what the message is doing, and subsequently display text, links, and buttons once the message has been successfully processed.

use \Drupal\stamps\Messenger\Stamp\DescriptionStamp;
use \Drupal\stamps\Messenger\Stamp\ActionsStamp;
use \Drupal\Core\Link;
use \Symfony\Component\Messenger\Envelope;

$envelope = new Envelope($testMessage, [
  DescriptionStamp::create(title: 'A custom message!', description: '...and a description.'),
  ActionsStamp::fromLinks(primary: [
    Link::fromTextAndUrl('Go home', Url::fromRoute('<front>'))
  ]),
]);
$bus->dispatch($envelope);

This code produces toasts like:

Toasty
Toasty displaying notifications.

For example, a message may be scheduled for a future date (via \Symfony\Component\Messenger\Stamp\DelayStamp) to publish content. Metadata stamps could include information such as the content title, a description like The content was published, and a handy action link to the content itself.

Bus, middlewares, and processing

Once a message has been dispatched to the bus, middleware from both Common Stamps and Toasty will modify and send notifications respectively. The current user middleware from Common Stamps will apply a user stamp tracking which user, if any, was authenticated while the message was dispatched.

Later, after the message handler has successfully processed the message, Toasty’s’ middleware intercepts the message. Metadata like description, links, buttons, and recipients are compiled by reading the stamps applied to the message. This metadata is subsequently transmitted to the websocket server.

The websocket server

Toasty includes a Vue app to render the user interface and connects to the websocket server. It establishes a persistent connection and listens for notifications dispatched by Toasty to the websocket server.

The websocket server can be the official Pusher.com service, which provides 200,000 free messages per day. Alternatively, you can choose to self-host using Soketi, an open source app that is compatible with the Pusher API.

Pusher Mini combines Key, which is used for storing secrets, with the Pusher PHP library to connect to Pusher.com or a Soketi server.

After installation, a key is set up with app secrets. The Pusher Mini module configuration sets up routing, non-secrets, and connection details for both the client-websocket server, and another for the application-websocket server.

Key config
Pusher mini config

Once websockets are configured, messages will be pushed to the browser as soon as the middleware of Messenger and Toasty has processed the message.

Received messages are transformed into small notification toasts for the user to take action on or ignore.

toast

The next and final post in this Symfony Messenger series covers how we could bring the integration components introduced by SM into Drupal core.

Related Articles

Adding real-time processing to QueueWorker plugins

Projects no longer need to rely on unpredictable processing time frames. The SM project can intercept legacy Drupal @QueueWorker items and insert them into the Symfony Messenger message bus, effectively giving existing core and contrib queue workers jobs real-time processing capabilities.

Automatic message scheduling and replacing hook_cron

Symfony Scheduler provides a viable replacement to hook_cron wherein messages can be scheduled for dispatch at a predefined interval. Messages are dispatched the moment they are scheduled, and there is no message duplication, making tasks more reliable and efficient.