4

I'm using agenda jobs in nodejs. I was wondering if it's possible to define a job with a dependency. In my case I have 3 jobs, each one of the jobs execute a part of a whole logic, which is quite big, that's why they are separated.

  1. In the Job 1, I collect info from the database, transform them and perform a few tasks.
  2. In the Job 2, I get all the data that had been previously processed by the Job 1 and perform new transformations..
  3. In the Job 3, I get again all the data that had been processed in the Job 2 and send a few reports.

I have those tasks schedule to be executed every 5 minutes. But the thing is that the 3 of them are schedule at the same time because, they are schedule dynamically.

job1.schedule("now");
job1.repeatEvery('5 minutes');

job2.schedule("now");
job2.repeatEvery('5 minutes');

job3.schedule("now");
job3.repeatEvery('5 minutes');

As it's configured currently, to process one instance that needs to go through the 3 jobs, worst case scenario the user will need to wait 15min, which is not ideal.

I was wondering if there is an option to define that the tasks should be executed as soon as the previous task is finished. I'm aware that a possible workaround will be to schedule the jobs with a few minutes of difference, but given that depending on the number of instances the job can require more or less time this doesn't work for me.

fingerprints
  • 2,751
  • 1
  • 25
  • 45

1 Answers1

2

The way I am doing a pretty similar thing is, I trigger the next job when the main function of the preceding job is done, this way I can feed data from one job to another and run them in sequence.

So I trigger job3 in the definition of job2 and trigger job2 in the definition of job1:

// DEFINE JOBS
agenda.define('job1', (job) => {
    return myMainJob1Function(job.attrs.data)
      .then((data) => {
        for (const element of data) {
          agenda.now('job2', { // runs many instances of 'job2' job with distinct data
            // use output data from the "parent" job
            arg1: element.arg1,
            arg2: element.arg2,
            arg3: element.arg3,
            arg4: job.attrs.data.someArg, // this will propagate an argument we set for the "parent" job
          });
        }
      });
  });

agenda.define('job2', (job) => {
    return myMainJob2Function(job.attrs.data) // data supplied from 'job1'
      .then((data) => {
        for (const element of data) {
          agenda.now('job3', { // runs many instances of 'job3' job with distinct data
            // use output data from the "parent" job
            arg1: element.arg1,
            arg2: element.arg2,
            arg3: element.arg3,
            arg4: job.attrs.data.someArg, // this will propagate an argument we set for the "parent" job
          });
        }
      });
  });

agenda.define('job3', (job) => {
    return myMainJob3Function(job.attrs.data) // data supplied from 'job2'
      .then((data) => {
        // save data to database or do something else
      });
  });

// TRIGGER 'job1', WHICH TRIGGERS CHILD JOBS
agenda.now('job1', { someArg: 5 }); // we're providing some initial argument, that gets passed onto child jobs
const schedule = '0 0/5 0 ? * * *' // cron expression for every 5 minutes
agenda.every(schedule, 'job1', { someArg: 5 });

One other thing that comes to mind is using triggers for complete or success of job1 but when you run many of the same jobs with different input data you can't (I haven't found a way) listen to those events with regard to the specific job instance that you want.

That being said you can do:

agenda.on('success:job1', (job) => {
  agenda.now('job2', { someArg: job.attrs.data.someArg });
});
  • Hi, i have a similar problem to this, i want to dynamically schedule jobs to run at different times with different input data(an array of objects for each job), but the times are relative. E.g after the first job is scheduled to run 3 days later with the data in the first object, the job should schedule to run again 24 hours after the 3 days with the data from the second object in the array, and the next job should schedule to run 6 hours after the second job with the data in the 3rd object. Do you know how i can accomplish this? – Nathaniel Babalola May 09 '21 at 23:53
  • 1
    @NathanielBabalola if I understand correctly, you should use `agenda.schedule` instead of `agenda.now`. See https://github.com/agenda/agenda#schedulewhen-name-data – Kuba Serafinowski May 11 '21 at 12:15
  • Thanks, but I'm also having a problem with the scheduling. I posted the question here, I would be glad if you can look at it https://stackoverflow.com/questions/67527454/agenda-not-computing-human-interval-time-well – Nathaniel Babalola May 14 '21 at 02:31
  • 1
    I checked and human-interval for your phrase outputs 389400000 ms so it seems to be working fine. I don't have an agenda project lying around right now to be able to reproduce the same behavior, especially without sample code provided. I'm afraid I can't help beyond that. I can't comment there (not enough reputation) and I don't have an answer so won't post it there. – Kuba Serafinowski May 15 '21 at 20:06
  • ooh okay, what did you use to convert that human-interval time to milliseconds – Nathaniel Babalola May 16 '21 at 19:14
  • 1
    I used human-interval, it returns milliseconds when given text input. – Kuba Serafinowski May 18 '21 at 16:14
  • Okay thanks , I used human-interval to convert it to milliseconds then used humanizeDuration to convert it back to a human interval string but just in hours and minutes, and it worked. – Nathaniel Babalola May 19 '21 at 23:02