Git Product home page Git Product logo

nuwber / rabbitevents Goto Github PK

View Code? Open in Web Editor NEW
120.0 120.0 36.0 10.75 MB

Nuwber's RabbitEvents provides a simple observer implementation, allowing you to publishing and handling for various events that occur in your applications. For example, if you need to react to some event occurred in another API.

License: MIT License

PHP 97.71% Shell 1.93% Dockerfile 0.37%
broadcast broadcasting-events event-sourcing eventbus events laravel microservice publish-subscribe rabbitmq registering-events

rabbitevents's People

Contributors

ahloul avatar andrew-nuwber avatar chris-murat avatar eugene-nuwber avatar igor875126 avatar joskfg avatar le-yak avatar lucianholt97 avatar masterjus avatar matthewhallcom avatar morloderex avatar nicita13 avatar nope7777 avatar progorn avatar thanhsonitnic avatar webartisan10 avatar zhenya293456 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rabbitevents's Issues

Your application doesn't have any registered broadcast events

I cannot get the Listener to log at all.

The command line artisan rabbitevents:listen feedback is running, the published event appears in the RabbitMQ management interface if I don't have the command line running.

I can view the message and the payload is all there but as soon as I run the command line, the message is acknowledged and plucked from RabbitMQ Management but the Listener in the same app is not called (no log events written to the log files).

<?php

namespace App\Providers;

use Nuwber\Events\RabbitEventsServiceProvider;

class RabbitEventsServiceProvider extends RabbitEventsServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'feedback' => [
            'App\Listeners\Feedback\FeedbackLogger',
        ],
    ];

    public function boot()
    {
        parent::boot();
        //
    }
}
<?php

namespace App\Listeners\Feedback;

use Illuminate\Support\Facades\Log;

class FeedbackLogger
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        Log::info('Feedback Logger Init...');
    }

    /**
     * Handle the event.
     *
     * @param  object  $event
     * @return void
     */
    public function handle(string $event, array $payload)
    {
        Log::info('Feedback Logger Fired!...');
        Log::info($event);

        if ($event === 'feedback.created') {
            Log::info('New Feedback Ticket...');
            Log::info(print_r($payload));
        }
    }
}
    Route::get('/tests/rabbit', function () {
        publish('feedback', ['subject' => 'Test Feedback Ticket!', 'comments' => 'Random Feedback Comments...!', 'sent_at' => now()->format('H:i:s A')]);

        return 'done!';
    });

oh and I also had to change the composer.json to pull in 'dev-master' to get the install commands to be pulled in, just calling the composer command you have in your documents pulls in a version missing all that.

Do payloads have to be JSON?

In the Queue\Job class it uses the payload function from \Illuminate\Queue\Jobs\Job. This function returns json and if the payload in rabbitmq is not json it returns null. When this happens you will get a too few arguments error on your listener classes handle function.

If its expected that we will always be using json can we add that to the documentation? Otherwise we should implement this so other none json data can be stored and passed along.

Can't install this package

Run

composer require nuwber/rabbitevents

Then got error:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for nuwber/rabbitevents ^4.3 -> satisfiable by nuwber/rabbitevents[v4.3].
    - nuwber/rabbitevents v4.3 requires ext-pcntl * -> the requested PHP extension pcntl is missing from your system.

  To enable extensions, verify that they are enabled in your .ini files:
    - C:\xampp\php\php.ini
  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.

Installation failed, reverting ./composer.json to its original content.

Implement `publish` method and helper.

Currently, there's only one way to publish a message: to call fire helper instead of to call big construction of class calls.

The idea is to make other possibilities:

  1. To create some event class that can be published with method publish. Example:
$payload = [
...
];

SomeEvent::publish($payload)
  1. To create helper function publish which could accept event object or an array. Example:
$payload = [];

publish(new SomeEvent($payload));

publish($payload); //like now by helper `fire`
  1. Keep function fire work as it currently work

This solution should also fix the usual problem when a developer passes only one array and when params are passing to listeners, they could be passed as several args (every array element as a separate variable), not one array.

exception Illuminate\Container\EntryNotFoundException when try using command

