Skip to content

Commit daa6a2c

Browse files
authored
SWIFT-853 Clarify requirements for when when cursors/change streams need to be killed (#488)
1 parent 78f1fd3 commit daa6a2c

File tree

9 files changed

+100
-12
lines changed

9 files changed

+100
-12
lines changed

Sources/MongoSwift/ChangeStream.swift

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,19 @@ public class ChangeStream<T: Codable>: CursorProtocol {
108108
}
109109
}
110110

111-
/// Indicates whether this change stream has the potential to return more data.
111+
/**
112+
* Indicates whether this change stream has the potential to return more data.
113+
*
114+
* This change stream will be dead after `next` returns `nil`, but it may still be alive after `tryNext` returns
115+
* `nil`.
116+
*
117+
* After either of `next` or `tryNext` return a non-`DecodingError` error, this change stream will be dead. It may
118+
* still be alive after either returns a `DecodingError`, however.
119+
*
120+
* - Warning:
121+
* If this change stream is alive when it goes out of scope, it will leak resources. To ensure it is dead
122+
* before it leaves scope, invoke `ChangeStream.kill(...)` on it.
123+
*/
112124
public func isAlive() -> EventLoopFuture<Bool> {
113125
self.client.operationExecutor.execute {
114126
self.wrappedCursor.isAlive
@@ -234,9 +246,13 @@ public class ChangeStream<T: Codable>: CursorProtocol {
234246
/**
235247
* Kill this change stream.
236248
*
237-
* This method MUST be called before this change stream goes out of scope to prevent leaking resources.
238-
* This method may be called even if there are unresolved futures created from other `ChangeStream` methods.
239-
* This method will have no effect if the change stream is already dead.
249+
* This method MAY be called even if there are unresolved futures created from other `ChangeStream` methods.
250+
*
251+
* This method MAY be called if the change stream is already dead. It will have no effect.
252+
*
253+
* - Warning:
254+
* If this change stream is alive when it goes out of scope, it will leak resources. To ensure it
255+
* is dead before it leaves scope, invoke this method.
240256
*
241257
* - Returns:
242258
* An `EventLoopFuture` that evaluates when the change stream has completed closing. This future should not fail.

Sources/MongoSwift/MongoClient.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,10 @@ public class MongoClient {
475475
* - options: An optional `ChangeStreamOptions` to use when constructing the change stream.
476476
* - session: An optional `ClientSession` to use with this change stream.
477477
*
478+
* - Warning:
479+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
480+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
481+
*
478482
* - Returns:
479483
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching all collections in this
480484
* deployment.
@@ -512,6 +516,10 @@ public class MongoClient {
512516
* - withFullDocumentType: The type that the `fullDocument` field of the emitted `ChangeStreamEvent`s will be
513517
* decoded to.
514518
*
519+
* - Warning:
520+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
521+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
522+
*
515523
* - Returns:
516524
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching all collections in this
517525
* deployment.
@@ -554,6 +562,10 @@ public class MongoClient {
554562
* - withEventType: The type that the entire change stream response will be decoded to and that will be returned
555563
* when iterating through the change stream.
556564
*
565+
* - Warning:
566+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
567+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
568+
*
557569
* - Returns:
558570
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching all collections in this
559571
* deployment.

Sources/MongoSwift/MongoCollection+ChangeStreams.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ extension MongoCollection {
1212
* - options: An optional `ChangeStreamOptions` to use when constructing the change stream.
1313
* - session: An optional `ClientSession` to use with this change stream.
1414
*
15+
* - Warning:
16+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
17+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
18+
*
1519
* - Returns:
1620
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching this collection.
1721
*
@@ -46,6 +50,10 @@ extension MongoCollection {
4650
* - withFullDocumentType: The type that the `fullDocument` field of the emitted `ChangeStreamEvent`s will be
4751
* decoded to.
4852
*
53+
* - Warning:
54+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
55+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
56+
*
4957
* - Returns:
5058
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching this collection.
5159
*
@@ -85,6 +93,10 @@ extension MongoCollection {
8593
* - withEventType: The type that the entire change stream response will be decoded to and that will be returned
8694
* when iterating through the change stream.
8795
*
96+
* - Warning:
97+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
98+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
99+
*
88100
* - Returns:
89101
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching this collection.
90102
*

Sources/MongoSwift/MongoCollection+Indexes.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,10 @@ extension MongoCollection {
381381
* - Parameters:
382382
* - session: Optional `ClientSession` to use when executing this command
383383
*
384+
* - Warning:
385+
* If the returned cursor is alive when it goes out of scope, it will leak resources. To ensure the
386+
* cursor is dead before it leaves scope, invoke `MongoCursor.kill(...)` on it.
387+
*
384388
* - Returns:
385389
* An `EventLoopFuture<MongoCursor<IndexModel>>`. On success, contains a cursor over the indexes.
386390
*

Sources/MongoSwift/MongoCollection+Read.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ extension MongoCollection {
66
/**
77
* Finds the documents in this collection which match the provided filter.
88
*
9+
* - Warning:
10+
* If the returned cursor is alive when it goes out of scope, it will leak resources. To ensure the cursor
11+
* is dead before it leaves scope, invoke `MongoCursor.kill(...)` on it.
12+
*
913
* - Parameters:
1014
* - filter: A `BSONDocument` that should match the query
1115
* - options: Optional `FindOptions` to use when executing the command
@@ -66,6 +70,10 @@ extension MongoCollection {
6670
* - options: Optional `AggregateOptions` to use when executing the command
6771
* - session: Optional `ClientSession` to use when executing this command
6872
*
73+
* - Warning:
74+
* If the returned cursor is alive when it goes out of scope, it will leak resources. To ensure the cursor
75+
* is dead before it leaves scope, invoke `MongoCursor.kill(...)` on it.
76+
*
6977
* - Returns:
7078
* An `EventLoopFuture<MongoCursor<CollectionType>`. On success, contains a cursor over the resulting documents.
7179
*

Sources/MongoSwift/MongoCursor.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,17 @@ public class MongoCursor<T: Codable>: CursorProtocol {
9999
* This method is mainly useful if this cursor is tailable, since in that case `tryNext` may return more results
100100
* even after returning `nil`.
101101
*
102-
* If this cursor is non-tailable, it will always be dead as soon as either `tryNext` returns `nil` or an error.
102+
* If this cursor is non-tailable, it will always be dead after either `tryNext` returns `nil` or a
103+
* non-`DecodingError` error.
103104
*
104-
* This cursor will be dead as soon as `next` returns `nil` or an error, regardless of the `MongoCursorType`.
105+
* This cursor will be dead after `next` returns `nil` or a non-`DecodingError` error, regardless of the
106+
* `MongoCursorType`.
107+
*
108+
* This cursor may still be alive after `next` or `tryNext` returns a `DecodingError`.
109+
*
110+
* - Warning:
111+
* If this cursor is alive when it goes out of scope, it will leak resources. To ensure it is dead before it
112+
* leaves scope, invoke `MongoCursor.kill(...)` on it.
105113
*/
106114
public func isAlive() -> EventLoopFuture<Bool> {
107115
self.client.operationExecutor.execute {
@@ -231,8 +239,13 @@ public class MongoCursor<T: Codable>: CursorProtocol {
231239
/**
232240
* Kill this cursor.
233241
*
234-
* This method MUST be called before this cursor goes out of scope to prevent leaking resources.
235-
* This method may be called even if there are unresolved futures created from other `MongoCursor` methods.
242+
* This method MAY be called even if there are unresolved futures created from other `MongoCursor` methods.
243+
*
244+
* This method MAY be called if the cursor is already dead. It will have no effect.
245+
*
246+
* - Warning:
247+
* If this cursor is alive when it goes out of scope, it will leak resources. To ensure it
248+
* is dead before it leaves scope, invoke this method.
236249
*
237250
* - Returns:
238251
* An `EventLoopFuture` that evaluates when the cursor has completed closing. This future should not fail.

Sources/MongoSwift/MongoDatabase.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,10 @@ public struct MongoDatabase {
234234
* - options: Optional `ListCollectionsOptions` to use when executing this command
235235
* - session: Optional `ClientSession` to use when executing this command
236236
*
237+
* - Warning:
238+
* If the returned cursor is alive when it goes out of scope, it will leak resources. To ensure the cursor
239+
* is dead before it leaves scope, invoke `MongoCursor.kill(...)` on it.
240+
*
237241
* - Returns:
238242
* An `EventLoopFuture<MongoCursor<CollectionSpecification>>` containing a cursor over the collections.
239243
*
@@ -352,6 +356,10 @@ public struct MongoDatabase {
352356
* - options: An optional `ChangeStreamOptions` to use when constructing the change stream.
353357
* - session: An optional `ClientSession` to use with this change stream.
354358
*
359+
* - Warning:
360+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
361+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
362+
*
355363
* - Returns:
356364
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching all collections in this
357365
* database.
@@ -389,6 +397,10 @@ public struct MongoDatabase {
389397
* - withFullDocumentType: The type that the `fullDocument` field of the emitted `ChangeStreamEvent`s will be
390398
* decoded to.
391399
*
400+
* - Warning:
401+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
402+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
403+
*
392404
* - Returns:
393405
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching all collections in this
394406
* database.
@@ -431,6 +443,10 @@ public struct MongoDatabase {
431443
* - withEventType: The type that the entire change stream response will be decoded to and that will be returned
432444
* when iterating through the change stream.
433445
*
446+
* - Warning:
447+
* If the returned change stream is alive when it goes out of scope, it will leak resources. To ensure the
448+
* change stream is dead before it leaves scope, invoke `ChangeStream.kill(...)` on it.
449+
*
434450
* - Returns:
435451
* An `EventLoopFuture<ChangeStream>`. On success, contains a `ChangeStream` watching all collections in this
436452
* database.

Sources/MongoSwiftSync/ChangeStream.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ public class ChangeStream<T: Codable>: CursorProtocol {
2626
/**
2727
* Indicates whether this change stream has the potential to return more data.
2828
*
29-
* This change stream will be dead if `next` returns `nil` or an error. It will also be dead if `tryNext` returns
30-
* an error, but will still be alive if `tryNext` returns `nil`.
29+
* This change stream will be dead after `next` returns `nil`, but it may still be alive after `tryNext` returns
30+
* `nil`.
31+
*
32+
* After either of `next` or `tryNext` return a non-`DecodingError` error, this change stream will be dead. It may
33+
* still be alive after either returns a `DecodingError`, however.
3134
*/
3235
public func isAlive() -> Bool {
3336
do {

Sources/MongoSwiftSync/MongoCursor.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ public class MongoCursor<T: Codable>: CursorProtocol {
1919
* This method is mainly useful if this cursor is tailable, since in that case `tryNext` may return more results
2020
* even after returning `nil`.
2121
*
22-
* If this cursor is non-tailable, it will always be dead as soon as either `tryNext` returns `nil` or an error.
22+
* If this cursor is non-tailable, it will always be dead after either `tryNext` returns `nil` or a
23+
* non-`DecodingError` error.
2324
*
24-
* This cursor will be dead as soon as `next` returns `nil` or an error, regardless of the `MongoCursorType`.
25+
* This cursor will be dead after `next` returns `nil` or a non-`DecodingError` error, regardless of the
26+
* `MongoCursorType`.
27+
*
28+
* This cursor may still be alive after `next` or `tryNext` returns a `DecodingError`.
2529
*/
2630
public func isAlive() -> Bool {
2731
do {

0 commit comments

Comments
 (0)