Helper functions to manage cron tasks
npm install @winkgroup/cron
or
yarn add @winkgroup/cron
We provide 3 main classes:
- CronRunner: with internal setInterval
- Cron: basic class without internal setInterval
- CronRunnerWithWebSocket: with internal setInterval and commands to be controlled through websocket
It is an abstract class to need to extend. The abstract method you need to extend is _run() => Promise<void>
.
Here an example:
import CronRunner from '@winkgroup/cron'
class DemoCronRunner extends CronRunner {
constructor() {
super(5)
}
async _run() {
console.info('something should be run every 5 seconds')
}
}
const demoCron = new DemoCronRunner() // immidiatly starting cron
super contructor has these params:
super(everySeconds, [options])
options in the constructor are:
- consoleLog: an instance of ConsoleLog class
- maxEverySeconds: in case of aborted task you can set a maxEverySeconds param. In this case everytime the task is aborted it will double the time for the next try until it will reach the maxEverySeconds time. This param is not considered if you set the backoffFunction
- backoffFunction : you can pass an option to set a backoff function in case of aborted task. Signature of the function has to be:
(currentWaitingSeconds: number) => number
, where the result is the next periood to wait - startActive: if true the cron is active at start (default: true)
- forceRun: if true it runs the periodic task no matter if the previous task is not completed (default: false)
other inherited methods you can overload are:
start() => Promise<void>
: to start cron. It is called by default when a new object is instanciatedstop() => Promise<void>
: to stop the period task to runrun([force]) => Promise<void>
: to manually call the periodic task. If force is true, than the task will run even if the previous task is not completed or the cooldown period is not passedsetup() => Promise<void>
: you can overload this method to run some previous asyncronous tasks before the running of the first taskgetState() => CronRunnerState
: CronRunnerState is an object like this
{
active: boolean;
running: boolean;
everySeconds: number;
defaultEverySeconds: number;
lastRunAt: number;
}
This is the simplest class. It doesn't have its own setInterval running and the tipical scenario to use this class is when you don't want to manager different intervals to reduce memory consumption and you want to keep anything regarding periodic tasks in one single place in your app.
Here an example:
import Cron from '@winkgroup/cron'
const cron5 = new Cron(5) // every 5 seconds
const cron2 = new Cron(2) // every 2 seconds
async function unifiedPeriodicTasks() {
await cron5.run( async () => {
// anything you want to run every 5 seconds
})
await cron2.run( async () => {
// anything you want to run every 2 seconds
})
}
setInterval( unifiedPeriodicTasks, 1000)
even if your unifiedPeriodicTasks
is called every second, your tasks will run with the period specified when you instanciated the Cron objects.
You can also manage cron setting when your task starts and stops, instead of using run
method:
import Cron from '@winkgroup/cron'
const cron5 = new Cron(5)
setInterval(async () => {
if (!cron5.tryStartRun()) return
await myTask() // some very long task
cron5.runCompleted()
}, 1000)
be aware the 5 seconds interval is calculated starting from runCompleted
execution. This mean that if you have a task that takes 10 seconds to run and you set 5 seconds interval, the next task will run 15 seconds after the starting of the previous task. Another point to be aware of is that if you forget to call runCompleted
no other task will be called after the first one, since Cron
assumes the previous task is still running.
You can use Cron
objects for debouncing, too. Here an example:
import Cron from '@winkgroup/cron'
const cron3 = new Cron(3)
setInterval(async () => {
if (cron2.debounce()) {
console.log('bouncing')
return
}
console.log('task debounced')
}, 1000)
/*
Expected output:
task debounced
bouncing
bouncing
task debounced
bouncing
bouncing
...
*/
You can instantiate a Cron
object with these params:
new Cron([everySeconds], [options])
- everySeconds: cooldown between the end of a task and the start of the following one (default: 0)
options in the constructor are:
- consoleLog: an instance of ConsoleLog class
- maxEverySeconds: in case of aborted task you can set a maxEverySeconds param. In this case everytime the task is aborted it will double the time for the next try until it will reach the maxEverySeconds time. This param is not considered if you set the backoffFunction
- backoffFunction : you can pass an option to set a backoff function in case of aborted task. Signature of the function has to be:
(currentWaitingSeconds: number) => number
, where the result is the next periood to wait
Here the list of attributes for Cron
objects:
- everySeconds: cooldown between the end of a task and the start of the following one
- lastRunAt: epoch coming from Date().getTime(). You can use this to force a different cooldown
- consoleLog: an instance of ConsoleLog class
- backoffFunction: as described above
Here the list methods for Cron
objects:
running() => boolean
: it says if a task is runningnextRunIn() => number
: number of seconds you have to wait to run the next taskdebounce() => boolean
: if false you can run a debounced task according to cooldown period you set as everySeconds attribute. If true you have to wait. Every time you call this method the lastRunAt is updated at the current timerun(task, [force]) => Promise<void>
: task is a function like this() => Promise<void>
and it is called if the cooldown period is passed or you force the run with the second paramtryStartRun([force]) => boolean
: if true you can start your periodic job. When true,Cron
object consider you will start your task, so it expects you conclude your task by callingrunCompleted
. If you don't callrunCompleted
any other call totryStartRun([force])
will return false, assuming your previous task is still running. ForcingtryStartRun
will always return truerunCompleted([abort = false]) => void
: used to notifyCron
object you ended your task, if abort is true then current running will not be considered valid
There is also a static method:
comeBackIn(milliseconds) => string
: it returns the ISOString of current time plus the number of milliseconds you set as parameter
TO DO
in playground
folder you will find a working implementation of CronRunnerWithWebSocket. You can run it with npm run playground
or yarn playground