Advertisement
Guest User

Untitled

a guest
Nov 29th, 2018
112
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. (ns task-scheduler.lib.routine
  2.   (:require
  3.     [clojure.core.async :as a :refer [go go-loop close! chan <! >! put! alt! timeout pipe]])
  4.   (:import [clojure.core.async.impl.channels ManyToManyChannel]))
  5.  
  6. ; effects
  7. ; ----------------------------
  8. (defn effect [c name & args]
  9.   (let [res-chan (chan)]
  10.     (put! c {:name name :args args :res-chan res-chan})
  11.     res-chan))
  12.  
  13. (defmulti handle-effect
  14.   (fn [effect] (:name effect)))
  15.  
  16. (defmethod handle-effect :call [{:keys [args]}]
  17.   (apply (first args) (rest args)))
  18.  
  19. (defmethod handle-effect :timeout [{:keys [args]}]
  20.   (timeout (first args)))
  21.  
  22. (defn closed? [c]
  23.   (go (alt! c true :default false)))
  24.  
  25. (defn ensure-chan [v]
  26.     (if (instance? ManyToManyChannel v)
  27.       v
  28.       (let [c (chan 1)]
  29.         (if (nil? v) (close! c) (put! c v (fn [_] (close! c))))
  30.         c)))
  31.  
  32.  
  33. (defn routine-impl [handler]
  34.   (let [process-chan (chan)
  35.         close-chan (chan)]
  36.     (handler (partial effect process-chan))
  37.     (go-loop []
  38.       (when-let [{:keys [res-chan] :as effect} (<! process-chan)]
  39.         (when-not (<! (closed? close-chan))
  40.           (let [result (handle-effect effect)]
  41.             (pipe (ensure-chan result) res-chan))
  42.           (recur))))
  43.     close-chan))
  44.  
  45. (defmacro routine [& args]
  46.   `(routine-impl (fn [~'effect] (go ~@args))))
  47.  
  48. ;; usage example
  49.  
  50. (def sample-routine
  51.   (routine
  52.     (<! (effect :call println "I am performing some side-effect"))  
  53.     (<! (effect :timeout 5000))
  54.     (<! (effect :call println "It seems I won't be called if routine gets canceled"))))
  55.                  
  56. (go
  57.   (<! (timeout 3000))
  58.   (println "canceling routine")
  59.   (close! sample-routine))
  60.  
  61.  
  62. (Thread/sleep 10000)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement