UNPKG

occaecatidicta

Version:
152 lines (122 loc) 3.32 kB
/** * The main class and interface of the schedule module */ import * as PriorityQueue from './priorityQueue'; import * as Job from './job'; import { SimpleTriggerOpts } from './simpleTrigger'; import { getLogger } from 'omelox-logger'; import * as path from 'path'; let logger = getLogger('omelox-scheduler', path.basename(__filename)); let timerCount = 0; let map: {[key: number]: Job.Job} = {}; let queue = PriorityQueue.createPriorityQueue(comparator); let jobId = 0; let timer: any; // The accuracy of the scheduler, it will affect the performance when the schedule tasks are // crowded together let accuracy = 10; /** * Schedule a new Job * @param trigger The trigger to use * @param jobFunc The function the job to run * @param jobData The data the job use * @return The job id, which can be canceled by cancelJob(id:number) */ function scheduleJob<T>(trigger: SimpleTriggerOpts | string, jobFunc: (data?: T) => void, jobData?: T): number { let job: Job.Job = Job.createJob(trigger, jobFunc, jobData); let excuteTime = job.excuteTime(); let id = job.id; map[id] = job; let element = { id: id, time: excuteTime }; let curJob = queue.peek(); if (!curJob || excuteTime < curJob.time) { queue.offer(element); setTimer(job); return job.id; } queue.offer(element); return job.id; } /** * Cancel Job */ function cancelJob(id: number): boolean { let curJob = queue.peek(); if (curJob && id === curJob.id) { // to avoid queue.peek() is null queue.pop(); delete map[id]; clearTimeout(timer); excuteJob(); } delete map[id]; return true; } /** * Clear last timeout and schedule the next job, it will automaticly run the job that * need to run now * @param job The job need to schedule * @return void */ function setTimer(job: Job.Job) { clearTimeout(timer); timer = setTimeout(excuteJob, job.excuteTime() - Date.now()); } /** * The function used to ran the schedule job, and setTimeout for next running job */ function excuteJob() { let job = peekNextJob(); let nextJob; while (!!job && (job.excuteTime() - Date.now()) < accuracy) { job.run(); queue.pop(); let nextTime = job.nextTime(); if (nextTime === null) { delete map[job.id]; } else { queue.offer({ id: job.id, time: nextTime }); } job = peekNextJob(); } // If all the job have been canceled if (!job) return; // Run next schedule setTimer(job); } /** * Return, but not remove the next valid job * @return Next valid job */ function peekNextJob() { if (queue.size() <= 0) return null; let job = null; do { job = map[queue.peek().id]; if (!job) queue.pop(); } while (!job && queue.size() > 0); return (!!job) ? job : null; } /** * Return and remove the next valid job * @return Next valid job */ function getNextJob() { let job = null; while (!job && queue.size() > 0) { let id = queue.pop().id; job = map[id]; } return (!!job) ? job : null; } function comparator(e1: {time: number}, e2: {time: number}) { return e1.time > e2.time; } export { scheduleJob, cancelJob };