Hi
I have tried to implement a job scheduler in enonic xp. However, I couldn´t since I haven’t found an option to do that. I really appreciate your help.
Hi
I have tried to implement a job scheduler in enonic xp. However, I couldn´t since I haven’t found an option to do that. I really appreciate your help.
Hi!
What Are you trying to do? Any reason you cannot start jobs from The operating system?
Hi
I have working in enonic 4.7. On this vesion when I open the system options I can create a job scheduler so I would like to know if there is a similar option in enonic xp
I see, the answer is currently not.
Hi
Ok. Thank you. I appreciate your help
You could do something like the code below.
Note: The tasklist will grow quickly. Could be avoided if https://github.com/enonic/xp/issues/4881 gets implemented.
import {
get as getTask,
list as listTasks,
sleep,
submit as submitTask
} from '/lib/xp/task';
const LOG_PREFIX = `whatever`;
const STATE_FINISHED = 'FINISHED';
function toStr(object, replacer = null, space = 4) {
return JSON.stringify(object, replacer, space);
}
function scheduler({
cron = {
hour: 999, // Will never match, so tasks without cron won't be started
minute: 0//,
//second: 0
},
taskDescription = 'noop',
taskCb = () => { log.debug(`${LOG_PREFIX} default noop taskCb`); },
delay = 60000 // milliseconds (Once a minute)
} = {}) { //log.debug(`${LOG_PREFIX} scheduler({ delay:${delay} })`);
submitTask({
description: 'Scheduler',
task: () => {
const now = new Date();
const hour = now.getHours();
const minute = now.getMinutes();
//const second = now.getSeconds();
if( // TODO: What if some other process makes the scheduler skips a minute??? I guess that means load is too high anyway.
(cron.hour === '*' || minute === cron.hour)
&& (cron.minute === '*' || minute === cron.minute)
//&& (cron.second === '*' || second === cron.second)
) {
//log.debug(`${LOG_PREFIX} scheduler() cron match ${hour}:${minute}:${second} === ${cron.hour}:${cron.minute}:${cron.second}`);
log.debug(`${LOG_PREFIX} scheduler() cron match ${hour}:${minute} === ${cron.hour}:${cron.minute}`);
// Do not start new job if previous of same description is not finished...
sleepUntil({ conditionCb: () => {
const unfinishedTasksWithDescription = listTasks().filter((t)=>{ return t.description === taskDescription && t.state !== STATE_FINISHED }); log.debug(`${LOG_PREFIX} scheduler() unfinishedTasksWithDescription:${toStr(unfinishedTasksWithDescription)}`);
return unfinishedTasksWithDescription.length ? false : true;
} });
const newTaskId = submitTask({
description: taskDescription,
task: taskCb
}); log.debug(`${LOG_PREFIX} scheduler() newTaskId:${toStr(newTaskId)}`);
} else {
//log.debug(`${LOG_PREFIX} scheduler() NO cron match ${hour}:${minute}:${second} !== ${cron.hour}:${cron.minute}:${cron.second}`);
log.debug(`${LOG_PREFIX} scheduler() NO cron match ${hour}:${minute} !== ${cron.hour}:${cron.minute}`);
} // cron
log.debug(`${LOG_PREFIX} scheduler sleeping for ${delay}ms`);
sleep(delay); // Let the scheduler sleep, before starting another.
scheduler({ cron, taskDescription, taskCb, delay }) // "recurse"
} // task
});
} // function scheduler
scheduler({
cron: {
hour: 2,
minute: 30//,
//second: '*'
},
taskDescription: 'My task description',
taskCb: () => {
log.debug(`${LOG_PREFIX} Started my task.`);
// The actual code to be executed at some point in time
}
});
A better solution: https://github.com/enonic/app-office-league/blob/master/src/main/resources/lib/maintenance-tasks.js
Which is stopped and started in main.js https://github.com/enonic/app-office-league/blob/master/src/main/resources/main.js
Perhaps https://github.com/enonic/app-cronjob could become a lib, to make an even better solution.