DEV Community 👩‍💻👨‍💻

Sergey Telpuk
Sergey Telpuk

Posted on

Send `Job` from Node-app to PHP-app via Queue.

Hello guys!

In this article, I wanna share one very interesting and fast solution to executing jobs onto PHP side. Spiral Framework allows us to use jobs in an easy way. The whole done repository is here.

At my contrived app, Nodejs(Nestjs) sends the job to PHP.
Look at Nodejs job:

import {IJob} from "../interfaces/job.interface";

export class Ping implements IJob {
    readonly JOB = 'App.Job.Amqp.Ping'; //namespace(path) to job on PHP side

        private readonly value: string
    ) {




export interface IJob {
    JOB: string;

This dto will be sent to PHP-app via the queue (RabbitMQ).
Look at JobPusherService:

import {Injectable} from "@nestjs/common";
import uuid4 from "uuid/v4";
import {IJob} from "./interfaces/job.interface";
import amqp from "amqplib";

export class JobPusherService {
    readonly CONNECT = 'amqp://rabbit:rabbit@rabbitmq:5672';

    async send(job: IJob) {
        const server = await amqp.connect(this.CONNECT);
        const channel = await server.createChannel();

        const jobExecuting = job.JOB;

        delete job.JOB;

                headers: {
                    "rr-id": uuid4(),
                    "rr-job": jobExecuting,
                    "rr-attempt": 1000_000_000_000,
                    "rr-maxAttempts": 1000_000_000_000,
                    "rr-timeout": 1000_000_000_000,
                    "rr-delay": 1000_000_000_000,
                    "rr-retryDelay": 1000_000_000_000,

That one wraps up dto with necessary headers and push it into the queue.

Move up to PHP-app. Underhood, Spiral Framework uses roadrunner. All necessary configuration is at .rr.yml:

# http service configuration.

    # enable HTTP/2, only with TSL, enabled by default
    enabled: true

    command: "php app.php"

    # max transfer channels, default 128
  maxConcurrentStreams: 128

    # force redirect to https connection
    redirect: true

    # custom https port (default 443)
    port:  443

    # ssl cert
    cert: ./certs/server.crt

    # ssl private key
    key: ./certs/server.key

# queue and jobs
    addr: amqp://rabbit:rabbit@rabbitmq:5672/

    app-job-amqp*.pipeline: amqp

      broker: amqp
      queue:  contrived_queue

  consume: ["amqp"]

    command: "php app.php"
    pool.numWorkers: 10

# serve static files
  dir:    "public"
  forbid: [".php", ".htaccess"]

# control the max memory usage
    http.maxMemory: 100
    jobs.maxMemory: 100

  listen: tcp://php-app:6001 #for watcher

For more details information look at this doc.

Job looks like:

 * (QueueInterface)->push(new PingJob(["value"=>"my value"]));
class Ping extends AbstractJob
     * @param string $id
     * @param string $value
    public function do(string $id, string $value)

        // do something
        error_log("pong by {$id}, {$value}");

As you can see, It's very easy and quite fast to execute jobs.

To be continued...

Top comments (0)

In defense of the modern web

I expect I'll annoy everyone with this post: the anti-JavaScript crusaders, justly aghast at how much of the stuff we slather onto modern websites; the people arguing the web is a broken platform for interactive applications anyway and we should start over;

React users; the old guard with their artisanal JS and hand authored HTML; and Tom MacWright, someone I've admired from afar since I first became aware of his work on Mapbox many years ago. But I guess that's the price of having opinions.