Multithreading future不使用javax.mail

Multithreading future不使用javax.mail,multithreading,clojure,jakarta-mail,future,Multithreading,Clojure,Jakarta Mail,Future,我正在玩future,似乎无法让它与javax.mail一起工作。例如,为了好玩,我尝试设置一个compojure处理程序来抓取一堆电子邮件并将它们放入数据库,但在收集和插入所有电子邮件之前向客户端发送响应 我在import posts功能(如下)中有一些println正在进行,当我从repl运行此功能时,它工作正常,第一次打印了142条日志消息。因为数据库是空的,没有新消息。第二次。当我通过运行本地开发jetty服务器进行尝试时,每次加载页面时,我都会得到println输出的142条日志消息,

我正在玩
future
,似乎无法让它与
javax.mail
一起工作。例如,为了好玩,我尝试设置一个compojure处理程序来抓取一堆电子邮件并将它们放入数据库,但在收集和插入所有电子邮件之前向客户端发送响应

我在
import posts
功能(如下)中有一些
println
正在进行,当我从repl运行此功能时,它工作正常,第一次打印了142条日志消息。因为数据库是空的,
没有新消息。
第二次。当我通过运行本地开发jetty服务器进行尝试时,每次加载页面时,我都会得到
println
输出的
142条日志消息
,而且它们永远不会被插入数据库。好的,然后我试着从repl将它们导入db,然后从jetty尝试,每次我仍然得到142条日志消息。实现这一目标的最佳方式是什么

复合处理程序: 导入电子邮件的功能:
(defn导入帖子)
[usr_id^javax.mail.Folder文件夹&{:keys[subject term public?]}]
(让[消息(获取最新消息usr_id文件夹)
日记账(进入[](.search文件夹(主题词(或主题词“日记”))邮件))]
(println(计数日记账)“日记账消息”)
(如果(<(盘点日记帐)2)
(println“无新消息”)
(地图
(fn[期刊]
(打印“插入日记账”(.getSubject日记账))
(让[[title-created-bodyparts-uid:as-post][(.getSubject-journal)
(->journal.getSentDate.getTime(java.sql.Timestamp.))
(->journal.getContent)
(->文件夹(.getUID日志))]
车身(->(.getBodyPart车身部件0)
.getDataHandler.getInputStream slurp md/md到html字符串)]
(post/insert{:title:body body:created:usr_id 4:public true:email_id})
))
期刊))

您可能已经被懒惰的bug咬到了:

如果将
doall
包裹在
map
周围,可能会有所帮助

(doall (map
    (fn [journal]

或者
dorun
如果您不想在之后检查结果(dorun类似于doall,不保存整个序列,因此不太可能耗尽内存)


当您从repl运行导入文章时,repl会打印将
fn[journal]
映射到日志的结果,这会导致将日志插入数据库的副作用。当jetty运行这个程序时,什么都不看结果,这个序列仍然懒散地没有实现,副作用也不会发生

由于内存不足,我也尝试了
,最后我发现
doseq
对于这种产生副作用的活动来说是一个可行的选择,因为它不会试图将整个集合保存在内存中:

(defn import-posts
  [usr_id ^javax.mail.Folder folder & {:keys [subject-term public?]}]
  (let [last-uid (post/last-uid usr_id)
        messages (get-latest-messages usr_id folder last-uid)
        journals (into [] (.search folder (SubjectTerm. (or subject-term "journal")) messages))]
    (if (and (< (count journals) 2)
             (= last-uid (-> folder (.getUID (first journals)))))
      (println "No new messages.")
      (doseq [import (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)]
        import))))
(defn导入帖子)
[usr_id^javax.mail.Folder文件夹&{:keys[subject term public?]}]
(let[last uid(post/last uid usr\U id)
消息(获取最新消息usr\U id文件夹最后一个uid)
日记账(进入[](.search文件夹(主题词(或主题词“日记”))邮件))]
(如果(和(<(盘点日记帐)2)
(=最后一个uid(->文件夹(.getUID(第一个日记账щщ)]))
(println“无新消息”)
(doseq[导入(映射)
(fn[期刊]
(打印“插入日记账”(.getSubject日记账))
(让[[title-created-bodyparts-uid:as-post][(.getSubject-journal)
(->journal.getSentDate.getTime(java.sql.Timestamp.))
(->journal.getContent)
(->文件夹(.getUID日志))]
车身(->(.getBodyPart车身部件0)
.getDataHandler.getInputStream slurp md/md到html字符串)]
(发布/插入{:标题:正文正文:已创建:usr_id 4:public true:email_id})
期刊)]
(进口)

hehe,这是我对这类常见bug的昵称,因为REPL正在打印结果,所以只在REPL中工作,然后在生产中什么也不会发生。我只是觉得它有一个很好的环:-)事实上,这个答案是有问题的,因为它在27封电子邮件之后停止导入(因为它耗尽了内存)。如果你能避开懒惰和内存不足的问题,你怎么能做到呢?多伦就像多尔一样,不掌握整个过程。我在你的答案中添加了这条评论,并接受了。再次感谢!
(doall (map
    (fn [journal]
(dorun (map
    (fn [journal]
(defn import-posts
  [usr_id ^javax.mail.Folder folder & {:keys [subject-term public?]}]
  (let [last-uid (post/last-uid usr_id)
        messages (get-latest-messages usr_id folder last-uid)
        journals (into [] (.search folder (SubjectTerm. (or subject-term "journal")) messages))]
    (if (and (< (count journals) 2)
             (= last-uid (-> folder (.getUID (first journals)))))
      (println "No new messages.")
      (doseq [import (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)]
        import))))