Running a Cron Job in LoopBack 4 for adding a report to a database table using a loopback repository.

Mohammad Quadri
2 min readJul 2, 2020

I needed to make a report entry in a table on a weekly basis. And here is how I did it.

I knew that I needed to run a cron job but not sure exactly how. I followed the instruction from here Running cron jobs | LoopBack Documentation and able to set the thing to simply console log “job is running 🥳. “.

// application.tsimport {CronComponent} from '@loopback/cron';...
...

// Binding Cron components for cron jobs inside the constructor of Application class
this.component(CronComponent);
...

Next, created a class for running the job. See for more details.

// MyCronJob.tsimport {CronJob, cronJob} from '@loopback/cron';

@cronJob()
export class MyCronJob extends CronJob {
constructor() {
super({
name: 'my-job',
onTick: () => {
// do the work
this.performMyJob();
},
cronTime: '*/10 * * * * *', // Every ten second
start: true,
});
}

performMyJob() {
console.log('Job is running 🥳.');
}
}

And bind this class in the constructor of the Application class.

...
this.component(CronComponent);

this.add(createBindingFromClass(MyCronJob));
...

But it was of no use. I needed to run some tasks. And tasks are asynchronous like updating or getting task using a repository. I injected the repository instance in the constructor.

constructor(
@repository(ReportRepository) public reportRepository: ReportRepository,
) {
....

And called a simple count function in performMyJob function.

async performMyJob() {
const count = await this.reportRepository.count()
console.log(count);
}

But here is a problem. I can not call this function now from onTick function of the cron job. And you might be wondering well why not simply convert the onTick function as async as well. Okay, you might be some genius but it took me around 4 hours to figure it out. And yes the solution is to simply convert onTick function as async as well.

onTick: async () => {
// do the work
await this.performMyJob();
}

Now the complete class looked like this.

import {CronJob, cronJob} from '@loopback/cron';
import {repository} from '@loopback/repository';
import {ReportRepository} from '../repositories';

@cronJob()
export class MyCronJob extends CronJob {
constructor(
@repository(ReportRepository) public reportRepository: ReportRepository,
) {
super({
name: 'my-job',
onTick: async () => {
// do the work
await this.performMyJob();
},
cronTime: '*/10 * * * * *', // Every ten second
start: true,
});
}

async performMyJob() {
const count = await this.reportRepository.count()
console.log(count);
}
}

By default, all cron jobs will be started and stopped by CronComponent when the application is started or stopped. But if you want to manually start or stop you will need to inject the CronJob Class in the constructor of a class.

constructor(
....
@inject(CronBindings.COMPONENT) private myCronJob: MyCronJob,
) {}

Now you can call this.myCronJob.start() or this.myCronJob.stop() to start or stop.

Rest I leave up to you to explore. Cheers!!!

--

--