Implementing a cron type scheduler in clojure
clojure
Solution
I needed something that
- started scheduled tasks at whole-second intervals as opposed to whole minute intervals having high system-time accuracy.
- would spawn as many threads as needed, so that tasks started at earlier intervals could exist along side tasks started at later intervals.
After doing a bit of source code reading for at-at, Monotony and Quartzite, I felt that they did not fit the requirements that I was after (which was really something more bare bone) so I wrote my own - cronj
An example of the usage.
(require '[cronj.core :as cj])
(cj/schedule-task! {:id 0 :desc 0
:handler #(println "job 0:" %)
:tab "/5 * * * * * *"}) ;; every 5 seconds
(cj/schedule-task! {:id 1 :desc 1
:handler #(println "job 1:" %)
:tab "/3 * * * * * *"}) ;; every 3 seconds
(cj/start!)
;; wait for scheduler to do its thing ......
(cj/stop!)
Problem
I'm looking for any way for clojure that can trigger an event at a given time, For example: I want a particular process to start at 9:30am and then I can trigger another process to start running half an hour later etc. Thanks in advance! Updated 2: Thanks @arthur-ulfeoldt and @unknown-person who also suggested using https://github.com/samaaron/at-at before deleting his answer. The documentation is a little out of date but here's how I got going. ``` (use 'overtone.at-at) (def my-pool (mk-pool)) ;=> make a thread pool (every 1000 #(println "I am super cool!") my-pool :initial-delay 2000) ;=> starts print function every 1 sec after a 2 sec delay (stop *1) ;=> stops it ``` So to make it start at exactly 9, with an interval of half an hour, I would do: ``` (require '[clj-time.core :as t]) (require '[clj-time.coerce :as c]) (use 'overtone.at-at) ;Make Thread Pool (def my-pool (mk-pool)) (def current-time (t/now)) (def current-date (t/date-time (t/year current-time) (t/month current-time) (t/day current-time))) (def next-9-oclock (if (> 9 (t/hour current-time)) (t/plus current-date (t/hours 9)) (t/plus current-date (t/days 1) (t/hours 9)))) (def initial-delay (- (c/to-long next-9-oclock) (c/to-long current-time)) (every 1800000 #(println "I am super cool!") my-pool :initial-delay initial-delay) ``` Updated: @arthur-ulfeoldt, I am not sure how to translate some of the java code into clojure. http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ScheduledExecutorService.html like: ``` final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); ``` and: ``` final Runnable beeper = new Runnable() { public void run() { System.out.println("beep"); } }; ``` Entire Example ``` class BeeperControl { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public void beepForAnHour() { final Runnable beeper = new Runnable() { public void run() { System.out.println("beep"); } }; final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); scheduler.schedule(new Runnable() { public void run() { beeperHandle.cancel(true); } }, 60 * 60, SECONDS); } } ```