Create a job scheduler in enonic xp

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.

**Enonic xp
**Windows 7

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
    }
});
1 Like

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.

1 Like