2013-07-11 18 views
1

我通過Clojure中進行並行http請求的例子工作,Clojure的代理中並行HTTP IllegalStateException異常並等待換

http://lethain.com/a-couple-of-clojure-agent-examples/

特別

(ns parallel-fetch 
    (:import [java.io InputStream InputStreamReader BufferedReader] 
      [java.net URL HttpURLConnection])) 

(defn get-url [url] 
    (let [conn (.openConnection (URL. url))] 
    (.setRequestMethod conn "GET") 
    (.connect conn) 
    (with-open [stream (BufferedReader. 
         (InputStreamReader. (.getInputStream conn)))] 
     (.toString (reduce #(.append %1 %2) 
          (StringBuffer.) (line-seq stream)))))) 

(defn get-urls [urls] 
    (let [agents (doall (map #(agent %) urls))] 
    (doseq [agent agents] (send-off agent get-url)) 
    (apply await-for 5000 agents) 
    (doall (map #(deref %) agents)))) 

(prn (get-urls '("http://lethain.com" "http://willarson.com"))) 

當我在運行此

IllegalStateException await-for in transaction 

這是什麼意思和 我如何解決它?

+0

奇怪...我只是嘗試了代碼,我沒有得到'IllegalStateException'異常。錯誤信息來自於['await-for']的定義(http://clojuredocs.org/clojure_core/clojure.core/await-for),但它只有在事務內部使用該函數時纔會顯示即在'dosync'中),因爲這就是'io!'宏的用途,而且我在代碼中看不到單個事務。 –

+0

您是否可以在移動'doseq'表單的最後一個關閉表達式以包含'(apply await-for)'時,檢查您是否沒有在'get-urls'中意外鍵入'doseq'作爲'dosync'。 ..)'在它的身體? –

+0

是的,雙重檢查。當我將代碼放入.clj文件,然後嘗試從repl中加載代碼時,出現此錯誤: IllegalStateException await-for在事務clojure.core中/ await-for(core.clj:2942)' –

回答

1

以議論的問題考慮在內:

事務正在建立中加載您的命名空間的過程,因爲它在頂層到get-urls通話時,await-for發生在事務並拋出異常。

解決該問題的最佳方法是將prn/get-urls表單放入函數中,並且只有在加載名稱空間後才調用它。 (如果你想在一個überjar運行此代碼作爲獨立的應用程序,與lein runjava -jar,你就會把調用該函數內部-main

順便說一句,本次交易設置當您使用:reload-all,但不是沒有它。 (見私有函數load-lib,其中檢查的:reload-all存在,並決定使用私有函數load-all如果它的存在,並load-all本身,這是在交易成立。Here's a link to the 1.5.1 source.