@@ -7,6 +7,8 @@ import NIOConcurrencyHelpers
77internal struct MongocCursor : MongocCursorWrapper {
88 internal let pointer : OpaquePointer
99
10+ internal static var isLazy : Bool { return true }
11+
1012 internal init ( referencing pointer: OpaquePointer ) {
1113 self . pointer = pointer
1214 }
@@ -39,24 +41,6 @@ public class MongoCursor<T: Codable>: CursorProtocol {
3941 /// Decoder from the client, database, or collection that created this cursor.
4042 internal let decoder : BSONDecoder
4143
42- /// Used to store a cached next value to return, if one exists.
43- private enum CachedDocument {
44- /// Indicates that the associated value is the next value to return. This value may be nil.
45- case cached( T ? )
46- /// Indicates that there is no value cached.
47- case none
48-
49- /// Get the contents of the cache and clear it.
50- fileprivate mutating func clear( ) -> CachedDocument {
51- let copy = self
52- self = . none
53- return copy
54- }
55- }
56-
57- /// Tracks the caching status of this cursor.
58- private var cached : CachedDocument
59-
6044 /**
6145 * Initializes a new `MongoCursor` instance. Not meant to be instantiated directly by a user. When `forceIO` is
6246 * true, this initializer will force a connection to the server if one is not already established.
@@ -75,25 +59,13 @@ public class MongoCursor<T: Codable>: CursorProtocol {
7559 ) throws {
7660 self . client = client
7761 self . decoder = decoder
78- self . cached = . none
7962
8063 self . wrappedCursor = try Cursor (
8164 mongocCursor: MongocCursor ( referencing: cursorPtr) ,
8265 connection: connection,
8366 session: session,
8467 type: cursorType ?? . nonTailable
8568 )
86-
87- let next = try self . decode ( result: self . wrappedCursor. tryNext ( ) )
88- self . cached = . cached( next)
89- }
90-
91- /// Close this cursor
92- ///
93- /// This method should only be called while the lock is held.
94- internal func blockingKill( ) {
95- self . cached = . none
96- self . wrappedCursor. kill ( )
9769 }
9870
9971 /// Asserts that the cursor was closed.
@@ -111,12 +83,7 @@ public class MongoCursor<T: Codable>: CursorProtocol {
11183
11284 /// Decodes the given document to the generic type.
11385 private func decode( doc: Document ) throws -> T {
114- do {
115- return try self . decoder. decode ( T . self, from: doc)
116- } catch {
117- self . blockingKill ( )
118- throw error
119- }
86+ return try self . decoder. decode ( T . self, from: doc)
12087 }
12188
12289 /**
@@ -130,9 +97,6 @@ public class MongoCursor<T: Codable>: CursorProtocol {
13097 * This cursor will be dead as soon as `next` returns `nil` or an error, regardless of the `CursorType`.
13198 */
13299 public var isAlive : Bool {
133- if case . cached = self . cached {
134- return true
135- }
136100 return self . wrappedCursor. isAlive
137101 }
138102
@@ -147,37 +111,6 @@ public class MongoCursor<T: Codable>: CursorProtocol {
147111 }
148112 }
149113
150- /**
151- * Consolidate the currently available results of the cursor into an array of type `T`.
152- *
153- * If this cursor is not tailable, this method will exhaust it.
154- *
155- * If this cursor is tailable, `all` will only fetch the currently available results, and it
156- * may return more data if it is called again while the cursor is still alive.
157- *
158- * - Returns:
159- * An `EventLoopFuture<[T]>` evaluating to the results currently available to this cursor or an error.
160- *
161- * If the future evaluates to an error, that error is likely one of the following:
162- * - `CommandError` if an error occurs while fetching more results from the server.
163- * - `LogicError` if this function is called after the cursor has died.
164- * - `LogicError` if this function is called and the session associated with this cursor is inactive.
165- * - `DecodingError` if an error occurs decoding the server's responses.
166- */
167- internal func all( ) -> EventLoopFuture < [ T ] > {
168- return self . client. operationExecutor. execute {
169- var results : [ T ] = [ ]
170- if case let . cached( result) = self . cached. clear ( ) , let unwrappedResult = result {
171- results. append ( unwrappedResult)
172- }
173- // If the cursor still could have more results after clearing the cache, collect them too.
174- if self . isAlive {
175- results += try self . wrappedCursor. all ( ) . map { try self . decode ( doc: $0) }
176- }
177- return results
178- }
179- }
180-
181114 /**
182115 * Attempt to get the next `T` from the cursor, returning `nil` if there are no results.
183116 *
@@ -200,10 +133,7 @@ public class MongoCursor<T: Codable>: CursorProtocol {
200133 */
201134 public func tryNext( ) -> EventLoopFuture < T ? > {
202135 return self . client. operationExecutor. execute {
203- if case let . cached( result) = self . cached. clear ( ) {
204- return result
205- }
206- return try self . decode ( result: self . wrappedCursor. tryNext ( ) )
136+ try self . decode ( result: self . wrappedCursor. tryNext ( ) )
207137 }
208138 }
209139
@@ -226,15 +156,30 @@ public class MongoCursor<T: Codable>: CursorProtocol {
226156 */
227157 public func next( ) -> EventLoopFuture < T ? > {
228158 return self . client. operationExecutor. execute {
229- if case let . cached( result) = self . cached. clear ( ) {
230- // If there are no more results forthcoming after clearing the cache, or the cache had a non-nil
231- // result in it, return that.
232- if !self . isAlive || result != nil {
233- return result
234- }
235- }
236- // Otherwise iterate until a result is received.
237- return try self . decode ( result: self . wrappedCursor. next ( ) )
159+ try self . decode ( result: self . wrappedCursor. next ( ) )
160+ }
161+ }
162+
163+ /**
164+ * Consolidate the currently available results of the cursor into an array of type `T`.
165+ *
166+ * If this cursor is not tailable, this method will exhaust it.
167+ *
168+ * If this cursor is tailable, `toArray` will only fetch the currently available results, and it
169+ * may return more data if it is called again while the cursor is still alive.
170+ *
171+ * - Returns:
172+ * An `EventLoopFuture<[T]>` evaluating to the results currently available in this cursor, or an error.
173+ *
174+ * If the future evaluates to an error, that error is likely one of the following:
175+ * - `CommandError` if an error occurs while fetching more results from the server.
176+ * - `LogicError` if this function is called after the cursor has died.
177+ * - `LogicError` if this function is called and the session associated with this cursor is inactive.
178+ * - `DecodingError` if an error occurs decoding the server's responses.
179+ */
180+ public func toArray( ) -> EventLoopFuture < [ T ] > {
181+ return self . client. operationExecutor. execute {
182+ try self . wrappedCursor. toArray ( ) . map { try self . decode ( doc: $0) }
238183 }
239184 }
240185
@@ -249,7 +194,7 @@ public class MongoCursor<T: Codable>: CursorProtocol {
249194 */
250195 public func kill( ) -> EventLoopFuture < Void > {
251196 return self . client. operationExecutor. execute {
252- self . blockingKill ( )
197+ self . wrappedCursor . kill ( )
253198 }
254199 }
255200}
0 commit comments