TODO.txt in rufus-scheduler-2.0.24 vs TODO.txt in rufus-scheduler-3.0.0

- old
+ new

@@ -1,57 +1,147 @@ -[o] spec for jobs in the past (in and at) -[o] :discard_past +[o] merge schedule_queue and unschedule_queue (and merge [un]schedule steps) +[x] OR stop using queue, since we've got the thread-safe JobArray +[x] if possible, drop the mutex in JobArray + NO, that mutex is necessary for Scheduler#jobs (on JRuby an co)... +[o] named mutexes +[o] drop the schedule queue, rely on the mutex in JobArray +[o] def jobs; (@jobs.to_a + running_jobs).uniq; end +[o] replace @unscheduled by @unscheduled_at +[o] make sure #jobs doesn't return unscheduled jobs +[o] job tags and find_by_tag(t) (as in rs 2.x) +[o] require tzinfo anyway (runtime dep) +[o] document frequency +[o] accept :frequency => '5s' +[o] timeout (as in rufus-scheduler 2.x) +[o] Rufus::Scheduler#running_jobs (as in rufus-scheduler 2.x) +[o] Rufus::Scheduler#terminate_all_jobs +[o] Rufus::Scheduler::Job#kill +[x] Rufus::Scheduler#kill_all_jobs +[o] Rufus::Scheduler#shutdown(:terminate or :kill (or nothing)) +[o] RepeatJob #pause / #resume (think about discard past) +[o] Rufus::Scheduler.start_new (backward comp) (with deprec note?) +[o] pass job to scheduled block? What does rs 2.x do? +[o] :first[_in|_at] for RepeatJob +[o] :last[_in|_at] for RepeatJob +[o] :times for RepeatJob (how many recurrences) +[o] fix issue #39 (first_at parses as UTC) +[o] about issue #43, raise if cron/every job frequency < scheduler frequency +[o] unlock spec/parse_spec.rb:30 "parse datimes with timezones" +[o] some kind of Schedulable (Xyz#call(job, time)) +[o] add Jruby and Rubinius to Travis +[o] make Job #first_at= / #last_at= automatically parse strings? +[o] bring in Kratob's spec about mutex vs timeout and adapt 3.0 to it, + https://github.com/jmettraux/rufus-scheduler/pull/67 +[x] :unschedule_if => lambda { |job| ... } +[o] OR look at how it was done in rs 2.0.x, some return value? + no, pass the job as arg to the block, then let the block do job.unschedule + so, document schedule.every('10d') { |j| j.unschedule if x?() } +[x] remove the time in job.trigger(time) +[o] add spec for job queued then unscheduled +[o] add spec for Scheduler#shutdown and work threads +[o] at some point, bring back rbx19 to Travis +[o] move the parse/util part of scheduler.rb to util.rb +[o] rescue KillSignal in job thread loop to kill just the job +[o] add spec for raise if scheduling a job while scheduler is shutting down +[o] schedule_in(2.days.from_now) {} + at and in could understand each others time parameter, ftw... + use the new #parse_to_time? no +[o] do repeat jobs reschedule after timing out? yes +[o] schedule_interval('20s')? +[x] Scheduler#reschedule(job) (new copy of the job) +[x] #free_all_work_threads is missing an implementation +[x] rescue StandardError + :on_error => :crash[_scheduler] + :on_error => :ignore + :on_error => ... +[o] on_error: what about TimeoutError in that scheme? + TimeoutError goes to $stderr, like a normal error +[o] link to SO for support + - sublink to "how to report bugs effectively" +[o] link to #ruote for support +[x] lockblock? pass a block to teach the scheduler how to lock? + is not necessary, @scheduler = Scheduler.new if should_start? + the surrounding Ruby code checks +[o] introduce job "vars", as in + http://stackoverflow.com/questions/18202848/how-to-have-a-variable-that-will-available-to-particular-scheduled-task-whenever + or job['key'] Job #[] and #[]=, as with Thread #[] #[]= + job-local variables #keys #key? +[o] thread-safety for job-local variables? +[x] discard past? discard_past => true or => "1d" + default would be discard_past => "1m" or scheduler freq * 2 ? + jobs would adjust their next_time until it fits the window... + ~~ discard past by default +[o] expanded block/schedulable (it's "callable") + ``` + scheduler.every '10m' do + def pre + return false if Backend.down? + # ... + end + def post + # ... + end + def trigger + puts "oh hai!" + end + end + ``` + or something like that... + ... + OR accept a class (and instantiate it the first time) + ``` + scheduler.every '10m', Class.new do + def call(job, time) + # ... + end + end + ``` + the job contains the instance in its @callable +[x] add spec case for corner case in Job#trigger (overlap vs reschedule) !!! +[o] rethink job array vs job set for #scheduled? +[x] introduce common parent class for EveryJob and IntervalJob +[o] create spec/ at_job_spec.rb, repeat_job_spec.rb, cron_job_spec.rb, ... +[x] ensure EveryJob do not schedule in the past (it's already like that) +[o] CronLine#next_time should return a time with subseconds chopped off +[o] drop min work threads setting? +[o] thread pool something? Thread upper limit? +[o] Rufus::Scheduler.singleton, Rufus::Scheduler.s +[o] EveryJob#first_at= and IntervalJob#first_at= should alter @next_time +[o] scheduler.schedule duration/time/cron ... for at/in/cron + (not every, nor interval) + scheduler.repeat time/cron ... for every/cron -[o] every -[o] cron +[o] :lockfile => x, timestamp, process_id, thread_id... + warning: have to clean up that file on exit... or does the scheduler + timestamps it? +[ ] develop lockfile timestamp thinggy + ~ if the timestamp is too old (twice the default frequency?) then + lock [file] take over... + Is that really what we want all the time? -[o] CHECK every and unschedule !!! +[ ] idea: :mutex => x and :skip_on_mutex => true ? + would prevent blocking/waiting for the mutex to get available + :mutex => [ "mutex_name", true ] + :mutex => [ [ "mutex_name", true ], [ "other_mutex_name", false ] ] -[o] :tags -[o] timeout feature (at/in/every/cron) in Job class +[ ] bring back EM (but only EM.defer ?) :defer => true (Job or Scheduler + or both option?) -[o] :first_in, :first_at +[ ] prepare a daemon, trust daemon-kit for that -[x] :dont_reschedule (or block returns false ?) +[ ] :if => lambda { |job, time| ... } why not? + :unless => lambda { ... + :block => lambda { ... + can help get the block themselves leaner + # + investigate guards for schedulables... def if_guard; ...; end -[o] [get_]jobs methods -[o] find methods - -[x] CTRL-C during tests : allow, trap_int... - -[o] 1.9 -[o] j1.2.0 - -[o] revise trigger block arity - use a compatibility switch ? yes - -[o] synchronize @cron_jobs ? - -[o] why not : make it work even if EM is not present - EmScheduler < Scheduler - FiberScheduler < Scheduler - -[x] :blocking => 'blockname' idea, mutex = @mutexes['blockname'] ... -[o] eventually, make sleep frequency customizable - -[o] PlainScheduler : name thread - -[o] document :blocking - -[o] README.rdoc -[o] fix jruby120 --em - -[o] handle_exception (job, e) - -[o] Schedulable - -[o] Rufus::Scheduler.start_new() : autodetect EM ? -[o] check :blocking and every (reschedule blocking...) -[o] document :thread_name scheduler option - -[o] unify cron_jobs#trigger_matching_jobs(now) and jobs#job_to_trigger -[o] pluggable job queues - -[ ] Joel's complaint about timeout jobs gone ballistic -[x] move trigger_job out of the scheduler +[ ] scheduler.every '10', Class.new do + def call(job, time) + # might fail... + end + def on_error(err, job) + # catches... + end + end