I'm getting this error

Illuminate\Container\EntryNotFoundException

<?php
namespace App\Console\Commands;
use App\Jobs\PingJob;
use Illuminate\Console\Command;
use App\Events\SomeEvent;

class PingJobCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'ping:job';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     * @throws \Throwable
     */
    public function handle()
    {
        SomeEvent::publish(["name"=>"some name"]);
    }
}

Fanout events

Does the project support sending events using Fanout type?

Need more tests

There are few classes and methods that needs to be covered by tests

PsrContext not instantiable

While playing with this library I've run into the following exception...

Illuminate\Contracts\Container\BindingResolutionException thrown with message "Target [Interop\Queue\PsrContext] is not instantiable while building [Nuwber\Events\BroadcastFactory]."

I've following the instructions on the README.md and done the following...

  1. Installed the package with composer require nuwber/rabbitevents
  2. Created RabbitMQEventServiceProvider that extends Nuwber\Events\BroadcastEventServiceProvider
  3. Registered the following with my app service providers... \App\Providers\RabbitMQEventServiceProvider::class, \Enqueue\LaravelQueue\EnqueueServiceProvider::class,
  4. Setup the queue driver for interop and set it as the default.

This is version 5.5 of Laravel. Any ideas what I'm missing or what might be wrong?

Add option --message-ttl

There's the option --tries which tells how many times a Message could be handled. But there's the problem if a Message becomes outdated. If there's still possible tries but a Message is already expired, it sould be skept and removed from a queue.

The --message-life-time (could be ranamed if necessary) should set the number of seconds in which a message should be handled.

Call to undefined method Illuminate\Queue\SyncQueue::getPsrContext()

Hi there,
Thank for an awesome package.

I'm starting to playing around with this, think a got it all right with the config (reading your guide).
Tried different approaches and still get the same error message.

I've set up my app/config.php with

'providers' => [

        /*
         * Laravel Framework Service Providers...
         */
        ...
        /*
         * Package Service Providers...
         */
        
        Enqueue\LaravelQueue\EnqueueServiceProvider::class,
        Nuwber\Events\BroadcastEventServiceProvider::class,

        /*
         * Application Service Providers...
         */
        ...
        App\Providers\RabbitMQEventServiceProvider::class

    ],

App\Http\Providers\RabbitMQEventServiceProvider.php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Nuwber\Events\BroadcastEventServiceProvider;

class RabbitMQEventServiceProvider extends BroadcastEventServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */

  protected $listen = [
        'item.*' => [
            'App\Listeners\ItemLogger',
        ],
    ];
    public function register()
    {
        //
        
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
        
    }
}

App\Http\Listerns

<?php

namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class ItemLogger
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  object  $event
     * @return void
     */
    public function handle(string $event, array $payload)
    {
        //
        log($event);
        log($payload);
    }
}

Using Laravel 5.7
Im getting this error everywhere, when a fire an event or trying to listen to events.

Call to undefined method Illuminate\Queue\SyncQueue::getPsrContext()

What have a done wrong?

Thank you!

Target [Interop\Queue\PsrContext] is not instantiable while building [Nuwber\Events\BroadcastFactory].

Hey guys, I've got this error:

Target [Interop\Queue\PsrContext] is not instantiable while building [Nuwber\Events\BroadcastFactory]. after following the installation instructions.

I see this issue was closed off already without a provided fix. This is on a fresh project for testing purposes.

It comes from the Helper:

function fire(string $event, array $payload)
    {
        app(BroadcastFactory::class)->send(
            app(MessageFactory::class)->make($event, $payload)
        );
    }

When going through the debugging in Laravel 5.

Also in the instructions it says there will be a console command of events:listen but this does not exist, did you mean queue:listen by any chance?

I'd really like to try out this package if you could provide some ideas in how to resolve this issue?

Handlers could be executed twice after a Message release

Description:
Let's imagine hat we have 3 listeners on an event.

The first Listener was successfuly ran. The second was failed and the Message has been released. The third Listener was skept because the second failed.

The Message is back to the queue and we try to process it again. First Listener will be executed again.

