-
Notifications
You must be signed in to change notification settings - Fork 167
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
RUST-52 Implement Sessions API #304
Conversation
src/test/spec/sessions/mod.rs
Outdated
let result = match operation.object { | ||
OperationObject::Collection => { | ||
let result = operation.execute_on_collection(&coll, session).await; | ||
if test.description == "Server supports implicit sessions" { |
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.
This one particular test runs two operations with implicit sessions in sequence and then checks to see if they used the same lsid. Delaying here has the same effect as delaying after calling drop
(since drop
is called when the implicit session goes out of scope); made it conditional to avoid slowing down the tests a ton.
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.
Sounds good, could you add a comment into the code here explaining that?
src/test/spec/sessions/mod.rs
Outdated
} | ||
OperationObject::TestRunner => { | ||
match operation.name.as_str() { | ||
"assertDifferentLsidOnLastTwoCommands" => { |
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.
All of these operations take in different arguments so it didn't make much sense to integrate them into the usual operation parsing -- I'll abstract this out a little more if it gets too unwieldy when the additional transactions operations are introduced.
src/test/spec/sessions/operation.rs
Outdated
@@ -0,0 +1,1178 @@ | |||
use std::{collections::HashMap, fmt::Debug, ops::Deref}; |
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.
This is all quite similar to the operations stuff in the other runners, just some minor adjustments to fit in with the specific test schema for sessions/transactions.
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.
The README for the runner claims it has the same format as the transactions runner, which should mean it has the v2 format (transactions / retryable reads / crud v2). Is there any chance we'll be able to reuse code there instead of introducing an entirely new runner?
src/test/spec/sessions/test_event.rs
Outdated
for (k, v) in &expected.command { | ||
if k == "lsid" { | ||
match v.as_str().unwrap() { | ||
"session0" => { |
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.
The tests specify lsids as the name of the session (e.g.)
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.
Looks really good so far! I haven't gotten a chance to review the whole thing yet, but I do have a few minor comments / suggestions on the bits I have seen.
src/test/spec/sessions/mod.rs
Outdated
let result = match operation.object { | ||
OperationObject::Collection => { | ||
let result = operation.execute_on_collection(&coll, session).await; | ||
if test.description == "Server supports implicit sessions" { |
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.
Sounds good, could you add a comment into the code here explaining that?
src/test/spec/sessions/operation.rs
Outdated
@@ -0,0 +1,1178 @@ | |||
use std::{collections::HashMap, fmt::Debug, ops::Deref}; |
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.
The README for the runner claims it has the same format as the transactions runner, which should mean it has the v2 format (transactions / retryable reads / crud v2). Is there any chance we'll be able to reuse code there instead of introducing an entirely new runner?
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.
Looks great! I just have a few minor comments about the ClientSession
type and the tests.
src/client/session/mod.rs
Outdated
/// Returns a mutable reference to this session wrapped in an option. This method is necessary | ||
/// to bypass the construction of an option taking ownership of a mutable reference. | ||
#[allow(clippy::unnecessary_wraps)] | ||
pub(crate) fn as_mut_ref_option(&mut self) -> Option<&mut Self> { |
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.
I looked into this some more, and the issue has to do with reborrowing (well actually, the fact that a reborrow is not occurring). A reborrow seems to basically be an implicit copy of the reference that the compiler will insert in certain situations such as a function call. What's surprising is that hits behavior works even for mutable references, which do not implement Copy
or Clone
. It seems that due to the non-lexical-lifetimes feature, the compiler can tell when having multiple mutable references is okay or not. It also seems that the compiler is no longer able to / does not attempt to determine if a reborrow is safe when putting the mutable reference into an enum for passing into execute_operation
(I think this is because Option
is generic and does not have any &mut
specified, see here for an explanation). Calling as_mut_ref_option
does work though, since it first reborrows &mut self
and then moves that reference into an Option
, preventing a use-after-move compiler error. This could similarly be achieved by doing an explicit reborrow like Some(&mut *session)
. Feel free to keep this method if you think it's clearer or easier to use though.
This is all not documented very well, so most of what I understand of this situation comes from various forums / stackoverflow posts. Check out rust-lang/reference#788 for some useful links (and the request for better documentation on reborrows).
As a funny side note: I introduced MutableSessionRef
to actually do the opposite of what our problem here is--I needed a way to force a reference to move rather than reborrow, so I wrapped it in a struct which I could move around.
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.
Huh that's super interesting; I'm surprised there isn't better documentation of this in the Rust book. Updated to use an explicit reborrow.
Code changes LGTM, it looks like this just needs to be rebased to fix the merge conflict. I think the compilation issue on 1.45 should go away after that too. |
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.
@saghm I think it would be easiest for you to merge the error changes first; once that's in I can rebase and you can review whatever changes are needed to apply that work to this PR. |
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.
One question/suggestion about making something public and one clarification question about the v2 runner, but other than those, this looks good to me. Great job on this!
src/client/session/cluster_time.rs
Outdated
pub(crate) struct ClusterTime { | ||
cluster_time: Timestamp, | ||
pub struct ClusterTime { | ||
pub cluster_time: Timestamp, |
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.
I don't think these should be public; this allows a user who owns a ClusterTime to modify the timestamp or the signature, which is not useful since it would presumably break it. If users do actually need to inspect these values, we should make them private and add getters, but I think that this is supposed to be a mostly opaque value to users (that they receive from the driver and then can pass back in other places without needing to care about the internals), in which case we wouldn't need getters. Since the struct derives Debug, users will still be able to log cluster times even if we don't add getters, so that wouldn't be a reason to add getters either.
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.
That makes sense to me, the reasoning for exposing these was mainly for inspecting, but I think deriving Debug
should take care of that.
@@ -0,0 +1,304 @@ | |||
pub mod operation; |
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.
This (and the rest of the v2 test runner) is just moved from the previous location in the CRUD spec tests, correct?
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.
yep, I just did some renaming for the sake of clarity
No description provided.