Clojure Futures & Promises – done the wrong way…

I have an interest in Clojure and figured I would mess about with futures and promises.  The general idea is that two sets of long running jobs are created and kicked off at the same time – both are a lazy collection of futures.  There’s a third process that requires the results of these before it can start, in order for this to happen a function is created that takes the two vectors of futures, kicks them off an the polls for completion – (every? realized? <jobs>).  Once a set of jobs is completed a promise is updated (deliver <my-promise> <the-value>), and once both are complete the third task can be kicked off.

As per usual, there is probably a better &| idiomatic way to do this, however it does function as intended. You need to look past the Thread/sleeps …

(defn simple-log [msg]
  (spit "/tmp/ftr.log" (str msg "\n") :append true))

(defn create-jobs [jobs]
 (map (fn [job-id]
   (future (do
     (simple-log (str "Starting job: " job-id))
     (Thread/sleep (rand-int 5000))
     (simple-log (str "Finishing job: " job-id))))) jobs))

(defn jobs-complete? [running-tasks id some-promise]
 (if (every? realized? running-tasks)
   (do (simple-log (str "job " id " set complete"))
     (deliver some-promise true))
   (do (simple-log "waiting ...")
       (Thread/sleep 100)
       (recur running-tasks id some-promise))))

(defn runner [jobs id some-promise]
 (let [running-tasks (doall jobs)]
   (jobs-complete? running-tasks id some-promise)))

(def job-set-1 (create-jobs (range 1 100)))
(def job-set-2 (create-jobs (range 100 200)))
(def set-1-complete (promise))
(def set-2-complete (promise))

(runner job-set-1 :a set-1-complete)
(runner job-set-2 :b set-2-complete)

(if (and @set-1-complete @set-2-complete) (simple-log "ALL JOBS DONE!"))


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s