Какой самый простой способ запланировать функцию, которая будет вызываться ежедневно в полночь с Clojure? - PullRequest
1 голос
/ 14 февраля 2020

Хотя можно использовать потоки и устанавливать тайм-аут для запуска функции через заданные интервалы времени с момента запуска нового потока, как сделать так, чтобы функция запускалась в 00:00:00, начиная со следующей полуночи?

Ответы [ 3 ]

1 голос
/ 15 февраля 2020

Вы также можете взглянуть на библиотеку chime .

Я не тестировал этот код, но что-то вроде этого.

(ns my.example
  (:require [chime :refer [chime-at]])
  (:import  [java.time Instant LocalTime ZonedDateTime ZoneId Period]))

(defn my-task []
  (println "Executing a task"))

(defn periodic-seq [^Instant start duration-or-period]
  (iterate #(.addTo duration-or-period %) start)) ;; produces a lazy-seq of Instants

;; generates infinite sequence of days. Change the time zone to the one you need. 
(def days 
  (periodic-seq (-> (LocalTime/of 23 0 0) 
                    (.adjustInto (ZonedDateTime/now (ZoneId/of "America/New_York")))
                    .toInstant)
                (Period/ofDays 1)))

(chime-at days (fn [time] (my-task)))        

chime-at возвращает функция с нулевым аргументом, которую можно вызвать, чтобы отменить расписание. Таким образом, вы должны начать график, как это.

(def cancel (chime-at days (fn [time] my-task)))
(cancel) 

Опять же, я не проверял этот код.

1 голос
/ 14 февраля 2020

Просто используйте java.util.Timer: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Timer.html#schedule (java .util.TimerTask, java .util.Date)

public void schedule​(TimerTask task, Date time)

Schedules the specified task for execution at the specified time. If the time is in the past, the task is scheduled for immediate execution.

Parameters:
   task - task to be scheduled.
   time - time at which task is to be executed.

Похоже на ScheduledThreadPoolExecutor немного новее и имеет некоторые улучшения. Esp see

scheduleAtFixedRate​(Runnable command, long initialDelay, 
                    long period, TimeUnit unit) 

Отправляет действие periodi c, которое становится доступным сначала после заданной начальной задержки, а затем с заданным периодом; то есть выполнение начнется после initialDelay, затем initialDelay + period, затем initialDelay + 2 * period и т. д.


Вас также может заинтересовать at-at library: https://github.com/overtone/at-at

0 голосов
/ 16 февраля 2020

Вы можете взаимодействовать с любой Java библиотекой, такой как Quartz, cron4j или Java с самим таймером. Чтобы сделать его более идиоматичным c для Clojure, вы также можете написать макрос (или пару функций) для упрощения вещей. Например, с помощью макроса roll-your-own:

(deftask my-midnight-task
  "0 0 * * 2-6"
  (println "start to work")
  (do-something))

, где "0 0 * * 2-6" - шаблон типа cron, используемый в cron4j . Реализация здесь использует mount для планирования и планирования:

(defonce ^Scheduler scheduler (doto (Scheduler.)
                                (.setDaemon true)
                                (.start)))

(defmacro deftask [name cron & body]
  `(defstate ~name
     :start (.schedule scheduler ~cron (fn [] ~@body))
     :stop  (.deschedule scheduler ~name)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...