Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Schedule cron job in loopback #4047

Closed
anandrajputSF opened this issue Oct 29, 2018 · 17 comments
Closed

Schedule cron job in loopback #4047

anandrajputSF opened this issue Oct 29, 2018 · 17 comments
Assignees
Labels

Comments

@anandrajputSF
Copy link

How to create schedule cron job in loopback, where can I code? I tried to implement node-schedule but not work. I don't know how to call my controller code?

@matteo-pennisi
Copy link

To solve this I've used a workaround: I've created a public endpoint and a cron job that call that endpoint using https://cron-job.org/
Hope that it helps :)

@hacksparrow
Copy link
Member

@anandrajputSF can you explain your requirements in detail?

@anandrajputSF
Copy link
Author

@hacksparrow basically my requirement is connect with sql server, after some time interval fetch data from tables and log some where, if next time cron run, it will pick data from log table last run time and from this time it will again fetch data from sql server

@hacksparrow
Copy link
Member

@anandrajputSF LoopBack does not provide an in-built solution to your specific usecase, however with Remote hooks it can be very well achieved.

@hacksparrow
Copy link
Member

@anandrajputSF were you able to solve your problem?

@anandrajputSF
Copy link
Author

@hacksparrow i haven't try.

@nikhil-g777
Copy link

nikhil-g777 commented Dec 6, 2018

@anandrajputSF I have implemented something similar in loopback, you can do it the way you would do it in NodeJS and its nothing specific to loopback.
You can use this package : https://www.npmjs.com/package/cron
And you can paste the code in your controller file or a file in the boot folder. Here is some example code :

`'use strict';

const CronJob = require('cron').CronJob;

module.exports = function (app) {

function runCron() {
   //The code which you want to run in the cron job
}

var job = new CronJob({
    cronTime: '00 00 10 * * 0-6', // The Time at which you want the cron job to run
    onTick: runCron,
    start: false,
    timeZone: 'Asia/Kolkata'
});
job.start();

}`

Hope this Helps !

@matteo-pennisi
Copy link

@nikhil-g777 This seems to be a great solution if the application is running on a single instance. But if I have more instances running the same time they will run the same cron job multiple times.

@nikhil-g777
Copy link

nikhil-g777 commented Dec 14, 2018

@matteo-pennisi
You could use environment variables to keep one of the instances as the main instance with an instanceNumber as 1, which would run the cron job

if(process.env.instanceNumber == 1) { job.start(); }

This is more like a workaround, but I believe it should solve the problem

@dtelaroli
Copy link

dtelaroli commented Aug 2, 2019

It would be awesome if LB would have a way to inject a component, as a service or repository, in a cron component. Also invoke a self rest endpoint.

@dtelaroli
Copy link

dtelaroli commented Aug 21, 2019

This solution has worked for me.

Installation

https://www.npmjs.com/package/node-cron
$ npm install --save node-cron

Create a component

import { CronController } from "./controller/cron.controller";
const cron = require('node-cron');

export class Cron {
  constructor(
    protected cronController: CronController,
  ) {
  }

  async start() {
    this.eachMinute();
  }

  private async eachMinute() {
    console.log('Start Cron Jobs');

    cron.schedule('* * * * *', async () => {
      await this.cronController.start();
      console.log('running a task every minute');
    });
  }
}

Using Loopback DI Container to get a controller instance:

// index.ts
export async function main(options: ApplicationConfig = {}) {
  const app = new MyApplication(options);
  await app.boot();
  await app.start();

  const url = app.restServer.url;
  console.log(`Server is running at ${url}`);
  console.log(`Try ${url}/ping`);

  // Instanciate CronController
  const cronController = app.controller(CronController);
  
  // Get Instance
  const cronControllerInstance = await cronController.getValue(app);
  
  // Inject by constructor
  const cron = new Cron(cronControllerInstance);

  // Invoke method
  cron.start();

  return app;
}

@filipef101
Copy link

@dtelaroli Does that mean that the cron is only run on one instance?

@dtelaroli
Copy link

dtelaroli commented Aug 29, 2019

@filipef101 you can have multiple instances into the CronController or multiples Controllers into the Cron. It's up to you, but I think that is easier into the CronController, otherwise you should inject manually multiple controllers.

@stale
Copy link

stale bot commented Oct 28, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 28, 2019
@stale
Copy link

stale bot commented Nov 11, 2019

This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the CODEOWNERS file at the top-level of this repository.

@stale stale bot closed this as completed Nov 11, 2019
@juanvillegas
Copy link

Just for reference, there is a package called Bull that allows assigning an ID to the Job. If running multiple instances, attempting to create a job with an ID that already is in the queue will be ignored.
https://github.com/OptimalBits/bull

@minhng22
Copy link

minhng22 commented Mar 15, 2020

This solution has worked for me.

Installation

https://www.npmjs.com/package/node-cron
$ npm install --save node-cron

Create a component

import { CronController } from "./controller/cron.controller";
const cron = require('node-cron');

export class Cron {
  constructor(
    protected cronController: CronController,
  ) {
  }

  async start() {
    this.eachMinute();
  }

  private async eachMinute() {
    console.log('Start Cron Jobs');

    cron.schedule('* * * * *', async () => {
      await this.cronController.start();
      console.log('running a task every minute');
    });
  }
}

Using Loopback DI Container to get a controller instance:

// index.ts
export async function main(options: ApplicationConfig = {}) {
  const app = new MyApplication(options);
  await app.boot();
  await app.start();

  const url = app.restServer.url;
  console.log(`Server is running at ${url}`);
  console.log(`Try ${url}/ping`);

  // Instanciate CronController
  const cronController = app.controller(CronController);
  
  // Get Instance
  const cronControllerInstance = await cronController.getValue(app);
  
  // Inject by constructor
  const cron = new Cron(cronControllerInstance);

  // Invoke method
  cron.start();

  return app;
}

This solution worked for me as well. Loopback 4 tested. Example in repo: https://github.com/tangoat2019/covid19-tracking-api

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

8 participants