Skip to content

Commit f22e1fd

Browse files
authored
SWIFT-1391 Add MongoCollection async/await API (#704)
1 parent ae24e15 commit f22e1fd

12 files changed

+1185
-90
lines changed

Sources/MongoSwift/AsyncAwait/ClientSession+AsyncAwait.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ extension ClientSession {
1616
* automatically aborted if the session goes out of scope before `commitTransaction` is called.
1717
*
1818
* - Parameters:
19-
* - options: The options to use when starting this transaction
19+
* - options: The options to use when starting this transaction.
2020
*
2121
* - Throws:
2222
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.

Sources/MongoSwift/AsyncAwait/MongoClient+AsyncAwait.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ extension MongoClient {
4848
* Run the `listDatabases` command.
4949
*
5050
* - Parameters:
51-
* - filter: Optional `Document` specifying a filter that the listed databases must pass. This filter can be based
52-
* on the "name", "sizeOnDisk", "empty", or "shards" fields of the output.
51+
* - filter: Optional `BSONDocument` specifying a filter that the listed databases must pass. This filter can be
52+
* based on the "name", "sizeOnDisk", "empty", or "shards" fields of the output.
5353
* - options: Optional `ListDatabasesOptions` specifying options for listing databases.
5454
* - session: Optional `ClientSession` to use when executing this command.
5555
*
@@ -75,7 +75,7 @@ extension MongoClient {
7575
* Get a list of `MongoDatabase`s.
7676
*
7777
* - Parameters:
78-
* - filter: Optional `Document` specifying a filter on the names of the returned databases.
78+
* - filter: Optional `BSONDocument` specifying a filter on the names of the returned databases.
7979
* - options: Optional `ListDatabasesOptions` specifying options for listing databases.
8080
* - session: Optional `ClientSession` to use when executing this command.
8181
*
@@ -98,7 +98,7 @@ extension MongoClient {
9898
* Get a list of names of databases.
9999
*
100100
* - Parameters:
101-
* - filter: Optional `Document` specifying a filter on the names of the returned databases.
101+
* - filter: Optional `BSONDocument` specifying a filter on the names of the returned databases.
102102
* - options: Optional `ListDatabasesOptions` specifying options for listing databases.
103103
* - session: Optional `ClientSession` to use when executing this command.
104104
*
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#if compiler(>=5.5) && canImport(_Concurrency) && os(Linux)
2+
/// Extension to `MongoCollection` to support async/await APIs.
3+
extension MongoCollection {
4+
/**
5+
* Drops this collection from its parent database.
6+
* - Parameters:
7+
* - options: An optional `DropCollectionOptions` to use when executing this command.
8+
* - session: An optional `ClientSession` to use when executing this command.
9+
*
10+
* - Throws:
11+
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.
12+
*/
13+
public func drop(options: DropCollectionOptions? = nil, session: ClientSession? = nil) async throws {
14+
try await self.drop(options: options, session: session).get()
15+
}
16+
17+
/**
18+
* Renames this collection on the server. This method will return a handle to the renamed collection. The handle
19+
* which this method is invoked on will continue to refer to the old collection, which will then be empty.
20+
* The server will throw an error if the new name matches an existing collection unless the `dropTarget` option
21+
* is set to true.
22+
*
23+
* Note: This method is not supported on sharded collections.
24+
*
25+
* - Parameters:
26+
* - to: A `String`, the new name for the collection.
27+
* - options: Optional `RenameCollectionOptions` to use for the collection.
28+
* - session: Optional `ClientSession` to use when executing this command.
29+
*
30+
* - Returns:
31+
* A copy of the target `MongoCollection` with the new name.
32+
*
33+
* Throws:
34+
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.
35+
* - `MongoError.InvalidArgumentError` if the options passed in form an invalid combination.
36+
* - `MongoError.LogicError` if the provided session is inactive.
37+
* - `MongoError.LogicError` if this collection's parent client has already been closed.
38+
* - `EncodingError` if an error occurs while encoding the options to BSON.
39+
*/
40+
public func renamed(
41+
to newName: String,
42+
options: RenameCollectionOptions? = nil,
43+
session: ClientSession? = nil
44+
) async throws -> MongoCollection {
45+
try await self.renamed(to: newName, options: options, session: session).get()
46+
}
47+
}
48+
#endif
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
#if compiler(>=5.5) && canImport(_Concurrency) && os(Linux)
2+
/// Extension to `MongoCollection` to support async/await change stream APIs.
3+
extension MongoCollection {
4+
/**
5+
* Starts a `ChangeStream` on a collection. The `CollectionType` will be associated with the `fullDocument`
6+
* field in `ChangeStreamEvent`s emitted by the returned `ChangeStream`. The server will return an error if
7+
* this method is called on a system collection.
8+
*
9+
* - Parameters:
10+
* - pipeline: An array of aggregation pipeline stages to apply to the events returned by the change stream.
11+
* - options: An optional `ChangeStreamOptions` to use when constructing the change stream.
12+
* - session: An optional `ClientSession` to use with this change stream.
13+
*
14+
* - Returns: A `ChangeStream` on a specific collection.
15+
*
16+
* - Throws:
17+
* - `MongoError.CommandError` if an error occurs on the server while creating the change stream.
18+
* - `MongoError.InvalidArgumentError` if the options passed formed an invalid combination.
19+
* - `MongoError.InvalidArgumentError` if the `_id` field is projected out of the change stream documents by the
20+
* pipeline.
21+
*
22+
* - SeeAlso:
23+
* - https://docs.mongodb.com/manual/changeStreams/
24+
* - https://docs.mongodb.com/manual/meta/aggregation-quick-reference/
25+
* - https://docs.mongodb.com/manual/reference/system-collections/
26+
*/
27+
public func watch(
28+
_ pipeline: [BSONDocument] = [],
29+
options: ChangeStreamOptions? = nil,
30+
session: ClientSession? = nil
31+
) async throws -> ChangeStream<ChangeStreamEvent<CollectionType>> {
32+
try await self.watch(
33+
pipeline,
34+
options: options,
35+
session: session,
36+
withEventType: ChangeStreamEvent<CollectionType>.self
37+
)
38+
}
39+
40+
/**
41+
* Starts a `ChangeStream` on a collection. Associates the specified `Codable` type `T` with the `fullDocument`
42+
* field in the `ChangeStreamEvent`s emitted by the returned `ChangeStream`. The server will return an error
43+
* if this method is called on a system collection.
44+
*
45+
* - Parameters:
46+
* - pipeline: An array of aggregation pipeline stages to apply to the events returned by the change stream.
47+
* - options: An optional `ChangeStreamOptions` to use when constructing the change stream.
48+
* - session: An optional `ClientSession` to use with this change stream.
49+
* - withFullDocumentType: The type that the `fullDocument` field of the emitted `ChangeStreamEvent`s will be
50+
* decoded to.
51+
*
52+
* - Returns: A `ChangeStream` on a specific collection.
53+
*
54+
* - Throws:
55+
* - `MongoError.CommandError` if an error occurs on the server while creating the change stream.
56+
* - `MongoError.InvalidArgumentError` if the options passed formed an invalid combination.
57+
* - `MongoError.InvalidArgumentError` if the `_id` field is projected out of the change stream documents by the
58+
* pipeline.
59+
*
60+
* - SeeAlso:
61+
* - https://docs.mongodb.com/manual/changeStreams/
62+
* - https://docs.mongodb.com/manual/meta/aggregation-quick-reference/
63+
* - https://docs.mongodb.com/manual/reference/system-collections/
64+
*/
65+
public func watch<FullDocType: Codable>(
66+
_ pipeline: [BSONDocument] = [],
67+
options: ChangeStreamOptions? = nil,
68+
session: ClientSession? = nil,
69+
withFullDocumentType _: FullDocType.Type
70+
) async throws -> ChangeStream<ChangeStreamEvent<FullDocType>> {
71+
try await self.watch(
72+
pipeline,
73+
options: options,
74+
session: session,
75+
withEventType: ChangeStreamEvent<FullDocType>.self
76+
)
77+
}
78+
79+
/**
80+
* Starts a `ChangeStream` on a collection. Associates the specified `Codable` type `T` with the returned
81+
* `ChangeStream`. The server will return an error if this method is called on a system collection.
82+
*
83+
* - Parameters:
84+
* - pipeline: An array of aggregation pipeline stages to apply to the events returned by the change stream.
85+
* - options: An optional `ChangeStreamOptions` to use when constructing the change stream.
86+
* - session: An optional `ClientSession` to use with this change stream.
87+
* - withEventType: The type that the entire change stream response will be decoded to and that will be returned
88+
* when iterating through the change stream.
89+
*
90+
* - Returns: A `ChangeStream` on a specific collection.
91+
*
92+
* - Throws:
93+
* - `MongoError.CommandError` if an error occurs on the server while creating the change stream.
94+
* - `MongoError.InvalidArgumentError` if the options passed formed an invalid combination.
95+
* - `MongoError.InvalidArgumentError` if the `_id` field is projected out of the change stream documents by the
96+
* pipeline.
97+
*
98+
* - SeeAlso:
99+
* - https://docs.mongodb.com/manual/changeStreams/
100+
* - https://docs.mongodb.com/manual/meta/aggregation-quick-reference/
101+
* - https://docs.mongodb.com/manual/reference/system-collections/
102+
*/
103+
public func watch<EventType: Codable>(
104+
_ pipeline: [BSONDocument] = [],
105+
options: ChangeStreamOptions? = nil,
106+
session: ClientSession? = nil,
107+
withEventType _: EventType.Type
108+
) async throws -> ChangeStream<EventType> {
109+
try await self.watch(pipeline, options: options, session: session, withEventType: EventType.self).get()
110+
}
111+
}
112+
#endif
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#if compiler(>=5.5) && canImport(_Concurrency) && os(Linux)
2+
/// Extension to `MongoCollection` to support async/await find and modify APIs.
3+
extension MongoCollection {
4+
/**
5+
* Finds a single document and deletes it, returning the original.
6+
*
7+
* - Parameters:
8+
* - filter: a `BSONDocument` representing the match criteria.
9+
* - options: Optional `FindOneAndDeleteOptions` to use when executing the command.
10+
* - session: Optional `ClientSession` to use when executing this command.
11+
*
12+
* - Returns: The deleted document, represented as a `CollectionType`, or `nil` if no document was deleted.
13+
*
14+
* - Throws:
15+
* - `MongoError.InvalidArgumentError` if any of the provided options are invalid.
16+
* - `MongoError.LogicError` if the provided session is inactive.
17+
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.
18+
* - `MongoError.WriteError` if an error occurs while executing the command.
19+
* - `DecodingError` if the deleted document cannot be decoded to a `CollectionType` value.
20+
*/
21+
@discardableResult
22+
public func findOneAndDelete(
23+
_ filter: BSONDocument,
24+
options: FindOneAndDeleteOptions? = nil,
25+
session: ClientSession? = nil
26+
) async throws -> CollectionType? {
27+
try await self.findOneAndDelete(filter, options: options, session: session).get()
28+
}
29+
30+
/**
31+
* Finds a single document and replaces it, returning either the original or the replaced document.
32+
*
33+
* - Parameters:
34+
* - filter: a `BSONDocument` representing the match criteria.
35+
* - replacement: a `CollectionType` to replace the found document.
36+
* - options: Optional `FindOneAndReplaceOptions` to use when executing the command.
37+
* - session: Optional `ClientSession` to use when executing this command.
38+
*
39+
* - Returns: A `CollectionType`, representing either the original document or its replacement,
40+
* depending on selected options, or `nil` if there was no match.
41+
*
42+
* - Throws:
43+
* - `MongoError.InvalidArgumentError` if any of the provided options are invalid.
44+
* - `MongoError.LogicError` if the provided session is inactive.
45+
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.
46+
* - `MongoError.WriteError` if an error occurs while executing the command.
47+
* - `DecodingError` if the replaced document cannot be decoded to a `CollectionType` value.
48+
* - `EncodingError` if `replacement` cannot be encoded to a `BSONDocument`.
49+
*/
50+
@discardableResult
51+
public func findOneAndReplace(
52+
filter: BSONDocument,
53+
replacement: CollectionType,
54+
options: FindOneAndReplaceOptions? = nil,
55+
session: ClientSession? = nil
56+
) async throws -> CollectionType? {
57+
try await self.findOneAndReplace(
58+
filter: filter,
59+
replacement: replacement,
60+
options: options,
61+
session: session
62+
)
63+
.get()
64+
}
65+
66+
/**
67+
* Finds a single document and updates it, returning either the original or the updated document.
68+
*
69+
* - Parameters:
70+
* - filter: a `BSONDocument` representing the match criteria.
71+
* - update: a `BSONDocument` containing updates to apply.
72+
* - options: Optional `FindOneAndUpdateOptions` to use when executing the command.
73+
* - session: Optional `ClientSession` to use when executing this command.
74+
*
75+
* - Returns: A `CollectionType` representing either the original or updated document,
76+
* depending on selected options, or `nil` if there was no match.
77+
*
78+
* - Throws:
79+
* - `MongoError.InvalidArgumentError` if any of the provided options are invalid.
80+
* - `MongoError.LogicError` if the provided session is inactive.
81+
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.
82+
* - `MongoError.WriteError` if an error occurs while executing the command.
83+
* - `DecodingError` if the updated document cannot be decoded to a `CollectionType` value.
84+
*/
85+
@discardableResult
86+
public func findOneAndUpdate(
87+
filter: BSONDocument,
88+
update: BSONDocument,
89+
options: FindOneAndUpdateOptions? = nil,
90+
session: ClientSession? = nil
91+
) async throws -> CollectionType? {
92+
try await self.findOneAndUpdate(
93+
filter: filter,
94+
update: update,
95+
options: options,
96+
session: session
97+
)
98+
.get()
99+
}
100+
101+
/**
102+
* Finds a single document and updates it, returning either the original or the updated document.
103+
*
104+
* - Parameters:
105+
* - filter: a `BSONDocument` representing the match criteria.
106+
* - pipeline: an array of `BSONDocument` containing the aggregation pipeline to apply.
107+
* - options: Optional `FindOneAndUpdateOptions` to use when executing the command.
108+
* - session: Optional `ClientSession` to use when executing this command.
109+
*
110+
* - Returns: A `CollectionType` representing either the original or updated document,
111+
* depending on selected options, or `nil` if there was no match.
112+
*
113+
* - Throws:
114+
* - `MongoError.InvalidArgumentError` if any of the provided options are invalid.
115+
* - `MongoError.LogicError` if the provided session is inactive.
116+
* - `MongoError.CommandError` if an error occurs that prevents the command from executing.
117+
* - `MongoError.WriteError` if an error occurs while executing the command.
118+
* - `DecodingError` if the updated document cannot be decoded to a `CollectionType` value.
119+
*/
120+
@discardableResult
121+
public func findOneAndUpdate(
122+
filter: BSONDocument,
123+
pipeline: [BSONDocument],
124+
options: FindOneAndUpdateOptions? = nil,
125+
session: ClientSession? = nil
126+
) async throws -> CollectionType? {
127+
try await self.findOneAndUpdate(
128+
filter: filter,
129+
pipeline: pipeline,
130+
options: options,
131+
session: session
132+
)
133+
.get()
134+
}
135+
}
136+
#endif

0 commit comments

Comments
 (0)