-
Notifications
You must be signed in to change notification settings - Fork 67
SWIFT-957 Fill in namespace on invalidate events #519
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5b7b171
b3785f4
49255a5
b7061c8
6173700
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,6 +50,13 @@ public struct ResumeToken: Codable, Equatable { | |
| } | ||
| } | ||
|
|
||
| // TODO: SWIFT-981: Remove this. | ||
| /// The key we use for storing a change stream's namespace in it's `userInfo`. This allows types | ||
| /// using the decoder e.g. `ChangeStreamEvent` to access the namespace even if it is not present in the raw | ||
| /// document the server returns. Ok to force unwrap as initialization never fails. | ||
| // swiftlint:disable:next force_unwrapping | ||
| internal let changeStreamNamespaceKey = CodingUserInfoKey(rawValue: "namespace")! | ||
|
|
||
| // sourcery: skipSyncExport | ||
| /// A MongoDB change stream. | ||
| /// - SeeAlso: https://docs.mongodb.com/manual/changeStreams/ | ||
|
|
@@ -87,6 +94,7 @@ public class ChangeStream<T: Codable>: CursorProtocol { | |
| stealing changeStreamPtr: OpaquePointer, | ||
| connection: Connection, | ||
| client: MongoClient, | ||
| namespace: MongoNamespace, | ||
| session: ClientSession?, | ||
| decoder: BSONDecoder, | ||
| options: ChangeStreamOptions? | ||
|
|
@@ -99,7 +107,8 @@ public class ChangeStream<T: Codable>: CursorProtocol { | |
| type: .tailableAwait | ||
| ) | ||
| self.client = client | ||
| self.decoder = decoder | ||
| self.decoder = BSONDecoder(copies: decoder, options: nil) | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. since we are updating the userInfo I figured it was a bit safer to make a copy. this did make me think about the fact that right now users can't give us userInfo that we should use when decoding their custom types, even though they can configure all of the other encoder/decoder options via the strategies. I don't think that's too urgent though, we can wait until if/when someone asks for this capability. |
||
| self.decoder.userInfo[changeStreamNamespaceKey] = namespace | ||
|
|
||
| // TODO: SWIFT-519 - Starting 4.2, update resumeToken to startAfter (if set). | ||
| // startAfter takes precedence over resumeAfter. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -46,6 +46,7 @@ public struct ChangeStreamEvent<T: Codable>: Codable { | |
| /// - SeeAlso: https://docs.mongodb.com/manual/changeStreams/#resume-a-change-stream | ||
| public let _id: ResumeToken | ||
|
|
||
| // TODO: SWIFT-981: Make this field optional. | ||
| /// A document containing the database and collection names in which this change happened. | ||
| public let ns: MongoNamespace | ||
|
|
||
|
|
@@ -73,4 +74,29 @@ public struct ChangeStreamEvent<T: Codable>: Codable { | |
| * point after the update occurred. If the document was deleted since the updated happened, it will be nil. | ||
| */ | ||
| public let fullDocument: T? | ||
|
|
||
| private enum CodingKeys: String, CodingKey { | ||
| case operationType, _id, ns, documentKey, updateDescription, fullDocument | ||
| } | ||
|
|
||
| // Custom decode method to work around the fact that `invalidate` events do not have an `ns` field in the raw | ||
| // document. TODO SWIFT-981: Remove this. | ||
| public init(from decoder: Decoder) throws { | ||
| let container = try decoder.container(keyedBy: CodingKeys.self) | ||
| self.operationType = try container.decode(OperationType.self, forKey: .operationType) | ||
| self._id = try container.decode(ResumeToken.self, forKey: ._id) | ||
|
|
||
| do { | ||
| self.ns = try container.decode(MongoNamespace.self, forKey: .ns) | ||
| } catch { | ||
| guard let ns = decoder.userInfo[changeStreamNamespaceKey] as? MongoNamespace else { | ||
| throw error | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I considered just filling in with an empty namespace or something here, but that seemed like it would hide errors from the server in cases where a namespace is unexpectedly missing. |
||
| } | ||
| self.ns = ns | ||
| } | ||
|
|
||
| self.documentKey = try container.decodeIfPresent(BSONDocument.self, forKey: .documentKey) | ||
| self.updateDescription = try container.decodeIfPresent(UpdateDescription.self, forKey: .updateDescription) | ||
| self.fullDocument = try container.decodeIfPresent(T.self, forKey: .fullDocument) | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ideally this would have lived on
ChangeStream, but you can't have stored static properties on generic types 🤔