I am implementing NestJS worker, queues, using Bull.
According to the documentation, both the worker and the server (will) run in a same "process", but I want to run the worker in a separate process, so as to not block the main event loop.
I think it’s called "running a task in a separate binary" or something else.
Anyway, I tried googling it, went through the documentation of NestJS, but couldn’t find something similar.
++
In other words:
I have a main project (my current), and I want to create the worker in a separate process (standalone application) and want to connect both my current main project and worker. And I can’t really find it in the documentation.
In which module should I instantiate my Bull’s instance? I am assuming I’ll keep my producer
in my main module and consumer
in my worker module.
How can I do so?
Please note, by "separate process", I do not mean running a specific task in a separate process, as defined in Bull’s documentation.
I want to deploy the whole worker module in a separate process or whatever the term should be used.
++
[Extra, if possible]
Before running my server and worker, I also want to check whether my worker (bull instance) is successfully connected to my Redis server. I couldn’t find anything on the Bull’s documentation… do you think there is a good workaround for that?
2
Answers
While the answer provided by Isolated should work, I didn't really want to run a whole new project and import my modules the way he suggested. So after some more R&D, I've figured out a (better) way to do so.
Just like we have our
index.ts
ormain.ts
file for our "parent" project, in the same dir (doesn't have to be), create aworker.ts
andworker.module.ts
.In the
worker.module.ts
, make sure you register your Bull module again [BullModule.forRoot({})
] and include all the imports that you'd need for your consumer.In the
providers
, you should add ourconsumers
and you'll be good to go.The
worker.ts
would look like this (nothing fancy):Your
nest-cli.json
should like something like thisand create a new
nest-cli-worker.json
Now, the question is, how to run it?
I am using
yarn
commands to start my server (defining them inpackage.json
)To
start
myserver
, I'dor
and to
start
myworker
, I'd run the following command(s) in another (terminal) shell...or
P.S You don't necessarily have to add
dotenv/config
.Bonus:
Here's my
docker-compose.yaml
fileYou can use that documentation to implement the entire worker. If you use Nest.js in standalone mode you can just have Processor(s) and Process(es).
This is documented here. “Separate binary” isn’t a question either. A binary is the product of compilation, Node.js isn’t compiled so you’ll need a separate application.
You don’t need a workaround for anything, this is literally the nature of Bull and optionally Nest.js.
Sometimes you’ll need to adapt examples in docs to fit your needs, this can take some time to learn.
Terminology
I think there’s some confusion with terminology so in this post assume that:
process
is what yourapplication
runs inside (if you look in your OS process manager it should benode
).application
is one Node.js project that runs in a separateprocess
.worker
is anapplication
that is only focused with processing Queue jobs.Queue
andJob
is terminology of Bull.Processor
andProcess
is terminology of Nest.js@nestjs/bull
Solution
Here is how you create an application with a worker running in separate processes. After following these instructions, you should see two processes running your process manager.
Create a new Nest.js application that we’ll use for your
worker
:Open
src/main.ts
and replace everything inbootstrap
function with:Install
Bull
and the Nest.js implementation with:Open
src/app.module.ts
and removeAppController
fromcontrollers
, and addBullModule.registerQueue
to imports (from@nestjs/bull
.Your
src/app.module.ts
should now look like:Create a new file:
app.processor.ts
insrc
directory:And you’re done for the
worker
side of things. Now all you need to do is in yourapplication
(main project), update yourAppModule
to includeBullModule.registerQueue
(like above) and inject it:And then use
this.queue.add('namedJob', data);
Try above and if you get stuck, create a repository on Github and I’ll get you on the right track.
Reference