(await & agents)
Blocks the current thread (indefinitely!) until all actions dispatched thus far, from this thread or agent, to the agent(s) have occurred. Will block on failed agents. Will never return if a failed agent is restarted with :clear-actions true.
;; construct a simple agent
(def *agnt* (agent {}))
(send-off *agnt* (fn [state]
(Thread/sleep 10000)
(assoc state :done true)))
;;=> <Agent@5db18235: {}>
;; blocks till the agent action is finished
(await *agnt*)
;;=> nil
(import '(java.io BufferedWriter FileWriter))
;; Generally the agent can be sent messages asynchronously, send and forget.
;; In some cases a rendezvous is needed, e.g. in the case of an output file.
(def write-out
(agent {:handle (clojure.java.io/writer "results.txt" )
:last-msg ["init"]}
:validator (fn [state]
(and (contains? state :handle) (contains? state :last-msg)))
:error-handler (fn [result]
(println "invalid result") )))
(defn write-a-line [state msg nap]
(.write (:handle state) (str msg " line " "\
"))
(let [new-state (update-in state [:last-msg] into [msg])]
(println "message : " msg " : " new-state)
(Thread/sleep nap)
new-state))
;; these all have the same return value
(send-off write-out write-a-line "first" 2000)
(send-off write-out write-a-line "second" 1000)
(send-off write-out write-a-line "third" 5000)
(send-off write-out write-a-line "fourth" 1000)
@write-out
;;=> {:handle #<BufferedWriter java.io.BufferedWriter@e175cca>, :last-msg ["init"]}
(time (await write-out))
;; 9000.307 msecs
;; here we can see that the await causes the thread to block
;; until the agent's queue is empty.
@write-out
;;=> {:handle #<BufferedWriter java.io.BufferedWriter@e175cca>,
;; :last-msg ["init" "first" "second" "third" "fourth"]}
;; But wait the "result.txt" file is empty!
;; We need to close the file handle.
;; And now that we know the agent's queue is empty we
;; are free to close it.
;; This could do this in the current thread with the dereferenced
;; agents :handle '(.close (:handle @write-out))'
;; but it is probably better to be formal and let the agent do it.
(defn close-the-agent [state]
(.close (:handle state))
state)
(send-off write-out close-the-agent)
;; And the contents of "result.txt" are: (less the leading '; ')
; first line
; second line
; third line
; fourth line