Expected Result: Successful Listeners should not be executed after a Message release.

Getting "PhpAmqpLib\Exception\AMQPInvalidArgumentException: String too long" on message delay when I start listener without event names

Lumen version

10.0.1

Package version

8.1.3

PHP version

8.2

RabbitMQ version

3.8.34

Description

When I start listener without the event names, and some event handlers get an exception, then Enqueue\AmqpTools\RabbitMqDlxDelayStrategy tries to delay that failed event back to RMQ. However, I get an exception PhpAmqpLib\Exception\AMQPInvalidArgumentException: String too long

Full stacktrace:

PhpAmqpLib\Exception\AMQPInvalidArgumentException: String too long
#27 /vendor/php-amqplib/php-amqplib/PhpAmqpLib/Wire/AMQPWriter.php(294): PhpAmqpLib\Wire\AMQPWriter::write_shortstr
#26 /vendor/php-amqplib/php-amqplib/PhpAmqpLib/Helper/Protocol/Protocol091.php(444): PhpAmqpLib\Helper\Protocol\Protocol091::queueDeclare
#25 /vendor/php-amqplib/php-amqplib/PhpAmqpLib/Channel/AMQPChannel.php(662): PhpAmqpLib\Channel\AMQPChannel::queue_declare
#24 /vendor/enqueue/amqp-lib/AmqpContext.php(165): Enqueue\AmqpLib\AmqpContext::declareQueue
#23 /vendor/enqueue/amqp-tools/RabbitMqDlxDelayStrategy.php(53): Enqueue\AmqpTools\RabbitMqDlxDelayStrategy::delayMessage
#22 /vendor/enqueue/amqp-lib/AmqpProducer.php(149): Enqueue\AmqpLib\AmqpProducer::doSend
#21 /vendor/enqueue/amqp-lib/AmqpProducer.php(75): Enqueue\AmqpLib\AmqpProducer::send
#20 /vendor/nuwber/rabbitevents/src/RabbitEvents/Foundation/Support/Sender.php(28): RabbitEvents\Foundation\Support\Sender::send
#19 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Message/Handler.php(110): RabbitEvents\Listener\Message\Handler::release
#18 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Message/Processor.php(100): RabbitEvents\Listener\Message\Processor::handleException
#17 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Message/Processor.php(66): RabbitEvents\Listener\Message\Processor::runHandler
#16 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Message/Processor.php(33): RabbitEvents\Listener\Message\Processor::process
#15 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Worker.php(93): RabbitEvents\Listener\Worker::processMessage
#14 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Worker.php(49): RabbitEvents\Listener\Worker::work
#13 /vendor/nuwber/rabbitevents/src/RabbitEvents/Listener/Commands/ListenCommand.php(76): RabbitEvents\Listener\Commands\ListenCommand::handle
#12 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(36): Illuminate\Container\BoundMethod::Illuminate\Container\{closure}
#11 /vendor/laravel/framework/src/Illuminate/Container/Util.php(41): Illuminate\Container\Util::unwrapIfClosure
#10 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(93): Illuminate\Container\BoundMethod::callBoundMethod
#9 /vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php(35): Illuminate\Container\BoundMethod::call
#8 /vendor/laravel/framework/src/Illuminate/Container/Container.php(662): Illuminate\Container\Container::call
#7 /vendor/laravel/framework/src/Illuminate/Console/Command.php(211): Illuminate\Console\Command::execute
#6 /vendor/symfony/console/Command/Command.php(326): Symfony\Component\Console\Command\Command::run
#5 /vendor/laravel/framework/src/Illuminate/Console/Command.php(180): Illuminate\Console\Command::run
#4 /vendor/symfony/console/Application.php(1063): Symfony\Component\Console\Application::doRunCommand
#3 /vendor/symfony/console/Application.php(320): Symfony\Component\Console\Application::doRun
#2 /vendor/symfony/console/Application.php(174): Symfony\Component\Console\Application::run
#1 /vendor/laravel/lumen-framework/src/Console/Kernel.php(116): Laravel\Lumen\Console\Kernel::handle
#0 /artisan(35): null

