From d51c61d7983a1247bb7956e66d0d7f91512ac4d7 Mon Sep 17 00:00:00 2001 From: Tim Clemons Date: Tue, 19 Nov 2013 17:45:12 -0800 Subject: [PATCH] Enclose cursor operations in a with-yielding call. The with-yielding call will produce a lazy-seq in a separate thread that will generate content from the cursor. The cursor will then be safely closed if the seq is garbage collected or an error occurs. --- project.clj | 3 ++- src/clojure/monger/query.clj | 23 +++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/project.clj b/project.clj index 1f74b94..66fe1d4 100644 --- a/project.clj +++ b/project.clj @@ -7,7 +7,8 @@ [org.mongodb/mongo-java-driver "2.11.2"] [com.novemberain/validateur "1.5.0"] [clojurewerkz/support "0.19.0"] - [ragtime/ragtime.core "0.3.4"]] + [ragtime/ragtime.core "0.3.4"] + [clj-yield "1.1"]] :test-selectors {:default (fn [m] (and (not (:performance m)) (not (:edge-features m)) diff --git a/src/clojure/monger/query.clj b/src/clojure/monger/query.clj index bae17bf..cce2694 100644 --- a/src/clojure/monger/query.clj +++ b/src/clojure/monger/query.clj @@ -18,7 +18,8 @@ [monger.cursor :as cursor :refer [add-options]]) (:import [com.mongodb DB DBCollection DBObject DBCursor ReadPreference] [java.util List]) - (:use [monger conversion operators])) + (:use [monger conversion operators] + [yield])) ;; @@ -65,21 +66,23 @@ (defn exec [{ :keys [^DBCollection collection query fields skip limit sort batch-size hint snapshot read-preference keywordize-fields options] :or { limit 0 batch-size 256 skip 0 } }] - (with-open [cursor (doto (.find collection (to-db-object query) (as-field-selector fields)) + (with-yielding [y-out 1] + (with-open [cursor (doto (.find collection (to-db-object query) (as-field-selector fields)) (.limit limit) (.skip skip) (.sort (to-db-object sort)) (.batchSize batch-size) (.hint (to-db-object hint)))] - (when snapshot - (.snapshot cursor)) - (when read-preference - (.setReadPreference cursor read-preference)) - (when options + (when snapshot + (.snapshot cursor)) + (when read-preference + (.setReadPreference cursor read-preference)) + (when options (add-options cursor options)) - (map (fn [x] (from-db-object x keywordize-fields)) - cursor))) - + (loop [] + (when (.hasNext cursor) + (yield y-out (from-db-object (.next cursor) keywordize-fields)) + (recur)))))) ;; ;; API ;;