Remove job after it is complete in Node Bull is not working - node.js

I am using node bull for scheduling. Now for my jobs i pass a cron time to it (which is a specific time and a date). Now since i have provided a strict cron then it must run for only one time or even if it run second time then it must be removed from the queue (i have provided removeOnComplete: true).
But still it doesn't get removed and it runs again and my queue process this job again. So i want to stop this.
My add job function: (data is my job data, timings is my cron timing)
public async addJob(data: any, timings: any, jobId: any) {
console.log('adding job');
console.log(timings);
const job = await this.videoQueue.add(
{data: data},
{
repeat: {
cron: timings,
},
jobId: jobId,
removeOnComplete: true,
},
);
return job;
}
My process function:
this.videoQueue.process(async (job: any) => {
// processing function for my job.
});
I am new node and node bull. Maybe i am making a mistake but i am not able to debug it.
Thanks.

I can suggest you use node-schedule package to schedule with cron time. It's very easy to use actually
const schedule = require('node-schedule');
const job = schedule.scheduleJob('* * * * *', function(){
console.log('Job runned.');
job.cancel();
});

Related

How to Access SchedulerRegistery ID in Nest Js

I am using #nestjs/schedule for scheduling tasks. Sample code for scheduling are as follows
async scheduleCron(cronId: any, day: any){
let cronTime = '0 0 '+day+' * *';
const job = new CronJob('* * * * *', () => {
this.postOrder();
});
this.schedulerRegistry.addCronJob(cronId, job);
job.start();
}
Here cronId is my custom Id which I passed to identify between different crons. Now when postOrder is called by a specific cronjob I want to access cronId of cronjob so that I know which cronjob had executed and based on that I can make appropriate db queries.
Is there a way I can access id ?.
From documentation what I understand is that you need to pass id to fetch details and not the other way around.
Any clue or alternative way to solve this issue would be really appreciated.
Do you mean accessing the list of the job like this?
this.schedulerRegistry.getCronJobs().forEach((job) => {
job.stop();
})

NestJs Cron Service

I am trying to create a Schedule service using nestJs' Cron decorator
I have a Cron-decorated method below:
#Cron(CronExpression.EVERY_5_SECONDS)
triggerDataloaderCron() {
this.logger.debug('called every 10 seconds');
return this.healthService.getPCFHealth();
}
And this cron job calls a method in another service, which is shown below
getHealth() {
//code to form up an endpoint, saved as the variable fullUrl
//Does not come into this block
return this.httpService.get(fullUrl).pipe(
map((axiosResponse: AxiosResponse) => {
return axiosResponse.data;
}),
catchError((err) => {
console.log("in error", err);
throw new CustomException(ExceptionConstants.EurekaConnectionException);
})
);
}
When the cron job runs, i am able to enter the getHealth() method, but the this.httpService etc... block of code does not run.
Any suggestions on how this can be achieved? Or if I am going about this the wrong way?
Thanks!
The getHealth method returns an Observable. An observable does not execute unless there is at least one subscriber.
In your cron method, add a subscription as follows:
this.healthService.getPCFHealth()
.subscribe(response => console.log(response))
Since the cron method executes at regular intervals, I don't think you need to return a value from it.

Run background task inside Jest

I was writing an automatic test framework with Jest. For this, I need to run some background tasks under certain intervals. In summary, this is like polling. Let's give an example with a pseudo code.
test('Some potato poteto test', () => {
jest.setTimeout(12000000); // 20 min
const intervalPeriod = 5 * 60 * 1000; // 5 min
let retry = 0;
const intervalId = setInterval(() => {
console.log("I am doing my 5 minutes check");
// my custom logic goes here
retry++;
if(retry === MAX_RETRY) { // this will be always hit
clearInterval(intervalId)
}
}, intervalPeriod);
});
So, in every 5 mins, I'll make a network call, do some of my custom logic. Now, the problem is while running this, the test finished but jest can't terminate.
By 'test-finished' I meant, test suite ran, but the code inside the setInterval does not get executed right then.
My question is, does this happen because setInterval does not run immediately in the event-loop and is jest not configured to run a setInterval?
Please note that I don't want to mock the setInterval and also I don't want to use any fake timer.
Therefore, is it possible to achieve this with Jest?
I also tried the same thing with the cron library for node but it is the same issue. Jest does not execute the code and finish executing then halted because those setInterval/cron are still running in the background.
Is there a way to run those tasks inside Jest? I mean is there a way to run those jobs and when they are done then terminate Jest?
That's intended, Jest execute all the test instructions and quit the test.
For jest to wait for a computation, you need to use Promises and its async mode.
Doc for Jest async mode: https://jestjs.io/docs/asynchronous
Learn more about Promises here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
And async/await syntax here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function
This is a naive way for doing it:
const MAX_RETRY = 3;
const INTERVAL_PERIOD = 5 * 60 * 1000; // 5 min
const SAFETY_TIME = INTERVAL_PERIOD;
const TEST_TIMEOUT = (1 + MAX_RETRY) * INTERVAL_PERIOD + SAFETY_TIME;
test('Some potato poteto test', async () => {
let retry = 0;
let success = false;
function yourLogicFunction(): boolean {
const resultOfYourLogicFunction = retry === MAX_RETRY; // because retry is used in this condition I store the result before changing it
console.log(`this is my attempt number ${retry}`);
retry++;
return resultOfYourLogicFunction;
}
function mockRequest(resolve: (value: unknown) => void): void {
setTimeout(() => resolve(yourLogicFunction()), INTERVAL_PERIOD);
}
while (!success && retry <= MAX_RETRY) {
success = await new Promise(mockRequest) as boolean;
}
}, TEST_TIMEOUT);
The third parameter of test is its timeout.

Aysnc v3.1.0 => queue.push does nothing after no. of tasks are complete(defined concurrency)

var que = async.queue(async function({id}) {
const res = await fetchData(id);
return res;
}, 2);
que.push({id}, function (err, res) {
console.log('handle res');
});
Here concurrency is set as 2. so after first two tasks are done and if I push a new task in the queue. nothing happens. No err, even the task in also not pushed.
If I update concurrency to 5, it will perform the first 5 tasks and then it fails for the 6th task.
Do we have to clear the queue after each task is done?
I am using it in Reactjs project.
NOTE: I am able to make this work correctly on my local, but when I create the react build and deploy it, it does not work there.

Node.js agenda: how to retry jobs after failure?

Using Agenda, is it possible to set jobs to retry after several times after failure?
If it's a repeating job, you can change the nextRunAt value when it fails and it will run again:
agenda.on("fail", async (error, job) => {
const nextRunAt = new Date();
job.attrs.nextRunAt = nextRunAt;
await job.save();
});
if it's a scheduled job (meaning it doesn't repeat, the above code won't work. You have to create a new job.
agenda.on("fail", async (error, job) => {
if(job.attrs.repeatInterval) {
// create a new job and pass it job.attrs.data
}
});
Retry is not directly supported as an option, but it has a simple workaround by setting the failed jobs nextRunAt to a future time.
Refer this article :
https://crossbrowsertesting.com/blog/product-update/task-scheduling-with-agenda/

Resources