Skip to content

Commit eeb06a7

Browse files
authored
Merge pull request #114 from DefangLabs/110-bullmq-bull-board-redis-sample
BullMQ Sample
2 parents 878579d + 6cbfc8b commit eeb06a7

23 files changed

+3351
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: deploy
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
- pr-test/*
8+
9+
concurrency:
10+
group: deploy
11+
cancel-in-progress: false
12+
13+
jobs:
14+
deploy:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: read
18+
id-token: write
19+
20+
steps:
21+
- name: Checkout Repo
22+
uses: actions/checkout@v4
23+
24+
- name: Install defang
25+
run: . <(curl -Ls https://s.defang.io/install)
26+
27+
- name: Login to Defang
28+
run: defang login
29+
30+
- name: Deploy
31+
run: defang compose up -v --detach
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# BullMQ & BullBoard & Redis
2+
3+
This sample project demonstrates how to deploy a BullMQ message queue on top of managed Redis with a queue processor and a dashboard to monitor the queue.
4+
5+
Once your app is up and running you can go to the `/board` route for the `board` service to see the Bull Board dashboard and use the username `admin` and the password you set to log in (see [Deploying](#deploying)).
6+
7+
To add a job to the queue, you can go to the `/add` route of the `api` service. This will use some default values so you can test things out. You can also see an example of a post request in the [sample http request](./api/add.test.http) file.
8+
9+
The `worker` service is the queue processor that will process the jobs added to the queue. You can see in the `compose.yaml` file that the `worker` service is set to scale to 2 instances. This means that there will be 2 workers processing jobs from the queue. You can set this to your desired number of workers, but we wanted to show how you can increase the number of workers to handle more jobs.
10+
11+
12+
## Prerequisites
13+
14+
1. Download <a href="https://github.com/defang-io/defang">Defang CLI</a>
15+
2. (optional) If you are using <a href="https://docs.defang.io/docs/concepts/defang-byoc">Defang BYOC</a>, make sure you have properly <a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html">authenticated your AWS account</a>.
16+
17+
## Deploying
18+
19+
1. Open the terminal and type `defang login`
20+
2. Run `defang config set BOARD_PASSWORD` to set the password for the BullBoard dashboard.
21+
3. Type `defang compose up` in the CLI.
22+
4. Your app will be running within a few minutes.
23+
24+
25+
## Local Development
26+
27+
1. Run `docker compose -f compose.dev.yaml up`
28+
29+
---
30+
31+
Title: BullMQ & BullBoard & Redis
32+
33+
Short Description: A sample project with BullMQ, BullBoard, and Redis.
34+
35+
Tags: BullMQ, BullBoard, Redis, Express, Node.js, Message Queue
36+
37+
Languages: nodejs, javascript
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# Logs
2+
logs
3+
*.log
4+
5+
# Runtime data
6+
pids
7+
*.pid
8+
*.seed
9+
*.pid.lock
10+
11+
# Directory for instrumented libs generated by jscoverage/JSCover
12+
lib-cov
13+
14+
# Coverage directory used by tools like istanbul
15+
coverage
16+
17+
# nyc test coverage
18+
.nyc_output
19+
20+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21+
.grunt
22+
23+
# node-waf configuration
24+
.lock-wscript
25+
26+
# Compiled binary addons (https://nodejs.org/api/addons.html)
27+
build/Release
28+
29+
# Dependency directories
30+
node_modules/
31+
jspm_packages/
32+
33+
# TypeScript v1.x
34+
*.ts~
35+
*.tsx~
36+
37+
# Optional npm cache directory
38+
.npm
39+
40+
# Optional eslint cache
41+
.eslintcache
42+
43+
# Microbundle cache
44+
.rpt2_cache/
45+
.rts2_cache_cjs/
46+
.rts2_cache_es/
47+
.rts2_cache_umd/
48+
49+
# Optional REPL history
50+
.node_repl_history
51+
52+
# Output of 'npm pack'
53+
*.tgz
54+
55+
# Yarn Integrity file
56+
.yarn-integrity
57+
58+
# dotenv environment variables file
59+
.env
60+
.env.test
61+
62+
# parcel-bundler cache (https://parceljs.org/)
63+
.cache
64+
65+
# next.js build output
66+
.next
67+
68+
# nuxt.js build / generate output
69+
.nuxt
70+
dist/
71+
72+
# vuepress build output
73+
.vuepress/dist
74+
75+
# Serverless directories
76+
.serverless/
77+
78+
# FuseBox cache
79+
.fusebox/
80+
81+
# DynamoDB Local files
82+
.dynamodb/
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
8+
# Runtime data
9+
pids
10+
*.pid
11+
*.seed
12+
*.pid.lock
13+
14+
# Directory for instrumented libs generated by jscoverage/JSCover
15+
lib-cov
16+
17+
# Coverage directory used by tools like istanbul
18+
coverage
19+
20+
# nyc test coverage
21+
.nyc_output
22+
23+
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
24+
.grunt
25+
26+
# Bower dependency directory (https://bower.io/)
27+
bower_components
28+
29+
# node-waf configuration
30+
.lock-wscript
31+
32+
# Compiled binary addons (https://nodejs.org/api/addons.html)
33+
build/Release
34+
35+
# Dependency directories
36+
node_modules/
37+
jspm_packages/
38+
39+
# TypeScript v1.x
40+
*.ts~
41+
*.tsx~
42+
43+
# Optional npm cache directory
44+
.npm
45+
46+
# Optional eslint cache
47+
.eslintcache
48+
49+
# Microbundle cache
50+
.rpt2_cache/
51+
.rts2_cache_cjs/
52+
.rts2_cache_es/
53+
.rts2_cache_umd/
54+
55+
# Optional REPL history
56+
.node_repl_history
57+
58+
# Output of 'npm pack'
59+
*.tgz
60+
61+
# Yarn Integrity file
62+
.yarn-integrity
63+
64+
# dotenv environment variables file
65+
.env
66+
.env.test
67+
68+
# parcel-bundler cache (https://parceljs.org/)
69+
.cache
70+
71+
# next.js build output
72+
.next
73+
74+
# nuxt.js build / generate output
75+
.nuxt
76+
dist/
77+
78+
# vuepress build output
79+
.vuepress/dist
80+
81+
# Serverless directories
82+
.serverless/
83+
84+
# FuseBox cache
85+
.fusebox/
86+
87+
# DynamoDB Local files
88+
.dynamodb/
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Use the official Node.js 14 LTS image as the base image
2+
FROM node:20-alpine
3+
4+
# Set the working directory
5+
WORKDIR /app
6+
7+
# Copy package.json and package-lock.json
8+
COPY package*.json ./
9+
10+
# Install dependencies
11+
RUN npm ci
12+
13+
# Copy the rest of the application source code
14+
COPY . .
15+
16+
# Define the command to run the application
17+
CMD ["node", "index.mjs"]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
POST http://localhost:3001/add HTTP/1.1
2+
Content-Type: application/json
3+
4+
{
5+
"name": "process-object",
6+
"data": {
7+
"id": 1,
8+
"name": "object-to-process"
9+
}
10+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Queue, Worker } from 'bullmq';
2+
import IORedis from 'ioredis';
3+
import express from 'express';
4+
5+
const connectionString = process.env.REDIS;
6+
const connection = new IORedis(connectionString);
7+
8+
const myQueue = new Queue(process.env.QUEUE, { connection });
9+
10+
const app = express();
11+
app.use(express.json());
12+
13+
// For health check
14+
app.get('/', async (req, res) => {
15+
res.send('All good');
16+
});
17+
18+
// GET example
19+
app.get('/add', async (req, res) => {
20+
const params = req.query;
21+
const name = params.name || 'myjob';
22+
const data = JSON.parse(params.data || '{}');
23+
24+
await myQueue.add(name, data);
25+
res.send('Job added');
26+
});
27+
28+
// POST example
29+
app.post('/add', async (req, res) => {
30+
const body = req.body;
31+
const name = body.name || 'myjob';
32+
const data = body.data || {};
33+
34+
await myQueue.add(name, data);
35+
});
36+
37+
app.listen(3001, () => {
38+
console.log('Server is running on http://localhost:3001');
39+
});

0 commit comments

Comments
 (0)