; TODO read jovs specification from filesystem (include "/usr/local/var/mlisp/terminal.lsp") (defn cron::sleep-to-next-minute () (* 1000 (- 60 (int (date-to-str (get-universal-time) "%S"))))) (defn cron::eval-time-spec (val time_spec) (cond ((nil? time_spec) #t) ; no time_spec -> it's true ((= time_spec "*") #t) ((string-regex? time_spec "^[0-9]{1,4}$") (= val (int time_spec))) ((string-regex? time_spec "^[0-9]{1,2}-[0-9]{1,2}$") (def interval (string-split time_spec "-")) (and (>= val (int (first interval))) (<= val (int (second interval))))) (#t nil) ; TODO exception ) ) (defn cron::add-job (name time_spec job) ; TODO if already there replace it (set! cron::entries (push cron::entries (list name time_spec job))) ) (defn cron::time-to-run (now time_spec) (do ; second, minute, hour, day, month, year, day-of-the-week (def time (decode-universal-time (get-universal-time))) (def time_minute (second time)) (def time_hour (third time)) (def time_day (fourth time)) (def time_month (fifth time)) (def time_year (sixth time)) (def time_weekday (seventh time)) (def bool (cron::eval-time-spec time_minute (find-val-in-list time_spec "minute"))) (set! bool (and bool (cron::eval-time-spec time_hour (find-val-in-list time_spec "hour")))) (set! bool (and bool (cron::eval-time-spec time_weekday (find-val-in-list time_spec "weekday")))) (set! bool (and bool (cron::eval-time-spec time_day (find-val-in-list time_spec "day")))) (set! bool (and bool (cron::eval-time-spec time_month (find-val-in-list time_spec "month")))) (set! bool (and bool (cron::eval-time-spec time_year (find-val-in-list time_spec "year")))) ; (print "time-to-run test" bool) bool )) (defn cron::run-job (name code) (do ;(print "running job:" name "->" code) (def run_code (+ "(thread-create " (display code) ")")) (eval (parse run_code)) ) ) (defn cron::start () (do (def wait_time (cron::sleep-to-next-minute)) (print "cron daemon started, waiting" wait_time "miliseconds for first run") ; (thread-sleep wait_time) (while (not cron::stop) (def now (get-universal-time)) (for e cron::entries (def job_name (first e)) (def time_spec (second e)) (def job_code (third e)) ; (print "\n\n") (def is_for_run (cron::time-to-run now time_spec)) ; (print "DEBUG" job_name "checked" is_for_run) (if is_for_run (cron::run-job job_name job_code) ; (print "not running" job_name) ) ) (thread-sleep (cron::sleep-to-next-minute)) ) (threads-join) )) (defn cron::stop () (set! cron::stop #t)) (def cron::entries '()) ; must be here (def cron::stop nil) ; must be here (cron::add-job "every_min_print" '(("minute" "*")) '(print "executing: every_min_print")) ; '(do (sleep 3) (print "executing: every_min_print"))) (cron::add-job "every_min_between_00_and_05" '(("minute" "00-05")) '(print "executing: every_min_between_00_and_05")) (cron::add-job "13:20_working_day" '(("weekday" "1-5")("hour" "13")("minute" "20")) '(print "executing: 13:20_working_day")) (cron::add-job "15:20_working_day" '(("weekday" "1-5")("hour" "15")("minute" "20")) '(print "executing: 15:20_working_day")) (cron::start)