schedule.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. /**
  2. * The main class and interface of the schedule module
  3. */
  4. var PriorityQueue = require('./priorityQueue');
  5. var Job = require('./job.js');
  6. var timerCount = 0;
  7. var logger = require('log4js').getLogger(__filename);
  8. var map = {};
  9. var queue = PriorityQueue.createPriorityQueue(comparator);
  10. var jobId = 0;
  11. var timer;
  12. //The accuracy of the scheduler, it will affect the performance when the schedule tasks are
  13. //crowded together
  14. var accuracy = 10;
  15. /**
  16. * Schedule a new Job
  17. */
  18. function scheduleJob(trigger, jobFunc, jobData){
  19. var job = Job.createJob(trigger, jobFunc, jobData);
  20. var excuteTime = job.excuteTime();
  21. var id = job.id;
  22. map[id] = job;
  23. var element = {
  24. id : id,
  25. time : excuteTime
  26. };
  27. var curJob = queue.peek();
  28. if(!curJob || excuteTime < curJob.time){
  29. queue.offer(element);
  30. setTimer(job);
  31. return job.id;
  32. }
  33. queue.offer(element);
  34. return job.id;
  35. }
  36. /**
  37. * Cancel Job
  38. */
  39. function cancelJob(id){
  40. if(id == queue.peek().id){
  41. queue.pop();
  42. delete map[id];
  43. var job = getNextJob();
  44. if(!job)
  45. return true;
  46. setTimer(job);
  47. }
  48. delete map[id];
  49. return true;
  50. }
  51. /**
  52. * Clear last timeout and schedule the next job, it will automaticly run the job that
  53. * need to run now
  54. * @param job The job need to schedule
  55. * @return void
  56. */
  57. function setTimer(job){
  58. clearTimeout(timer);
  59. while((job.time-Date.now()) < accuracy){
  60. job.run();
  61. job = getNextJob();
  62. if(!job)
  63. return;
  64. }
  65. timer = setTimeout(excuteJob, job.excuteTime()-Date.now());
  66. }
  67. /**
  68. * The function used to ran the schedule job, and setTimeout for next running job
  69. */
  70. function excuteJob(){
  71. var job = peekNextJob();
  72. var nextJob;
  73. while(!!job && (job.excuteTime()-Date.now())<accuracy){
  74. job.run();
  75. queue.pop();
  76. var nextTime = job.nextTime();
  77. if(nextTime === null){
  78. delete map[job.id];
  79. }else{
  80. queue.offer({id:job.id, time: nextTime});
  81. }
  82. job = peekNextJob();
  83. }
  84. //If all the job have been canceled
  85. if(!job)
  86. return;
  87. //Run next schedule
  88. setTimer(job);
  89. }
  90. /**
  91. * Return, but not remove the next valid job
  92. * @return Next valid job
  93. */
  94. function peekNextJob(){
  95. if(queue.size() <= 0)
  96. return null;
  97. var job = null;
  98. do{
  99. job = map[queue.peek().id];
  100. if(!job) queue.pop();
  101. }while(!job && queue.size() > 0);
  102. return (!!job)?job:null;
  103. }
  104. /**
  105. * Return and remove the next valid job
  106. * @return Next valid job
  107. */
  108. function getNextJob(){
  109. var job = null;
  110. while(!job && queue.size() > 0){
  111. var id = queue.pop().id;
  112. job = map[id];
  113. }
  114. return (!!job)?job:null;
  115. }
  116. function comparator(e1, e2){
  117. return e1.time > e2.time;
  118. }
  119. module.exports.scheduleJob = scheduleJob;
  120. module.exports.cancelJob = cancelJob;