Skip to content

RUST-1175 Support zero-copy deserialization from cursors #579

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

Merged

Conversation

patrickfreed
Copy link
Contributor

RUST-1175

This PR adds new methods to Cursor and SessionCursor to allow for zero-copy deserialization. As part of that, the trait requirements on the cursor types were relaxed, and they no longer require DeserializeOwned. The Stream implementations still do require all of the trait requirements though.

example usage:

#[derive(Debug, Deserialize)]
struct Stuff<'a> {
    #[serde(borrow)]
    name: &'a str,
    #[serde(borrow)]
    bio: &'a str
}

let coll = db.collection::<Stuff>("stuff");
let mut cursor = coll.find(None, None).await?;
while cursor.advance()?.await {
    println!("{:?}", cursor.deserialize_current()?);
}

@@ -37,17 +37,15 @@ where
provider: P,
client: Client,
info: CursorInformation,
buffer: VecDeque<RawDocumentBuf>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the stuff that needed to be preserved between GenericCursor constructions in a CursorState struct to ensure nothing gets forgotten.

@@ -90,10 +91,7 @@ pub(crate) use common::{
/// # }
/// ```
#[derive(Debug)]
pub struct Cursor<T>
where
T: DeserializeOwned + Unpin + Send + Sync,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we no longer buffer T, we can drop the Unpin + Send + Sync parts of this, and because we now support borrowed deserialization, we can drop DeserializeOwned too.

@@ -188,59 +186,6 @@ async fn op_selection_criteria() {
});
}

#[cfg_attr(feature = "tokio-runtime", tokio::test)]
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
async fn handle_success() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than continuing to maintain these tests that break a lot and don't offer much additional coverage over our integration tests, I decided just to delete the ones that broke. We discussed this a bit in slack, but in retrospect these tests are probably far too close to the actual implementation and are probably more effort than they're worth. Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, I don't think these are particularly valuable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM.

Copy link
Contributor

@isabelatkinson isabelatkinson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, just a few comments. do we also want to add this functionality to the sync API?

}

fn handle_get_more_result(&mut self, get_more_result: Result<GetMoreResult>) -> Result<()> {
self.state_mut().exhausted = get_more_result
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this necessary given mark_exhausted is called below?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, good catch. removed

@@ -188,59 +186,6 @@ async fn op_selection_criteria() {
});
}

#[cfg_attr(feature = "tokio-runtime", tokio::test)]
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
async fn handle_success() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed, I don't think these are particularly valuable

Copy link
Contributor Author

@patrickfreed patrickfreed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yep, totally forgot the sync API. Added it it now

}

fn handle_get_more_result(&mut self, get_more_result: Result<GetMoreResult>) -> Result<()> {
self.state_mut().exhausted = get_more_result
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nope, good catch. removed

fn mark_exhausted(&mut self) {
self.info.id = 0;
self.state.as_mut().unwrap().exhausted = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now that state is the single source of truth, this needed to be updated to use exhausted instead of the spec.

Copy link
Contributor

@abr-egn abr-egn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Minor comments only.

}

pub(super) fn is_exhausted(&self) -> bool {
self.exhausted
self.state.as_ref().unwrap().exhausted
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this and similar calls, I think it would be slightly better to centralize the unwrap in the state() accessor and write this as self.state().exhausted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. I had to leave the one on line 245 in to satisfy the borrow checker, not sure why though.

@@ -188,59 +186,6 @@ async fn op_selection_criteria() {
});
}

#[cfg_attr(feature = "tokio-runtime", tokio::test)]
#[cfg_attr(feature = "async-std-runtime", async_std::test)]
async fn handle_success() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM.

@patrickfreed patrickfreed merged commit 8e07cf4 into mongodb:master Feb 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants