@@ -98,6 +98,13 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
9898 /// Indicates that the cursor is still open. Stores a `MongocCursorWrapper`, along with the source
9999 /// connection, and possibly session to ensure they are kept alive as long as the cursor is.
100100 case open( cursor: CursorKind , connection: Connection , session: ClientSession ? )
101+
102+ /// Indicates the cursor last returned an error from `next`. `nil` will be returned if
103+ /// `next` is called again, and the cursor will be moved to `closed` state.
104+ case error
105+
106+ /// Indicates the cursor has completed iteration, either by exhausting its results or by returning
107+ /// an error and then `nil`.
101108 case closed
102109 }
103110
@@ -186,13 +193,13 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
186193
187194 guard mongocCursor. next ( outPtr: out) else {
188195 if let error = self . getMongocError ( ) {
189- self . close ( )
196+ self . close ( fromError : true )
190197 throw error
191198 }
192199
193200 // if we've reached the end of the cursor, close it.
194201 if !self . type. isTailable || !mongocCursor. more ( ) {
195- self . close ( )
202+ self . close ( fromError : false )
196203 }
197204
198205 return nil
@@ -209,12 +216,17 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
209216 /// Close this cursor
210217 ///
211218 /// This method should only be called while the lock is held.
212- private func close( ) {
219+ private func close( fromError : Bool ) {
213220 guard case let . open( mongocCursor, _, _) = self . state else {
214221 return
215222 }
216223 mongocCursor. destroy ( )
217- self . state = . closed
224+
225+ if fromError {
226+ self . state = . error
227+ } else {
228+ self . state = . closed
229+ }
218230 }
219231
220232 /// This initializer is blocking and should only be run via the executor.
@@ -232,7 +244,7 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
232244
233245 // If there was an error constructing the cursor, throw it.
234246 if let error = self . getMongocError ( ) {
235- self . close ( )
247+ self . close ( fromError : true )
236248 throw error
237249 }
238250
@@ -265,7 +277,7 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
265277 switch self . state {
266278 case . open:
267279 return true
268- case . closed:
280+ case . closed, . error :
269281 return false
270282 }
271283 }
@@ -275,7 +287,11 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
275287 internal func next( ) throws -> BSONDocument ? {
276288 try self . lock. withLock {
277289 guard self . _isAlive else {
278- throw ClosedCursorError
290+ guard case . error = self . state else {
291+ throw ClosedCursorError
292+ }
293+ self . state = . closed
294+ return nil
279295 }
280296
281297 if case let . cached( result) = self . cached. clear ( ) {
@@ -339,7 +355,7 @@ internal class Cursor<CursorKind: MongocCursorWrapper> {
339355 self . isClosing. store ( true )
340356 self . lock. withLock {
341357 self . cached = . none
342- self . close ( )
358+ self . close ( fromError : false )
343359 }
344360 self . isClosing. store ( false )
345361 }
0 commit comments