我正在玩future
,但似乎无法让它与javax.mail
一起工作。例如,为了好玩,我尝试设置一个 compojure 处理程序来抓取一堆电子邮件并将它们放入数据库中,但在收集和插入所有电子邮件之前向客户端发送响应。
我在 import-posts
函数中进行了一些 println
操作(如下),当我从 repl 运行它时,它工作正常,打印 142 日志消息。
第一次(因为数据库为空),没有新消息。
第二次。当我通过运行本地开发jetty服务器进行尝试时,每次加载页面时都会得到142日志消息
的println
输出,并且它们永远不会插入到数据库中。好的,然后我尝试将它们从 repl 导入数据库,然后从 jetty 尝试,每次仍然收到 142 条日志消息。实现这一目标的最佳方法是什么?
compojure 处理程序:
(GET "/" request
(if-let [usr_id (:id (friend/current-authentication))]
(friend/authorize
#{:pojagi.models.usr/user}
;; this is where I'm having trouble
(do (future (let [folder (mail/get-folder mail/gmail "Inbox")]
(println "importing emails from " (.getName folder) ".")
(mail/import-posts usr_id folder)))
(index/home)))
(index/index (:flash request))))
导入电子邮件的功能:
(defn import-posts
[usr_id ^javax.mail.Folder folder & {:keys [subject-term public?]}]
(let [messages (get-latest-messages usr_id folder)
journals (into [] (.search folder (SubjectTerm. (or subject-term "journal")) messages))]
(println (count journals) "journal messages.")
(if (< (count journals) 2)
(println "No new messages.")
(map
(fn [journal]
(println "inserting journal" (.getSubject journal))
(let [[title created bodyparts uid :as post] [(.getSubject journal)
(-> journal .getSentDate .getTime (java.sql.Timestamp.))
(-> journal .getContent)
(-> folder (.getUID journal))]
body (-> (.getBodyPart bodyparts 0)
.getDataHandler .getInputStream slurp md/md-to-html-string)]
(post/insert {:title title :body body :created created :usr_id 4 :public true :email_uid uid})
))
journals) )))
最佳答案
你可能被懒虫咬了:
如果你在 map
周围包裹一个doall
,它可能会有所帮助
(doall (map
(fn [journal]
或者dorun
如果你不想检查之后的结果(dorun就像doall一样,不保存整个序列,所以不太可能耗尽内存)
(dorun (map
(fn [journal]
当您从 repl 运行 import-posts 时,repl 会打印在期刊上映射 fn [journal]
的结果,这会导致将它们插入数据库的副作用。 当jetty运行时,什么都不看结果,序列保持延迟未实现,并且不会发生副作用。
关于multithreading - future 无法使用 javax.mail,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17436762/