Index: common.scm ================================================================== --- common.scm +++ common.scm @@ -1688,12 +1688,52 @@ '(5 10 15 20 30 40 50 500)) (if values (apply values result) (values 0 day 1 0 'd)))) - - +;; given a cron string and the last time event was processed return #t to run or #f to not run +;; +;; min hour dayofmonth month dayofweek +;; 0-59 0-23 1-31 1-12 0-6 ### NOTE: dayofweek does not include 7 +;; +;; #t => yes, run the job +;; #f => no, do not run the job +;; +(define (common:cron-event cron-str ref-seconds last-done) ;; ref-seconds = #f is NOW. + (let ((cron-items (map string->number (string-split cron-str))) + (ref-time (seconds->local-time (or ref-seconds (current-seconds)))) + (last-done-time (seconds->local-time last-done))) + (print "cron-items: " cron-items "(length cron-items): " (length cron-items)) + (if (not (eq? (length cron-items) 5)) ;; don't even try to figure out junk strings + #f + (match-let ((( min hour dayofmonth month dayofweek) + cron-items) + ;; 0 1 2 3 4 5 6 + ((rsec rmin rhour rdayofmonth rmonth ryr rdayofweek r7 r8 r9) + (vector->list ref-time)) + ((csec cmin chour cdayofmonth cmonth cyr cdayofweek c7 c8 c9) + (vector->list last-done-time))) + (let ((have-match (and (or (not dayofweek) + (eq? dayofweek rdayofweek)) ;; either any dayofweek or they are same + (or (not month) + (eq? month (+ rmonth 1))) ;; posix time month is 0-11 + (or (not dayofmonth) + (eq? dayofmonth rdayofmonth)))) + (hour-match (or (not hour) + (eq? hour rhour))) + (min-match (or (not min) + (eq? min rmin)))) + ;; now inject non-"*" times into the ref-time + (vector-set! ref-time 0 0) ;; set seconds to zero + (if min (vector-set! ref-time 1 min)) + (if hour (vector-set! ref-time 2 hour)) + (let* ((ref-transition-seconds (local-time->seconds ref-time)) + (done-since (> last-done ref-transition-seconds))) + ;; (print "have-match: " have-match " hour-match: " hour-match " min-match: " min-match " ref-transition-seconds - last-done: " (- ref-transition-seconds last-done) " done-since: " done-since) + (and have-match + (not done-since)))))))) + ;;====================================================================== ;; C O L O R S ;;====================================================================== (define (common:name->iup-color name) Index: mtut.scm ================================================================== --- mtut.scm +++ mtut.scm @@ -244,12 +244,12 @@ (with-input-from-file pkt read-lines) "\n")) (apkt (convert-pkt->alist pktdat)) (ptype (alist-ref 'T apkt))) (add-to-queue pdb pktdat uuid (or ptype 'cmd) #f 0) - (print "Added " uuid " of type " ptype " to queue")) - (print "pkt: " uuid " exists, skipping...") + (debug:print 4 *default-log-port* "Added " uuid " of type " ptype " to queue")) + (debug:print 4 *default-log-port* "pkt: " uuid " exists, skipping...") ))) pkts)))) (string-split pktsdirs))))) ;;====================================================================== ADDED tests/unittests/cron.scm Index: tests/unittests/cron.scm ================================================================== --- /dev/null +++ tests/unittests/cron.scm @@ -0,0 +1,19 @@ + +(use test) + +;; S M H MD MTH YR WD +(define ref-time (vector 58 39 21 18 1 117 6 48 #f 25200)) + +(for-each + (lambda (situation crontab ref-seconds last-done expected) + (print "\nsituation: " situation) + (print "ref-seconds: " ref-seconds " = " (time->string (seconds->local-time ref-seconds))) + (print "last-done: " last-done " = " (time->string (seconds->local-time last-done))) + (print "crontab: " crontab) + (test #f expected (common:cron-event crontab ref-seconds last-done))) + '("midnight" "midnight, already done" "diffdate" "diffdate, already done" "diffday" "sameday, already done") + '("0 0 * * *" "0 0 * * *" "0 0 18 * *" "0 0 18 * *" "0 0 * * 5" "0 0 18 * 6" ) + '(1487489998.0 1487489998.0 1487489998.0 1487489998.0 1487489998.0 1487489998.0 ) + '(1487479198.0 1487489098.0 1487479198.0 1487489098.0 1487479198.0 1487489098.0 ) + '( #t #f #f #f #f #f ) + )