16

My question is how to use node-schedule to run a cron only on one instance out of two instances of node server. Currently it is running on both instances but I want it to be executed only on one instance. So How can you make a cluster run a task only once? Thanks in advance.

{
  "apps": [
    {
      "name": "Example",
      "script": "boot/app/app.js",
      "watch": false,
      "exec_mode": "cluster_mode",
      "instances": 2,
      "merge_logs": true,
      "cwd": "/srv/www.example.com/server",
      "env": {
        "NODE_ENV": "development",
        .......
    .......
      }
    }
  ]
}
Kamal K
  • 179
  • 2
  • 8

2 Answers2

11

You can use an environment variable provided by PM2 itself called NODE_APP_INSTANCE which requires PM2 2.5.

NODE_APP_INSTANCE environment variable is used to determine difference between process, for example you may want to run a cronjob only on one process, you can just check if process.env.NODE_APP_INSTANCE === 0, Since two processes can never have the same number.

More Info on PM2 official doc here.

Rahul Kumar
  • 5,120
  • 5
  • 33
  • 44
  • 1
    But how do we guarantee that one of the processes will have the ID 0. Is it not possible that if I run the app in cluster mode(2) they will have process IDs are 3 & 4 (assuming random numbers here) – Nick Div Jan 10 '20 at 06:41
4

You should use enviroment variables.

In your code you will check this env var:

if(process.env.WITH_SCHEDULE) {
    ...
}

When you start your instances, you will set WITH_SCHEDULE only for one instance.

Example pm2.json:

{
  "apps": [
    {
      "name": "Example",
      "script": "boot/app/app.js",
      "args": [],
      "error_file": "/srv/www.example.com/logs/error.log",
      "out_file": "/srv/www.example.com/logs/info.log",
      "ignore_watch": [
        "node_modules"
      ],
      "watch": false,
      "cwd": "/srv/www.example.com/server",
      "env": {
        "NODE_ENV": "production",
        "WITH_SCHEDULE": "1",
        "HOST": "127.0.0.1",
        "PORT": "9030"
      }
    },
    {
      "name": "Example",
      "script": "boot/app/app.js",
      "args": [],
      "error_file": "/srv/www.example.com/logs/error.log",
      "out_file": "/srv/www.example.com/logs/info.log",
      "ignore_watch": [
        "node_modules"
      ],
      "watch": false,
      "cwd": "/srv/www.example.com/server",
      "env": {
        "NODE_ENV": "production",
        "HOST": "127.0.0.1",
        "PORT": "9030"
      }
    }
  ]
}
galkin
  • 5,264
  • 3
  • 34
  • 51
  • what if i don't know how many cores my machine has? i used to use **instance:"max"** in the configuration to create one instance for each core. Is a way to separate the main instance and other instance? – kilik52 Jun 26 '17 at 02:28
  • never mind, i figured it out. use **instance: -1** for other instance – kilik52 Jun 26 '17 at 02:43
  • 2
    But this will render one of the instances unusable for scheduling. And what if the scheduling instance dies? This defeats the purpose of distributed systems... To make it robust and _the right way_ you should use either a central entity through which the instances will sync, or make them talk to each other and reach a consensus as to which one of them should schedule the task. The 1st option (central entity) is simpler and widely used. You can try this: https://github.com/thedeveloper/warlock – Milkncookiez Nov 16 '18 at 14:51