<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Enrico Bellanti</title>
    <description>The latest articles on DEV Community by Enrico Bellanti (@enrico_dev86).</description>
    <link>https://dev.to/enrico_dev86</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F876594%2Fc946b7d6-4047-4553-959b-54c3f0233542.jpeg</url>
      <title>DEV Community: Enrico Bellanti</title>
      <link>https://dev.to/enrico_dev86</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/enrico_dev86"/>
    <language>en</language>
    <item>
      <title>Notification Brodacast System with Laravel-Websocket and Rxjs</title>
      <dc:creator>Enrico Bellanti</dc:creator>
      <pubDate>Mon, 20 Jun 2022 13:17:07 +0000</pubDate>
      <link>https://dev.to/enrico_dev86/notification-brodacast-system-with-laravel-websocket-and-rxjs-fph</link>
      <guid>https://dev.to/enrico_dev86/notification-brodacast-system-with-laravel-websocket-and-rxjs-fph</guid>
      <description>&lt;p&gt;&lt;strong&gt;Why Laravel and Rxjs?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is my first post and i would like to explain how i resolve my issue.&lt;br&gt;
Obviously you can find many tutorial to implement a websocket but sometimes you can get into my same situation when you are working with Laravel at back-end and Angular at front-end more specifically with Rxjs.&lt;br&gt;
I tried to find some tutorial online which suggest to use laravel-websockets and laravel-echo which is a very common pattern but if you are using Rxjs is not the best solution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Installing Laravel Websockets&lt;/strong&gt;&lt;br&gt;
Require the Laravel Websockets package. It works as a replacement for external services like Pusher. Many settings will refer to Pusher today but be reminded that we are not using it. We want our own solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require beyondcode/laravel-websockets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We also need a package by Pusher.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require pusher/pusher-php-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, adapt your .env file. We want the BROADCAST_DRIVER to be pusher.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BROADCAST_DRIVER=pusher
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we need to set the Pusher credentials.&lt;br&gt;
(Note: Again I want to mention that we do not use the Pusher service. Our websockets server just has the same API.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PUSHER_APP_ID=12345
PUSHER_APP_KEY=12345
PUSHER_APP_SECRET=12345
PUSHER_APP_CLUSTER=mt1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Laravel Websockets package comes with a migration file for storing statistics and a config file we need to adapt. Let's publish them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan vendor:publish --provider="BeyondCode\LaravelWebSockets\WebSocketsServiceProvider" --tag="migrations"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new migration file that we can run. Make sure you have set up a database for this project and defined the DB credentials in the .env file. Afterward, we can run the migration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here, we publish the config file of Laravel Websockets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan websockets:serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To test that it is running, we can check the debugging dashboard under the endpoint /laravel-websockets. You can click connect to see if the dashboard can connect to the WebSockets server.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5zxebmkldwblwjwb4rx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd5zxebmkldwblwjwb4rx.png" alt="laravel-websockets-screen" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After clicking connect, you should see that the dashboard is subscribed to some debugging channels like private-websockets-dashboard-api-message. This will tell you that the server is set up correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Broadcast Notifications From Our Laravel Application&lt;/strong&gt;&lt;br&gt;
We can use notifications to send data to our WebSockets server. So let's create a new one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:notification RealTimeNotification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what we need to change:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use the ShouldBroadcast interface&lt;/li&gt;
&lt;li&gt;add a message property which we will pass through the constructor&lt;/li&gt;
&lt;li&gt;use the broadcast channel in the via method&lt;/li&gt;
&lt;li&gt;add a toBroadcast method to define the message
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\BroadcastMessage;

class RealTimeNotification extends Notification implements ShouldBroadcast
{
    use ShouldQueue;

    public string $message;

    public function __construct(string $message)
    {
        $this-&amp;gt;message = $message;
    }

    public function via($notifiable): array
    {
        return ['broadcast'];
    }

    public function toBroadcast($notifiable): BroadcastMessage
    {
        return new BroadcastMessage([
            'message' =&amp;gt; "$this-&amp;gt;message (User $notifiable-&amp;gt;id)",
            'event' =&amp;gt; class_basename($this),
        ]);
    }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before we can try sending this event, please adapt your broadcasting.php config file to use the following options:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'options' =&amp;gt; [
    'cluster' =&amp;gt; env('PUSHER_APP_CLUSTER'),
    'encrypted' =&amp;gt; false,
    'host' =&amp;gt; '127.0.0.1',
    'port' =&amp;gt; 6001,
    'scheme' =&amp;gt; 'http'
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these options, we make sure that when we broadcast something from our Laravel application, it gets sent to our WebSockets server.&lt;/p&gt;

&lt;p&gt;Let's have a test if everything is working properly.&lt;br&gt;
Let's trigger the nofification and check in the websockets dashbord if you have sucess.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$user = User::first();

$user-&amp;gt;notify(new App\Notifications\RealTimeNotification('Hello World'));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9dwozsfa8cue0yemfpe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9dwozsfa8cue0yemfpe.png" alt="websockets-dashboard-notification-test" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time to connect back-end to fornt-end&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's have a look at code to see how to connect front-end with Rxjs with laravel-websockets&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { ChangeDetectionStrategy, Component, OnDestroy } from '@angular/core';
import { Store } from '@ngrx/store';
import { filter, map, Subject, takeUntil } from 'rxjs';
import { IAuthTokenWs } from './shared/interfaces/webSocket.interface';
import { WebsocketService } from './shared/services/webSocket/websocket.service';
import { selectUserId } from './store/user/user-feature.selectors';

@Component({
  selector: 'hh-root',
  template: `
    &amp;lt;bn-loading-spinner&amp;gt;&amp;lt;/bn-loading-spinner&amp;gt;
    &amp;lt;router-outlet&amp;gt;&amp;lt;/router-outlet&amp;gt;
  `,
  styleUrls: ['./app.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements OnDestroy {
  destroy$$ = new Subject&amp;lt;void&amp;gt;();

  constructor(private websocketService: WebsocketService, private store: Store) {
    this.store
      .select(selectUserId)
      .pipe(
        takeUntil(this.destroy$$),
        filter((e) =&amp;gt; !!e),
        map((user_id) =&amp;gt; {
          let socket$ = new WebSocket('ws://localhost:6001/app/12345');

          socket$.onmessage = (msg) =&amp;gt; {
            let obj = JSON.parse(msg.data);

            if (obj.event === 'pusher:connection_established') {
              let socket_id = JSON.parse(obj.data).socket_id;
              this.websocketService
                .authWebsocket(user_id!!, socket_id)
                .pipe(takeUntil(this.destroy$$))
                .subscribe((e: IAuthTokenWs) =&amp;gt; {
                  let tmp = JSON.stringify({
                    event: 'pusher:subscribe',
                    data: {
                      auth: e.auth,
                      channel: `private-App.Models.User.${user_id}`,
                    },
                  });
                  socket$.send(tmp);
                });
            } else {
              this.websocketService.notifications.next([
                ...this.websocketService.notifications.value,
                JSON.parse(obj?.data)?.message,
              ]);
              console.log(JSON.parse(obj?.data)?.message);
            }
          };
        }),
      )
      .subscribe();
  }

  ngOnDestroy(): void {
    this.destroy$$.next();
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably noticed that we did not define a channel name with our notification as we did in our event. This is because there is a default pattern for the channel name of a notification notifiable-class.key. In our case, this would be App.Models.User.1. And when you take a look at the Web dashboard, you find a message triggered by our notification to the channel Channel: private-App.Models.User.1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
    return (int) $user-&amp;gt;id === (int) $id;
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our case we are using Ngrx aswell so we will get user_id with &lt;br&gt;
&lt;code&gt;.select(selectUserId)&lt;/code&gt;, but obiusly you can get anywhere you have stored it.&lt;br&gt;
Also in this application we use an interceptor which attach token to api call to be authorize by laravel guard at backend when we need to call the following api to retrive token auth to listen on private channel via websocket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  authWebsocket(userID: string, socket_id: string) {
    const data = {
      socket_id,
      channel_name: `private-App.Models.User.${userID}`,
    };

    return this.http.post&amp;lt;IAuthTokenWs&amp;gt;(`${this.apiBaseUrl}/broadcasting/auth`, data);
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After implemented it when triggering notification at back-end you should recive a console.log in your application front-end.&lt;br&gt;
Now your BE and FE are connected.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Considering you can receive notification in broadcast just if you are connected to the web application in real time broadcasting, probably when you are offline you won't get them back after you reconnect, there are several methods to implement this and i would like to make soon a new short tutorial "how to store notification unseen and retrives in specific moment" (for example immediatelly after login).&lt;/p&gt;

&lt;p&gt;Note: consider to implement Laravel Queue System with notifications to avoid that your faild ones never delivered to you receivers. I just wrote a an additional guide for it.&lt;a href="https://dev.to/enrico_dev86/laravel-notification-system-with-queue-28p4"&gt;notification-queue-tutorial&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>laravel</category>
      <category>angular</category>
      <category>react</category>
      <category>rxjs</category>
    </item>
    <item>
      <title>Laravel Notification System with Queue</title>
      <dc:creator>Enrico Bellanti</dc:creator>
      <pubDate>Mon, 20 Jun 2022 13:10:00 +0000</pubDate>
      <link>https://dev.to/enrico_dev86/laravel-notification-system-with-queue-28p4</link>
      <guid>https://dev.to/enrico_dev86/laravel-notification-system-with-queue-28p4</guid>
      <description>&lt;p&gt;&lt;strong&gt;Why Laravel Queue?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As i explain in previus posts i really suggest when you are using notification to implement also a queue system to avoid that failed notifications never get delivered.&lt;br&gt;
Reading the queue notification for first time seems to be something complicated to be implemented but it isn't so hard.&lt;br&gt;
I'll try to help you with this tutorial to make it easier as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's start&lt;/strong&gt;&lt;br&gt;
In order to use Queue you need to migrate table jobs with laravel command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:table

php artisan migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then set the .ENV file with database&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QUEUE_CONNECTION=database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's now create a notification example and see how to implement interface and trait&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Messages\BroadcastMessage;

class RealTimeNotification extends Notification implements ShouldBroadcast
{
    use Queueable;

    public string $message;

    public function __construct(string $message)
    {
        $this-&amp;gt;message = $message;
    }

    public function via($notifiable): array
    {
        return ['broadcast'];
    }

    public function toBroadcast($notifiable): BroadcastMessage
    {
        return new BroadcastMessage([
            'message' =&amp;gt; "$this-&amp;gt;message"
        ]);
    }

    /**
     * Get the array representation of the notification.
     *
     * @param  mixed  $notifiable
     * @return array
     */
    public function toArray($notifiable)
    {
        return [
            'message' =&amp;gt; "$this-&amp;gt;message",
        ];
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with the method &lt;em&gt;toArray&lt;/em&gt; we can specify how the notification must be formatted to be saved in the queue. Also this method is used to save the notification in notifications database table (I have already explained this feature in the post Notification System with websocket &lt;a href="https://dev.tourl"&gt;&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;One you add in notification class the interfrace "ShouldBroadcast" and the trait "Queueable" you can automatically send to job table all the notifications and in case they fail you can continue to manage without loosing forever, i will show you forward in this tutorial how to do that.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Artisan queue:work&lt;/strong&gt;&lt;br&gt;
From now you will have two table in database &lt;em&gt;jobs&lt;/em&gt; and &lt;em&gt;failed_jobs&lt;/em&gt; ones you trigger a notification it will be delivered firstly on jobs table and managed in queue if one of these fails it will be moved to failed_jobs table avoid to be get lost.&lt;/p&gt;

&lt;p&gt;To manage all these processes you need to start the artisan command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:work
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;after this command you can specify several configurations to be set at most but for this i would suggest to have a look at laravel docs&lt;br&gt;
&lt;a href="https://laravel.com/docs/9.x/queues#the-queue-work-command"&gt;laravel-queue-doc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The artisan &lt;em&gt;queue:work&lt;/em&gt; get one by one your notifications and send them according to your needs.&lt;br&gt;
you have here an example of configs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:work --sleep=3 --tries=3 --backoff=3 --max-time=3600 --max-jobs=5 --stop-when-empty****
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see i just set --tries 3, for example, in this way you can make the system tries 3 times to send notification before it get failed and move to failed_jobs table.&lt;/p&gt;

&lt;p&gt;Sometimes jobs can fail for a variety of resons, such as an exceeded worker timeout, in these case you can manage these in a different time, you can do that just running the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan queue:retry 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in this way you just pull back your jobs to the jobs table and make queue:work reprocess for a second time and give it a second chance.&lt;/p&gt;

&lt;p&gt;!attention: all these processes are run manually in this tutorial but should be managed by your server, i would suggest to install a &lt;em&gt;supervisor&lt;/em&gt; and just add the configuration that laravel provide in its documentation&lt;br&gt;
&lt;a href="https://laravel.com/docs/9.x/queues#supervisor-configuration"&gt;supervisor configuration&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;installing supervisor is not so difficult and after that you will have a supervisor.conf file where to add some settings like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3 --backoff=3 --max-time=3600 --max-jobs=5 --stop-when-empty
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
startretries=3
user=root
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
stderr_logfile=/var/www/html/storage/logs/worker-error.log
stopwaitsecs=3600
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hope this tutorial would be helpful but if i missed something or you have some ideas to refactor please contact me at &lt;a href="https://twitter.com/enrico_dev86"&gt;twitter-personal-link&lt;/a&gt;.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
