2013-07-11 6 views
1

Я работаю на примере создания параллельных запросов HTTP в Clojure,Clojure Агент Parellel 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

Weird ... Я просто попробовал код, и я не получаю исключение 'IllegalStateException'. Сообщение об ошибке исходит из defintion для ['await-for'] (http://clojuredocs.org/clojure_core/clojure.core/await-for), но оно должно отображаться только тогда, когда эта функция используется внутри транзакции (т.е. внутри 'dosync'), так как это макрос' io! ', и я не вижу ни одной транзакции в вашем коде. –

+0

Не могли бы вы дважды проверить, что вы случайно не набрали 'dosq' как' dosync' в 'get-urls', а также перемещаете заключительный паттерн закрытия формы' dosq', чтобы включить '(apply await-for. ..) 'в своем теле? –

+0

Да, дважды проверено. Я получаю эту ошибку, когда я помещаю код в файл .clj, а затем пытаюсь загрузить его из repl: '(используйте 'parallel-fetch: reload-all) IllegalStateException ждет в транзакции clojure.core/await-for (core.clj: 2942) ' –

ответ

1

Принимая комментарий по этому вопросу во внимание:

Транзакция создается в процессе загрузки пространства имен, и так как он имеет вызов get-urls на верхнем уровне await-for происходит в том, что транзакции и выбрасывает исключение.

Лучший способ исправить это, чтобы поместить форму prn/get-urls внутри функции и вызвать ее только после загрузки пространства имен. (Если вы хотите, чтобы запустить этот код, как автономное приложение, с lein run или java -jar на überjar, вы бы поместить вызов этой функции внутри -main.)

Кстати, сделка устанавливается при использовании :reload-all, но не без него. (См частных функций load-lib, который проверяет наличие :reload-all и решает использовать частную функцию load-all, если она есть, и load-all себя, что если сделка установлена. Here's a link to the 1.5.1 source.)