jarohen/chime

parameterize the executor

jasonjckn opened this issue · 1 comments

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!

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))))))))