vyuldashev / laravel-queue-rabbitmq

RabbitMQ driver for Laravel Queue. Supports Laravel Horizon.
MIT License
1.87k stars 375 forks source link

Target class [] does not exist - BindingResolutionException - queue messages get consumed - job seems to fail #291

Closed johnnemo closed 4 years ago

johnnemo commented 4 years ago

Laravel Version: 6.7.0 Package Version: 9.0 RabbitMQ Version: 3.8.2

Describe the bug The queue seems to be executed correctly but when I run php artisan queue:work but:

  1. the terminal displays:

[2019-12-16 15:36:31][] Processing: [2019-12-16 15:36:31][] Failed:

  1. The output in the laravel logs is: local.ERROR: Target class [] does not exist. {"exception":"[object] (Illuminate\Contracts\Container\BindingResolutionException(code: 0): Target class [] does not exist. at /vendor/laravel/framework/src/Illuminate/Container/Container.php:805) [stacktrace]

  2. In addition the failed_jobs table gets filled with the current job error and so, even if I can log the queue body of the message and the message seems consumed and Acked in the queue-end the job seems as failed eventually.

  3. This happens for the default worker as well as a custom one I created which extends the VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue class (needed to change the connect method and replace "instanceof" with "is_subclass_of" as suggested in https://github.com/vyuldashev/laravel-queue-rabbitmq/pull/247)

In any case, even if I leave the connector untouched and use the default worker the result is the same...

Note that this does not happen when I dispatch the job but only for the artisan queue:work

connection configuration 'rabbitmq' => [

        'driver' => 'rabbitmq',

        /*
         * Set to "horizon" if you wish to use Laravel Horizon.
         */
        'worker' =>  'worker' => env('RABBITMQ_WORKER', 'default'),,

        'dsn' => env('RABBITMQ_DSN', null),

        'factory_class' => Enqueue\AmqpLib\AmqpConnectionFactory::class,

        'host' => env('RABBITMQ_HOST', '127.0.0.1'),
        'port' => env('RABBITMQ_PORT', 5672),

        'vhost' => env('RABBITMQ_VHOST', '/'),
        'login' => env('RABBITMQ_LOGIN', 'guest'),
        'password' => env('RABBITMQ_PASSWORD', 'guest'),

        'queue' => env('RABBITMQ_QUEUE', 'default'),

        'options' => [

            'exchange' => [

                'name' => env('RABBITMQ_EXCHANGE_NAME'),

                'declare' => env('RABBITMQ_EXCHANGE_DECLARE', true),

                'type' => env('RABBITMQ_EXCHANGE_TYPE', \Interop\Amqp\AmqpTopic::TYPE_TOPIC),
                'passive' => env('RABBITMQ_EXCHANGE_PASSIVE', false),
                'durable' => env('RABBITMQ_EXCHANGE_DURABLE', true),
                'auto_delete' => env('RABBITMQ_EXCHANGE_AUTODELETE', false),
                'arguments' => env('RABBITMQ_EXCHANGE_ARGUMENTS'),
            ],

            'queue' => [

                'declare' => env('RABBITMQ_QUEUE_DECLARE', true),

                'bind' => env('RABBITMQ_QUEUE_DECLARE_BIND', true),

                'passive' => env('RABBITMQ_QUEUE_PASSIVE', false),
                'durable' => env('RABBITMQ_QUEUE_DURABLE', true),
                'exclusive' => env('RABBITMQ_QUEUE_EXCLUSIVE', false),
                'auto_delete' => env('RABBITMQ_QUEUE_AUTODELETE', false),
                'arguments' => env('RABBITMQ_QUEUE_ARGUMENTS'),
            ],
        ]

Queue Details The type of the queue is "topic". The queue is running in the local machine, while the test application lives inside the Homestead VM. Thus, to access the queue the url needs to be 10.0.2.2.

env configuration options RABBITMQ_HOST=10.0.2.2 RABBITMQ_QUEUE=q.user.created RABBITMQ_EXCHANGE_NAME=user.created

I would appreciate your help..

P.S.:Thank you @vyuldashev et all for your efforts.

vyuldashev commented 4 years ago

Did you disable auto-discovery?

johnnemo commented 4 years ago

No.. Should I? I have set up a fresh Laravel installation and nothing more. I did not change the composer.json as well so the auto-discovery does its job..

The error is almost the same with version 9.1 and 10.. The difference in v10 of the package is that the failed_jobs table does not get filled up

vyuldashev commented 4 years ago

Show your config/queue.php

johnnemo commented 4 years ago

For the 9.* version it is already in the description.

V10 queue.php:

<?php

return [

    /*
    |--------------------------------------------------------------------------
    | Default Queue Connection Name
    |--------------------------------------------------------------------------
    |
    | Laravel's queue API supports an assortment of back-ends via a single
    | API, giving you convenient access to each back-end using the same
    | syntax for every one. Here you may define a default connection.
    |
    */

    'default' => env('QUEUE_CONNECTION', 'sync'),

    /*
    |--------------------------------------------------------------------------
    | Queue Connections
    |--------------------------------------------------------------------------
    |
    | Here you may configure the connection information for each server that
    | is used by your application. A default configuration has been added
    | for each back-end shipped with Laravel. You are free to add more.
    |
    | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null"
    |
    */

    'connections' => [

        'rabbitmq' => [

            'driver' => 'rabbitmq',
            'queue' => env('RABBITMQ_QUEUE', 'default'),
            'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class,
            'worker' => env('RABBITMQ_WORKER', 'default'),

            'hosts' => [
                [
                    'host' => env('RABBITMQ_HOST', '127.0.0.1'),
                    'port' => env('RABBITMQ_PORT', 5672),
                    'user' => env('RABBITMQ_USER', 'guest'),
                    'password' => env('RABBITMQ_PASSWORD', 'guest'),
                    'vhost' => env('RABBITMQ_VHOST', '/'),
                ],
            ],

            'options' => [
                'exchange' => [

                    'name' => env('RABBITMQ_EXCHANGE_NAME'),

                    /*
                     * Determine if exchange should be created if it does not exist.
                     */

                    'declare' => env('RABBITMQ_EXCHANGE_DECLARE', true),

                    /*
                     * Read more about possible values at https://www.rabbitmq.com/tutorials/amqp-concepts.html
                     */

                    'type' => env('RABBITMQ_EXCHANGE_TYPE', \PhpAmqpLib\Exchange\AMQPExchangeType::TOPIC),
                ],
                'ssl_options' => [
                    'cafile' => env('RABBITMQ_SSL_CAFILE', null),
                    'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
                    'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
                    'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
                    'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
                ],
            ]

        ],

        'sync' => [
            'driver' => 'sync',
        ],

        'database' => [
            'driver' => 'database',
            'table' => 'jobs',
            'queue' => 'default',
            'retry_after' => 90,
        ],

        'beanstalkd' => [
            'driver' => 'beanstalkd',
            'host' => 'localhost',
            'queue' => 'default',
            'retry_after' => 90,
            'block_for' => 0,
        ],

        'sqs' => [
            'driver' => 'sqs',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'),
            'queue' => env('SQS_QUEUE', 'your-queue-name'),
            'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
        ],

        'redis' => [
            'driver' => 'redis',
            'connection' => 'default',
            'queue' => env('REDIS_QUEUE', 'default'),
            'retry_after' => 90,
            'block_for' => null,
        ],

    ],

    /*
    |--------------------------------------------------------------------------
    | Failed Queue Jobs
    |--------------------------------------------------------------------------
    |
    | These options configure the behavior of failed queue job logging so you
    | can control which database and table are used to store the jobs that
    | have failed. You may change them to any database / table you wish.
    |
    */

    'failed' => [
        'driver' => env('QUEUE_FAILED_DRIVER', 'database'),
        'database' => env('DB_CONNECTION', 'mysql'),
        'table' => 'failed_jobs',
    ],

];
vyuldashev commented 4 years ago

What's the value of QUEUE_CONNECTION?

johnnemo commented 4 years ago

The following env variables are set (10.0.2.2 is for accessing the local rabbit queue container from the VM - the error is the same when running both in the same machine and playing with 127.0.0.1):

RABBITMQ_HOST=10.0.2.2 RABBITMQ_QUEUE=q.user.created RABBITMQ_EXCHANGE_NAME=user.created QUEUE_CONNECTION=rabbitmq

ThanhSonITNIC commented 4 years ago

same problem

vyuldashev commented 4 years ago

Try v10.2.0

adm-bome commented 4 years ago

As @vyuldashev pointed out... use the latest version v10.2.0

This issue will shortly be closed. Please do not hesitate to comment on this issue, when you still have the same issues.

daeehamid commented 3 years ago

I've same problem

    "require": {
        "php": "^7.2",
        "laravel/lumen-framework": "^6.0",
        "vladimir-yuldashev/laravel-queue-rabbitmq": "^10.2"
    },
ReflectionException: Class  does not exist in C:\Projects\RabbitMq\rabbitmqLaravel\vendor\laravel\framework\src\Illuminate\Container\Container.php:803

and my config file

'rabbitmq' => [

            'driver' => 'rabbitmq',
            'queue' => env('RABBITMQ_QUEUE', 'default'),
            'connection' => PhpAmqpLib\Connection\AMQPLazyConnection::class,

            'hosts' => [
                [
                    'host' => env('RABBITMQ_HOST', '************'),
                    'port' => env('RABBITMQ_PORT', 5672),
                    'user' => env('RABBITMQ_USER', '****'),
                    'password' => env('RABBITMQ_PASSWORD', '***********'),
                    'vhost' => env('RABBITMQ_VHOST', '/'),
                ],
            ],

            'options' => [
                'ssl_options' => [
                    'cafile' => env('RABBITMQ_SSL_CAFILE', null),
                    'local_cert' => env('RABBITMQ_SSL_LOCALCERT', null),
                    'local_key' => env('RABBITMQ_SSL_LOCALKEY', null),
                    'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
                    'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
                ],
            ],

            /*
             * Set to "horizon" if you wish to use Laravel Horizon.
             */
            'worker' => env('RABBITMQ_WORKER', 'default'),

        ],

when I run php artisan rabbitmq:consume i've got this error in failed_job table

can anyone help me to solve this problem !? tnx

adm-bome commented 3 years ago

The job class must exist and php has to know about it.

This is not a library issue.

daeehamid commented 3 years ago

@adm-bome I did all this and checked, but no difference was found :(

adm-bome commented 3 years ago

@daeehamid Can you post the payload of the message in rabbitMQ

daeehamid commented 3 years ago

@adm-bome

My failed_job table https://ibb.co/Tk6D1GK

adm-bome commented 3 years ago

Realy! RTFM, this is not a forum, on how queueing works. Never the less....

Your payload is wrong. Laravel does not understand tessssssst. That's not an existing class, and laravel is searching for a class to execute as Job and pass some parameters to.

Please read laravel's documentation. Or create a correct payload for laravel to work with. There are more closed issues discussing the payload.

daeehamid commented 3 years ago

@adm-bome Teeeeeeessssst is my message , sending from publisher (based on rabbitmq toturial)

$connection = new AMQPStreamConnection('******', 5672, 'USERNAME', 'PASSWORD');
$channel = $connection->channel();

$channel->queue_declare('default', false, false, false, false);

$msg = new AMQPMessage('Teeeeeeessssst!');
$channel->basic_publish($msg, '', 'default');

echo " [x] Sent 'Teeeeeeessssst!'\n";

$channel->close();
$connection->close();

I just ran php artisan rabbitmq:consume in laravel and set configuration laravel-queue-rabbitmq documentation is very incomplete!!! :|

adm-bome commented 3 years ago

The documentation is not incomplete. This library follows the laravel's queuing concept. This is just a driver for the queueAPI to make use of rabbitMQ.

You have to create messages from within laravel. Or you can create a message on your own, but with an payload laravel understands.

Or create your own worker, if your stuck with the payload 'Teeeeeesssssst'.

In short... Follow the documentation from https://www.laravel.com

and see this issue #338