Based on your reply in the comment, you are using clusters. So for every instance that is running, a cron is created. If you have three instances in the cluster, you will get three crons. What you need to do is assign a name to your cluster. I'll give you an example of the setup we have.
We are running instances based on max cpu cores.
We assigned a name to the instances, and gave one of them the name primary
. And set it to run on one core.
The remaining instances doesn't matter what you name them, but we set the count to -1
. This way we utilize all cores on the machine.
Here's an example of the ecosystem.config.js
module.exports = {
apps: [
{
name: 'nest-primary',
script: './dist/src/main.js',
instances: '1',
exec_mode: 'cluster',
time: true,
combine_logs: true,
max_memory_restart: '3500M',
max_old_space_size: 3000,
log_date_format: 'HH:mm YYYY-MM-DD Z',
log_type: 'json',
merge_logs: true,
env_local: {
NODE_ENV: 'local',
HOST: 'localhost',
PORT: 3000,
DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
},
env_development: {
NODE_ENV: 'development',
PORT: 3000,
HOST: '0.0.0.0',
DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
},
},
{
name: 'nest-replica',
script: './dist/src/main.js',
instances: '-1',
exec_mode: 'cluster',
time: true,
combine_logs: true,
max_memory_restart: '3500M',
max_old_space_size: 3000,
log_date_format: 'HH:mm YYYY-MM-DD Z',
log_type: 'json',
merge_logs: true,
env_local: {
NODE_ENV: 'local',
HOST: 'localhost',
PORT: 3000,
DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
},
env_development: {
NODE_ENV: 'development',
PORT: 3000,
HOST: '0.0.0.0',
DATABASE_URL: 'mysql://user:password@localhost:3306/himam',
DATABASE_URL_PG: 'postgresql://postgres:password@localhost:5432/himam',
},
},
When I launch the cluster, I pass --env production
pm2 start ecosystem.config.js --env production
The most important part, in your crons, you need to check the name of the instance. You can do this by adding the names you used in the config above to your .env
PM2_PRIMARY_NAME=nest-primary
PM2_REPLICA_NAME=nest-replica
- Finally, in your code when you want to run the cron, check the name of the process, like this:
async handleCron() {
if (process.env.name !== this.configService.get('PM2_PRIMARY_NAME')) {
return;
}
// do your cron logic here.
This ensures that your cron will run only once, because your primary instance is only running on 1 core, and you won't have duplicate triggers. Please do update us.