Write more information on Exception Ocurred

Now there're 2 outputs for logs: console stdout and a system log if available.
We're able to understand a problem if console output is available but if not - debug is unavailable.

We need to write as more exception info as possible to an application log.

Make a separate config for rabbitevents

There were few issues when developers try to separate instances for rabbitevents and some other features.

So we need to create a separate config.

  1. Create the config stub
  2. Make a command like rabbitevents:install or rabbitevents:publish to publsh BroadcastEventsServiceProvider and rabbitevents.php config.
  3. The config should make possible to specify which connection to use for rabbitevents.

sync or dummy driver for testing environment

Hello,
great package, thank you for this!

Is it possible to add something like a built in sync or dummy driver for testing environments?

All laravel internal have some 'local' drivers like array for cache, memory for database or sync for queues. It makes testing scenarios very easy, because you don't need to deploy external services like rabbitmq.

Proposal:

Add a dummy driver which takes an event and it does just nothing with it. It's important, that the Listener::fake() should still work.

A config could looks like

    'connections' => [
        'rabbitmq' => [
             ...
        ],
        'testing' => [
            'driver' => 'dummy'
        ]
    ],

queue in rabbit not create with queue:work command.

When i push some job to queue for example with default queue, i receive this error:

local.ERROR: NOT_FOUND - no queue 'default' in vhost '/' {"exception":"[object] (PhpAmqpLib\Exception\AMQPProtocolChannelException(code: 404): NOT_FOUND - no queue 'default'

For some reason queue not created in rabbitmq when i try to listen to it. But when i use
php artisan rabbitevents:listen $eventname
all works correctly.

After this bug i switch to this package
https://github.com/vyuldashev/laravel-queue-rabbitmq
that include only laravel queue in one server functionaty using laravel queue API and i saw that queue created automatically in rabbitmq.

I fix this error by manually creating queue using rabbitmq manager. But if i understand correctly i shouldn't do this.

Question: Your application doesn't have any registered broadcast events.

Hey,

I'm sorry to be asking or facing all these newbie errors, that are more question I think.
But if you have the time to help me figure out why my event listeners are not registering in the application.

I've registered in app/config.php a service provider that is called "RabbitMQEventServiceProvider"

That file looks like this

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Nuwber\Events\BroadcastEventServiceProvider;

class RabbitMQEventServiceProvider extends BroadcastEventServiceProvider
{
    protected $listen = [
        'events' => [
            'App\Listeners\EventLogger',
        ],
    ];
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
        
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
        
    }
}

Then i have a simple listner

<?php

namespace App\Listeners;

use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class EventLogger
{
    /**
     * Create the event listener.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Handle the event.
     *
     * @param  object  $event
     * @return void
     */
    public function handle(string $event, array $payload)
    {
        //
        log($event);
        log($payload);
    }
}

What am I missing?

Thank you.

Config not properly read

Hello,
First of all to say a nice package & good work. I have an issue which I'm unable to solve:
Namely it seems that the package doesn't read the config/rabbitevents.php file & is always creating an AMQP connection with the fallback values provided in src/Amqp/Connection.php makeFactory function ie:

$factory = new AmqpConnectionFactory([
            'dsn' => $this->config->get('dsn'),
            'host' => $this->config->get('host', '127.0.0.1'),
            'port' => $this->config->get('port', 5672),
            'user' => $this->config->get('user', 'guest'),
            'pass' => $this->config->get('pass', 'guest'),
            'vhost' => $this->config->get('vhost', '/'),
            'ssl_on' => $this->config->get('ssl.is_enabled', false),
            'ssl_verify' => $this->config->get('ssl.verify_peer', true),
            'ssl_cacert' => $this->config->get('ssl.cafile'),
            'ssl_cert' => $this->config->get('ssl.local_cert'),
            'ssl_key' => $this->config->get('ssl.local_key'),
            'ssl_passphrase' => $this->config->get('ssl.passphrase'),
        ]);

When I try to dump $this->config I get an empty array. The only way I can get the package to work is if I change the fallback values inside this function in the package & after that everything works properly although I'm forced to use the events exchange which is set up as default in src/Amqp/TopicFactory.php
Versions:

