Skip to content

Exchange custom payloads between services instead of Job tasks #611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
CheesyTech opened this issue Dec 10, 2024 · 4 comments
Open

Exchange custom payloads between services instead of Job tasks #611

CheesyTech opened this issue Dec 10, 2024 · 4 comments
Assignees

Comments

@CheesyTech
Copy link

Hi. I was considering the package as a means to interact with RabbitMQ, but found a nuance.
The package exchanges not pure payload, but whole laravel-job. Are there any plans to modernize the package so that it is possible to exchange pure payloads as well?
My motivation is that for Laravel and Golang interaction I will have to write a wrapper for Laravel on the Go side, which is not very productive.
Is there such a possibility now?

@ALTELMA
Copy link

ALTELMA commented Dec 23, 2024

Try to explore on this. Not quite sure it related to your issue or not.

@abelschooleman
Copy link

For the consuming side you can create a custom job class as mentioned by @ALTELMA. For publishing you can just use the pushRaw method of the Queue facade with any payload you need.

That would look something like this:

Queue::connection('rabbitmq')->pushRaw($message->toJson(), 'queue_name_if_needed');

@CheesyTech
Copy link
Author

CheesyTech commented Jan 13, 2025

I've looked into the package a bit and the first solution that would work for me is to rewrite the default createPayload function in VladimirYuldashev\LaravelQueueRabbitMQ\Queue like this:

public function createPayload($job, $queue, $data = ''): string
 {
      if ($job instanceof JobPayloadContract) {
           return $job->payload();
      }

        return parent::createPayload($job, $queue, $data);
}

Contract example:
interface JobPayloadContract { public function payload(): string; }
Job example:

 class CreatePaymentLinkJob implements ShouldQueue, JobPayloadContract {

    public function __construct(
        private readonly string $orderId,
        private readonly CurrencyAlpha3 $currency,
    )
    {
    }
   
    public function payload(): string
    {
       // or use reflection for make payload
       return json_encode([
                   order_id' => $this->orderId,
                   currency' => $this->currency->value
        ]);
      }
}

However, as far as I understand it is not enough and it will be necessary to implement your RabbitMQQQueue completely, because to leave compatibility with Horizon (it is a priority when choosing this package, autoscaling) need additional parameters that are in Laravel\Horizon\JobPayload.

@Ontr
Copy link

Ontr commented Feb 23, 2025

Sending the payload as a fully packaged task happens in the default queuing mode, where RabbitMQ acts as the queue. To send a custom payload, the Job should be modified to run directly (without "implements ShouldQueue"). In this case, the sending logic is placed inside handle(), making the job itself responsible for sending the message to RabbitMQ.

pushRaw accepts "exchange", "exchange_type", and "persistent". However, this method lacks built-in support for "priority". Currently, this can be bypassed by adding "attempts" and setting 'prioritize_delayed' => true, or by including "data->command->priority" in the sent payload data - see method createMessage in VladimirYuldashev\LaravelQueueRabbitMQ\Queue\RabbitMQQueue).

namespace App\Jobs;

use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Queue;

class myJob
{
    use Queueable;

    /**
     * Create a new job instance.
     */
    public function __construct(private $data)
    {
    }

    /**
     * Execute the job.
     */
    public function handle(): void
    {
        $message = json_encode($this->data);

        Queue::connection('rabbitmq')->pushRaw(
            $message,
            'my_exchange_key', //queue
            [
                'exchange' => 'my_exchange',
                'exchange_type' => 'topic',
                'persistent' => true,
                'attempts' => 7
            ]
        );

    }
}

queue.php

    'rabbitmq' => [

        'driver' => 'rabbitmq',
        'hosts' => [
            [
            'host' => env('RABBITMQ_HOST'),
            'port' => env('RABBITMQ_PORT'),
            'user' => env('RABBITMQ_USER'),
            'password' => env('RABBITMQ_PASSWORD'),
            'vhost' => env('RABBITMQ_VHOST', '/'),
            ],
        ],
        'secure' => true,
        'options' => [
            'ssl_options' => [
                'cafile' => env('RABBITMQ_SSL_CAFILE', null),
                'verify_peer' => env('RABBITMQ_SSL_VERIFY_PEER', true),
                'passphrase' => env('RABBITMQ_SSL_PASSPHRASE', null),
            ],
            'queue' => [
                'prioritize_delayed' =>  true,
                'queue_max_priority' => 10,
            ],
        ],
   ],

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants