Support the ongoing development of Laravel.io →
Echo Queues Laravel

Hello there!

I want to trigger an event when a user's feed (of articles) is being updated. When the feed is updated, a FeedGenerated event is being broadcasted, and I would like my front-end to catch the event to allow user to manually refresh his feed.

The FeedGenerated event is being listened by the UpdateFeedArticles listener. This listener just Logs something for now (and it logs successfully).

The event is broadcasted as follow:

FeedGenerated::broadcast($user);

The FeedGenerated event:

<?php

namespace App\Providers;

use App\Models\User;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithBroadcasting;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class FeedGenerated implements ShouldBroadcast
{
    use Dispatchable, InteractsWithSockets, SerializesModels, InteractsWithBroadcasting;


    /**
     * The name of the queue connection to use when broadcasting the event.
     *
     * @var string
     */
    public string $connection = 'redis';

    /**
     * The name of the queue on which to place the broadcasting job.
     *
     * @var string
     */
    public string $queue = 'default';

    /**
     * Create a new event instance.
     */
    public function __construct(public User $user)
    {
        //
    }

    /**
     * Get the channels the event should broadcast on.
     *
     * @return array<int, \Illuminate\Broadcasting\Channel>
     */
    public function broadcastOn(): array
    {
        return [
            new Channel("user"),
        ];
    }
}

The UpdateFeedArticle listener:

<?php

namespace App\Providers;

use App\Providers\FeedGenerated;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;

class UpdateFeedArticles
{
    /**
     * Create the event listener.
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     */
    public function handle(FeedGenerated $event): void
    {
        \Log::debug('Event triggered', ['event' => $event, 'listener' => $this]);
    }
}

Laravel Echo instanciation:

import Echo from 'laravel-echo';

import Pusher from 'pusher-js';

window.Pusher = Pusher;

window.Websocket = new Echo({
    broadcaster: 'pusher',
    key: import.meta.env.VITE_PUSHER_APP_KEY,
    cluster: import.meta.env.VITE_PUSHER_APP_CLUSTER,
    wsHost: import.meta.env.VITE_PUSHER_HOST,
    wsPort: import.meta.env.VITE_PUSHER_PORT,
    wssPort: import.meta.env.VITE_PUSHER_PORT,
    forceTLS: false,
    encrypted: false,
    disableStats: true,
    enabledTransports: ['ws', 'wss'],
});

Websocket.connector.pusher.connection.bind('connected', () => {
    console.log('✅ Soketi Connected!');
});

Websocket.connector.pusher.connection.bind('disconnected', () => {
    console.log('👋 Soketi Disconnected!');
});

Websocket.connector.pusher.connection.bind('failed', () => {
    console.log('❌ Soketi Connection Failed!');
});

Here is my docker-composer.yml

version: '3'

networks:
  network_shapes:
    ipam:
      driver: default
    driver: bridge

services:
  phpfpm:
    container_name: '${APP_NAME}'
    build:
      args:
        user: '${WWWUSER}'
        uid: '${WWWGROUP}'
      context: ./docker
      dockerfile: Dockerfile
    working_dir: /var/www/html
    volumes:
      - ./:/var/www/html
      - 'tmpfiles:/tmp'
    networks:
      - network_shapes
    depends_on:
      - mariadb
    restart: unless-stopped

  soketi:
    image: 'quay.io/soketi/soketi:latest-16-alpine'
    environment:
      SOKETI_DEBUG: '${SOKETI_DEBUG:-1}'
      SOKETI_METRICS_SERVER_PORT: '${SOKETI_METRICS_SERVER_PORT}'
    ports:
      - '${SOKETI_PORT:-6001}:6001'
      - '${SOKETI_METRICS_SERVER_PORT:-9601}:9601'
    networks:
      - network_shapes
    depends_on:
      - redis

  nginx:
    image: ${NGINX_IMAGE}
    networks:
      - network_shapes
    ports:
      - '127.0.0.1:${APP_PORT}:80'
    volumes:
      - ./docker/nginx/tkt.conf:/etc/nginx/conf.d/default.conf
      - ./:/var/www/html
      - 'tmpfiles:/tmp'
    links:
      - phpfpm
    depends_on:
      - mariadb
    restart: unless-stopped

  mongo:
    ...

  redis:
    image: 'redis:latest'
    ports:
      - '127.0.0.1:${REDIS_PORT:-6379}:6379'
    volumes:
      - 'redis_volume:/data'
    networks:
      - network_shapes
    healthcheck:
      test: [ "CMD", "redis-cli", "ping" ]
      retries: 3
      timeout: 5s
    restart: unless-stopped

  mariadb:
    ...

  mailhog:
    ...

