parameterize the executor
jasonjckn opened this issue · 1 comments
jasonjckn commented
Hey, thanks for this library, exactly what I needed,
Instead of defaulting to Executors/newSingleThreadScheduledExecutor, can we get this parameterized, e.g. as a kwargs to chime-at. The reason for this is i'm trying to write unit tests with simulated time that aren't multi-threaded and mocked out the java.util.concurrent.ScheduledExecutorService interface.
Thanks!
jasonjckn commented
here's an example of a simulated time executor, could be useful...
(defprotocol PSimulatedTime
(advance-time [this amount])
(current-time [this]))
(def my-simuated-time-executor
(let [shutdown? (atom false)
simulated-clock (atom (chime/now)) ;; initially set simulated time to 'NOW' / bios clock time, but from here it diveats
scheduled-tasks (atom #{})
]
(reify
java.util.concurrent.ScheduledExecutorService
(^java.util.List shutdownNow [this] (reset! shutdown? true) nil)
(^void shutdown [this] (reset! shutdown? true))
(^boolean isShutdown [this] @shutdown?)
(^java.util.concurrent.ScheduledFuture schedule [this ^Runnable task, ^long delay, ^TimeUnit unit ]
(swap! scheduled-tasks
conj
{:task task,
:scheduled-at (jt/plus @simulated-clock (quantity+time-unit->duration delay unit))})
nil)
PSimulatedTime
(current-time [this] @simulated-clock)
(advance-time [this duration]
(swap! simulated-clock jt/plus duration)
(let [tasks-ready-to-run (into #{}
(filter #(<=java-time (:scheduled-at %) @simulated-clock))
@scheduled-tasks)]
(doseq [{:keys [task]} tasks-ready-to-run]
(.run ^Runnable task))
(swap! scheduled-tasks set/difference tasks-ready-to-run)
(if (seq tasks-ready-to-run)
(recur (jt/millis 0))))))))