Appearance
Message Queues
Handy tool for distributing work across multiple systems.
Very nice overview of the concept:
https://www.cloudamqp.com/blog/what-is-message-queuing.html
What is message queuing? - CloudAMQP
More technical version:
https://www.ibm.com/cloud/learn/message-queues
Message Queues: An Introduction | IBM
Many solutions available
https://github.com/topics/job-queue
job-queue · GitHub Topics
https://github.com/topics/background-jobs
background-jobs · GitHub Topics
https://github.com/topics/task-queue
task-queue · GitHub Topics · GitHub
https://github.com/topics/worker-pool
worker-pool · GitHub Topics · GitHub
Celery
https://github.com/topics/celery
celery · GitHub Topics
https://github.com/celery/celery
celery/celery: Distributed Task Queue (development branch)
https://docs.celeryq.dev/en/stable/getting-started/first-steps-with-celery.html#keeping-results
First Steps with Celery — Celery 5.3.1 documentation
https://docs.celeryq.dev/en/stable/userguide/configuration.html#std-setting-result_backend
Configuration and defaults — Celery 5.3.1 documentation
https://docs.celeryq.dev/en/stable/userguide/configuration.html#conf-rpc-result-backend
Configuration and defaults — Celery 5.3.1 documentation
https://duckduckgo.com/?t=ffab&q=celery+chained+events&ia=web
celery chained events at DuckDuckGo
https://stackoverflow.com/questions/55279820/running-chained-celery-tasks-at-specific-times
python - Running Chained Celery tasks at specific times - Stack Overflow
RQ
https://github.com/rq/rq
rq/rq: Simple job queues for Python
https://duckduckgo.com/?t=ffab&q=using+redis+as+a+task+queue+python&ia=web
using redis as a task queue python at DuckDuckGo
https://realpython.com/flask-by-example-implementing-a-redis-task-queue/
Flask by Example – Implementing a Redis Task Queue – Real Python
RabbitMQ
Seems to be a favorite. Has the ability to be accessed from many different languages, which is a limitation of bullmq (js only).
https://duckduckgo.com/?t=ffab&q=amqp&ia=web
amqp at DuckDuckGo
https://www.amqp.org/
Home | AMQP
https://duckduckgo.com/?t=ffab&q=celery+python&ia=web
celery python at DuckDuckGo
https://pypi.org/project/celery/
celery · PyPI
https://docs.celeryq.dev/en/latest/
Celery - Distributed Task Queue — Celery 5.3.0b1 documentation
https://docs.celeryq.dev/en/latest/getting-started/introduction.html
Introduction to Celery — Celery 5.3.0b1 documentation
https://rabbitmq.com/
Messaging that just works — RabbitMQ
https://rabbitmq.com/#community
Messaging that just works — RabbitMQ
https://github.com/rabbitmq?q=rabbitmq
RabbitMQ
https://github.com/rabbitmq/rabbitmq-server
rabbitmq/rabbitmq-server: Open source RabbitMQ: core server and tier 1 (built-in) plugins
https://github.com/topics/amqp
amqp · GitHub Topics
https://github.com/topics/mqtt
mqtt · GitHub Topics
https://github.com/emqx/emqx
emqx/emqx: The most scalable open-source MQTT broker for IoT
https://github.com/mqttjs/MQTT.js
mqttjs/MQTT.js: The MQTT client for Node.js and the browser
https://mqtt.org/
MQTT - The Standard for IoT Messaging
https://duckduckgo.com/?t=ffab&q=redis+message+queue&ia=web
redis message queue at DuckDuckGo
https://hevodata.com/learn/redis-message-queue/
Redis Message Queue: 4 Easy Steps to Build a Message Broker - Learn | Hevo
https://duckduckgo.com/?t=ffab&q=redis+vs+rabbitmq&ia=web
redis vs rabbitmq at DuckDuckGo
https://stackoverflow.com/questions/29539443/redis-vs-rabbitmq-as-a-data-broker-messaging-system-in-between-logstash-and-elas
Redis Vs RabbitMQ as a data broker/messaging system in between Logstash and elasticsearch - Stack Overflow
https://www.educba.com/rabbitmq-vs-redis/
RabbitMQ vs Redis | Top 9 Differences You Should Know
https://duckduckgo.com/?t=ffab&q=celery+vs+bull&ia=web
celery vs bull at DuckDuckGo
https://stackoverflow.com/questions/28470796/equivalent-of-celery-in-node-js
node.js - Equivalent of Celery in Node JS - Stack Overflow
https://thenewstack.io/how-kafka-and-redis-solve-stream-processing-challenges/
How Kafka and Redis Solve Stream-Processing Challenges – The New Stack
Bull & BullMQ
Javascript original. Tried and true. Good if you need to support platforms that lag behind from the latest version of Node.
https://github.com/OptimalBits/bull
Latest version. Written in Typescript (but does not require using Typescript).
https://github.com/taskforcesh/bullmq
Bull queues can be used by any javascript application easily.
They only require access to the Redis store being used to coordinate all of the workers.
Nice to have an easy to include system, especially if it works in javascript.
https://docs.bullmq.io/what-is-bullmq
What is BullMQ - BullMQ
https://docs.bullmq.io/
Quick Start - BullMQ
yarn add bullmq
yarn add bullmq
Connections
Be sure to configure where your redis server is when using the library (and make sure that the location running the code can access the redis server)
https://docs.bullmq.io/guide/connections
import { Queue, Worker } from 'bullmq'
// Create a new connection in every instance
const myQueue = new Queue('myqueue', { connection: {
host: "myredis.taskforce.run",
port: 32856
}});
const myWorker = new Worker('myworker', async (job)=>{}, { connection: {
host: "myredis.taskforce.run",
port: 32856
}});
import { Queue, Worker } from 'bullmq'
// Create a new connection in every instance
const myQueue = new Queue('myqueue', { connection: {
host: "myredis.taskforce.run",
port: 32856
}});
const myWorker = new Worker('myworker', async (job)=>{}, { connection: {
host: "myredis.taskforce.run",
port: 32856
}});
Jobs
One nice thing about using Bull is that it's easy to kick off jobs via your API, especially if you're already running javascript there (e.g. Express)
https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queueadd
"Boilerplate Request" is the name of the job
without providing, displays show "default" for every job
however, the job queue needs to leverage that value too
// .add("Boilerplate Request", req.body)
js
var express = require("express");
var router = express.Router();
var config = require("../config");
var Queue = require("bull");
const boilerplateQueue = new Queue("boilerplate", config.redis.url);
router.post("/new", (req, res, next) => {
console.log("CREATING NEW BOILERPLATE JOB", req.body);
boilerplateQueue
// .add("Boilerplate Request", req.body)
.add(req.body)
.then((created) => {
res.json(created);
})
.catch((err) => {
next(err);
});
});
module.exports = router;
var express = require("express");
var router = express.Router();
var config = require("../config");
var Queue = require("bull");
const boilerplateQueue = new Queue("boilerplate", config.redis.url);
router.post("/new", (req, res, next) => {
console.log("CREATING NEW BOILERPLATE JOB", req.body);
boilerplateQueue
// .add("Boilerplate Request", req.body)
.add(req.body)
.then((created) => {
res.json(created);
})
.catch((err) => {
next(err);
});
});
module.exports = router;
Child Processes
Often useful to leverage a child process for calling jobs Child Processes
Docker
It's a good idea to run your redis store in a separate container, but the bull que and even the bull-board can be added in the API.
Possible to run all the necessary infrastructure under docker. In docker-compose.yml
, add the following containers and volumes
https://github.com/Deadly0/bull-board-docker
redis:
container_name: redis
image: redis:5.0-alpine
restart: unless-stopped
ports:
- 6379:6379
volumes:
# - db_redis:/data
- ./db_redis:/data
redis:
container_name: redis
image: redis:5.0-alpine
restart: unless-stopped
ports:
- 6379:6379
volumes:
# - db_redis:/data
- ./db_redis:/data
version: "3"
services:
redis:
container_name: redis
image: redis:5.0-alpine
restart: unless-stopped
ports:
- 6379:6379
volumes:
- db_redis:/data
bullboard:
container_name: bullboard
image: deadly0/bull-board
restart: unless-stopped
ports:
- 9998:3000
environment:
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: example-password
REDIS_USE_TLS: 'false'
BULL_PREFIX: bull
depends_on:
- redis
volumes:
db_redis:
external: false
version: "3"
services:
redis:
container_name: redis
image: redis:5.0-alpine
restart: unless-stopped
ports:
- 6379:6379
volumes:
- db_redis:/data
bullboard:
container_name: bullboard
image: deadly0/bull-board
restart: unless-stopped
ports:
- 9998:3000
environment:
REDIS_HOST: redis
REDIS_PORT: 6379
REDIS_PASSWORD: example-password
REDIS_USE_TLS: 'false'
BULL_PREFIX: bull
depends_on:
- redis
volumes:
db_redis:
external: false
References
https://duckduckgo.com/?t=ffab&q=bull+mq&ia=web
bull mq at DuckDuckGo
https://docs.bullmq.io/what-is-bullmq
What is BullMQ - BullMQ
https://docs.bullmq.io/
Quick Start - BullMQ
https://docs.bullmq.io/what-is-bullmq
What is BullMQ - BullMQ
https://github.com/taskforcesh/bullmq
taskforcesh/bullmq: BullMQ - Premium Message Queue for NodeJS based on Redis
https://docs.bullmq.io/guide/workers
Workers - BullMQ
https://docs.bullmq.io/guide/connections
Connections leverage ioredis for talking to the Redis database. Note that the version of Redis needs to be 5.0 or higher.
Connections - BullMQ
https://github.com/luin/ioredis/blob/master/API.md
ioredis/API.md at master · luin/ioredis
Bullboard
https://github.com/felixmosh/bull-board
GitHub - felixmosh/bull-board: 🎯 Queue background jobs inspector
Install
Seems best to integrate with an existing express stack
but also possible to put it in its own container if that works better
yarn add @bull-board/express
yarn add @bull-board/express
const express = require('express')
const Queue = require('bull')
const { createBullBoard } = require('@bull-board/api')
const { BullAdapter } = require('@bull-board/api/bullAdapter')
const { ExpressAdapter } = require('@bull-board/express')
const someQueue = new Queue('someQueueName')
const someOtherQueue = new Queue('someOtherQueueName')
const serverAdapter = new ExpressAdapter();
const { addQueue, removeQueue, setQueues, replaceQueues } = createBullBoard({
queues: [
new BullAdapter(someQueue),
new BullAdapter(someOtherQueue),
],
serverAdapter:serverAdapter
})
const app = express()
serverAdapter.setBasePath('/admin/queues')
app.use('/admin/queues', serverAdapter.getRouter());
// other configurations of your server
const express = require('express')
const Queue = require('bull')
const { createBullBoard } = require('@bull-board/api')
const { BullAdapter } = require('@bull-board/api/bullAdapter')
const { ExpressAdapter } = require('@bull-board/express')
const someQueue = new Queue('someQueueName')
const someOtherQueue = new Queue('someOtherQueueName')
const serverAdapter = new ExpressAdapter();
const { addQueue, removeQueue, setQueues, replaceQueues } = createBullBoard({
queues: [
new BullAdapter(someQueue),
new BullAdapter(someOtherQueue),
],
serverAdapter:serverAdapter
})
const app = express()
serverAdapter.setBasePath('/admin/queues')
app.use('/admin/queues', serverAdapter.getRouter());
// other configurations of your server
Docker
https://github.com/Deadly0/bull-board-docker
https://github.com/Deadly0/bull-board-docker/blob/master/Dockerfile
bull-board-docker/Dockerfile at master · Deadly0/bull-board-docker · GitHub
https://github.com/Deadly0/bull-board-docker/tree/master/src
bull-board-docker/src at master · Deadly0/bull-board-docker · GitHub
https://github.com/topics/message-queue
Agenda
https://github.com/agenda/agenda
agenda/agenda: Lightweight job scheduling for Node.js
See Also
https://duckduckgo.com/?t=ffab&q=message+queuing&ia=web message queuing at DuckDuckGo