volumes:
  tmpfiles:
    driver: local
  mariadb_volume:
    driver: local
  redis_volume:
    driver: local

Here is my Nginx tkt.conf

server {
    listen 80;

    server_name localhost www.localhost .localhost *.localhost;

    index index.php index.html;

    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;

    root /var/www/html/public;

    client_max_body_size 100M;

    location /mailhog/ {
        proxy_pass      http://mailhog:8025/;
        proxy_set_header    Host             $host;
        proxy_set_header    X-Real-IP        $remote_addr;
        proxy_set_header    X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header    X-Client-Verify  SUCCESS;
        proxy_read_timeout 1800;
        proxy_connect_timeout 1800;
        chunked_transfer_encoding on;
        proxy_set_header X-NginX-Proxy true;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_redirect off;
        proxy_buffering off;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass phpfpm:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }

    location /websocket/ {
         proxy_pass http://127.0.0.1:6001;
         proxy_http_version 1.1;
         proxy_set_header Upgrade $http_upgrade;
         proxy_set_header Connection "Upgrade";
         proxy_set_header Host $host;
         proxy_read_timeout 86400; # Adjust to your needs
    }
}

The situation

When running the command (that broadcast the event):

docker exec -t shapppes php artisan feed:generate 01h739jr4vk8pq3yefsp22c964
Scoring articles for Sonny Stroman...

Feed created.

Horizon logs the following:

docker exec -t shapppes php artisan horizon
Horizon started successfully.
  2023-08-07 13:04:56 App\Actions\Article\Feed\GenerateFeed .......... RUNNING
  2023-08-07 13:04:57 App\Actions\Article\Feed\GenerateFeed .... 899.66ms DONE
  2023-08-07 13:04:57 App\Providers\FeedGenerated .................... RUNNING
  2023-08-07 13:04:57 App\Providers\FeedGenerated ............... 61.82ms DONE

Redis is successfully querying (seen via Laravel Telescope)

eval -- Push the job onto the queue...
redis.call('rpush', KEYS[1], ARGV[1])
-- Push a notification onto the "notify" queue...
redis.call('rpush', KEYS[2], 1) 2 queues:default queues:default:notify {"uuid":"bf2e429e-7702-4758-bedd-d072914a3215","displayName":"App\\Providers\\FeedGenerated","job":"Illuminate\\Queue\\CallQueuedHandler@call","maxTries":null,"maxExceptions":null,"failOnTimeout":false,"backoff":null,"timeout":null,"retryUntil":null,"data":{"commandName":"Illuminate\\Broadcasting\\BroadcastEvent","command":"O:38:\"Illuminate\\Broadcasting\\BroadcastEvent\":14:{s:5:\"event\";O:27:\"App\\Providers\\FeedGenerated\":1:{s:4:\"user\";O:45:\"Illuminate\\Contracts\\Database\\ModelIdentifier\":5:{s:5:\"class\";s:15:\"App\\Models\\User\";s:2:\"id\";s:26:\"01h739jr4vk8pq3yefsp22c964\";s:9:\"relations\";a:4:{i:0;s:4:\"page\";i:1;s:14:\"page.bookmarks\";i:2;s:10:\"page.image\";i:3;s:4:\"tags\";}s:10:\"connection\";s:5:\"mysql\";s:15:\"collectionClass\";N;}}s:5:\"tries\";N;s:7:\"timeout\";N;s:7:\"backoff\";N;s:13:\"maxExceptions\";N;s:10:\"connection\";N;s:5:\"queue\";N;s:15:\"chainConnection\";N;s:10:\"chainQueue\";N;s:19:\"chainCatchCallbacks\";N;s:5:\"delay\";N;s:11:\"afterCommit\";N;s:10:\"middleware\";a:0:{}s:7:\"chained\";a:0:{}}"},"telescope_uuid":"99d54a11-c8fc-489f-8676-a575ab0466bf","id":"bf2e429e-7702-4758-bedd-d072914a3215","attempts":0,"type":"broadcast","tags":["App\\Models\\User:01h739jr4vk8pq3yefsp22c964"],"silenced":false,"pushedAt":"1691413497.6378"}

The event is successfully handled by the listener, but nothing appears to be caught by Soketi (no Docker log, no feedback on the front-end).

0

Sign in to participate in this thread!

Eventy

Your banner here too?

Gaël Duval duvalg Joined 19 Apr 2022

Moderators

We'd like to thank these amazing companies for supporting us

Your logo here?

Laravel.io

The Laravel portal for problem solving, knowledge sharing and community building.

© 2025 Laravel.io - All rights reserved.