nuwber/rabbitevents": "^6.0"
"php": "^7.4.7",
"laravel/framework": "^7.0",

I'm not sure if it is my fault in setting things up (shouldn't be as I've followed through the instructions you provided & everything works like it should when I change the fallback values) or the package itself.
Thanks in advance!

Give ability to explicitly set queue name in `rabbitevents:listen` command

Currently, when calling the rabbitevents:listen command, you can specify the name of the service and a list of events to listen to. Based on this information, the name of the queue in RabbitMQ is formed. This approach has a problem, which is that the queue name is not stable when the list of events changes (adding, removing new routing keys).

This leads to the following unpleasant side effects:

  1. After deploying new topology we have 2 queues (old and new) in RMQ. The old one can only be deleted manually.
  2. In multi-instance deployment, a situation may arise when the same event is processed from the new queue (in new instances) and the old queue (instances have not been updated yet). In case the processing lacks indepotency (unfortunately, it happens) we can get duplication. We may also face a situation when there are messages in old queue that we have not had time to process, but they are not in new queue.

My suggestion is to allow you to explicitly set queue name in the rabbitevents:listen command. This would solve at least the problems described above, as well as improve the readability (and documentation) of queues in the Management Console.

Support php 8

Do you have plans of supporting php 8 ?

Because now there is problems with dependency library: enqueue/amqp-lib

    - enqueue/amqp-lib[dev-master, 0.10.0, ..., 0.10.4] require php ^7.1.3 -> your php version (8.0.1) does not satisfy that requirement.
    - nuwber/rabbitevents v5.7 requires enqueue/amqp-lib ^0.10 -> satisfiable by enqueue/amqp-lib[0.10.0, 0.10.1, 0.10.4, 0.10.x-dev (alias of dev-master)].
    - enqueue/amqp-lib 0.10.x-dev is an alias of enqueue/amqp-lib dev-master and thus requires it to be installed too.
    - Root composer.json requires nuwber/rabbitevents ^5.7 -> satisfiable by nuwber/rabbitevents[v5.7].

Add Laravel 6 support.

It looks like to avoid such problems we need to create our own connector to RabbitMQ.

Configuration file is ignored

As commented here #72 (comment) I have a similar problem.

Within RabbitEventServiceProvider you have a register method which looks like this:

    public function register(): void
    {
        $config = $this->resolveConfig();

        $this->offerPublishing();

        $this->app->singleton(
            Context::class,
            function () use ($config) {
                return (new Connection($config))->createContext();
            }
        );
    }

The $config variable contains the correct configuration settings but the Context is never used. Adding a dd() before return (new Connection($config))->createContext(); is ignored.

Result:

PhpAmqpLib\Exception\AMQPIOException 

  stream_socket_client(): Unable to connect to tcp://127.0.0.1:5672 (Connection refused)

  at vendor/php-amqplib/php-amqplib/PhpAmqpLib/Wire/IO/StreamIO.php:108
    104▕                 $this->context
    105▕             );
    106▕             $this->throwOnError();
    107▕         } catch (\ErrorException $e) {
  ➜ 108▕             throw new AMQPIOException($e->getMessage());
    109▕         } finally {
    110▕             $this->restoreErrorHandler();
    111▕         }
    112▕

      +23 vendor frames 
  24  artisan:37
      Illuminate\Foundation\Console\Kernel::handle()

I use v6 because v7@beta is not installable in my project.

EDIT: mixture of packages caused this issue.

Fanout support?

I know this has been asked before, a year ago. But is there any plan to support the exchange type fanout again in the near future? Thanks!

[QUESTION]: Deploying to productioin

Hi!

First of all, thanks for this package. I've been using it for a couple days now across various microservices and it works very nicely.

I'm wondering though, how you suggest deploying this to production? Within our platform we're talking about thousands of events across services. Having to provide a event.name within the php artisan rabbitevents:listen command just seems 'unrealistic' (for lack of a better word) in this scenario.

What would be your thoughts on this, and would you perhaps be open to a merge request from me for such functionality?

Cheers!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.