Skip to content

Port crates#index to use Diesel #609

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
merged 5 commits into from
Mar 11, 2017

Conversation

sgrif
Copy link
Contributor

@sgrif sgrif commented Mar 9, 2017

I decided to tackle this one next since we have an N+1 queries bug on
the max versions, it's a relatively high traffic endpoint, and the code
benefitted the most from Diesel.

There was probably more code added to support migrating the tests over
than to support the actual index function, but all those pieces will
start to get used as more endpoints are ported over. There were a few
tests that were hitting the followings and owners endpoints which I have
temporarily changed to hit the database directly instead.

Porting those endpoints would mean porting over more tests, which might
mean porting over more endpoints, etc. We didn't lose any coverage
overall, but we should still go back to hitting the endpoints directly
in tests when we can.

}

impl<'a> NewCrate<'a> {
pub fn create_or_update(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the same functionality as find_or_insert, but with a more clear name, and using Diesel. It's only used in tests currently.

src/krate.rs Outdated
let (offset, limit) = req.pagination(10, 100)?;
let query = req.query();
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 recommend using split diff here.

@sgrif
Copy link
Contributor Author

sgrif commented Mar 9, 2017

One thing that I didn't do here, but would be pretty easy to add if we want it is the ability to compose the branches in index. e.g. being able to write ?category=foo&keyword=bar&q=baz and have it do a full text search for baz on crates that have the category foo and the keyword bar.

And by pretty easy I mean that it's literally just removing the else from all the else ifs

@sgrif sgrif force-pushed the sg-port-crates-index2 branch 2 times, most recently from f635d52 to d9bfcdd Compare March 11, 2017 01:24
sgrif added 5 commits March 11, 2017 13:03
I decided to tackle this one next since we have an N+1 queries bug on
the max versions, it's a relatively high traffic endpoint, and the code
benefitted the most from Diesel.

There was probably more code added to support migrating the tests over
than to support the actual `index` function, but all those pieces will
start to get used as more endpoints are ported over. There were a few
tests that were hitting the followings and owners endpoints which I have
temporarily changed to hit the database directly instead.

Porting those endpoints would mean porting over more tests, which might
mean porting over more endpoints, etc. We didn't lose any coverage
overall, but we should still go back to hitting the endpoints directly
in tests when we can.
All the methods which do >1 query which modifies data should be wrapped
in a transaction
We should do this all over the application, as there's tons of endpoints
which are doing a separate query for the count when a window function
would achieve the same thing more efficiently.
@sgrif sgrif force-pushed the sg-port-crates-index2 branch from d9bfcdd to 8d5b143 Compare March 11, 2017 18:06
Copy link
Member

@carols10cents carols10cents left a comment

Choose a reason for hiding this comment

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

I see the tests that are hitting the database instead of the endpoints, but it looks to me like they're not really testing the same things? I could be convinced that this is ok if it's going to be temporary, just wanted to check that it's what you were intending.

@@ -0,0 +1 @@
ALTER TABLE versions ALTER COLUMN yanked SET NOT NULL;
Copy link
Member

Choose a reason for hiding this comment

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

Just checked to be sure: 0 records in production versions have yanked IS NULL

src/krate.rs Outdated
let max_version = krate.max_version(conn)?;
crates.push(krate.minimal_encodable(max_version, Some(badges)));
let mut query = crates_query(&params, req.user())?;
let sort = params.get("sort").map(|s| &**s).unwrap_or("alpha");
Copy link
Member

Choose a reason for hiding this comment

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

Love how the sorting is all in one place now 😻

.with_query(&query)));
assert_eq!(::json::<CrateList>(&mut response).crates.len(), 1);
// FIXME: Once owner endpoints use diesel, go back to hitting the real endpoint
assert_eq!(1, req.tx().unwrap().query("SELECT COUNT(*) FROM crate_owners
Copy link
Member

Choose a reason for hiding this comment

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

So this FIXME test is still doing an assertion...

req.with_path("/api/v1/crates/foo_following/following")
.with_method(Method::Get);
let mut response = ok_resp!(middle.call(&mut req));
assert!(::json::<F>(&mut response).following);
Copy link
Member

Choose a reason for hiding this comment

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

... but this assertion looks commented out....

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So basically this endpoint is tested elsewhere, and I'm assuming that ?following=1 is enough to generally verify this behavior, especially since I'm planning on hitting the following endpoints next after this is merged.

// FIXME: Go back to hitting the actual endpoint once it's using Diesel
req.db_conn().unwrap()
.execute("TRUNCATE TABLE follows")
.unwrap();
Copy link
Member

Choose a reason for hiding this comment

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

This test that's hitting the database instead of the endpoint looks like it's doing a lot more than the endpoint does...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I'm assuming that the table was empty when the test started running.

req.with_path("/api/v1/crates/foo_following/following")
.with_method(Method::Get);
let mut response = ok_resp!(middle.call(&mut req));
assert!(!::json::<F>(&mut response).following);
Copy link
Member

Choose a reason for hiding this comment

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

...and this assertion looks commented out...


let perfect_match = crates::name.eq(q_string).desc();
if sort == "downloads" {
query = query.order((perfect_match, crates::downloads.desc()));
Copy link
Member

Choose a reason for hiding this comment

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

Oh I guess sorting isn't in one place anymore, but I guess that's ok. This is better than it was!

I'm guessing later calls to order override earlier ones, like in activerecord?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, calls to order override the earlier ones. It's actually unlike Active Record (.reorder replaces earlier ones, .order appends). The only method in Diesel which doesn't override earlier calls is .filter.

@carols10cents
Copy link
Member

One thing that I didn't do here, but would be pretty easy to add if we want it is the ability to compose the branches in index. e.g. being able to write ?category=foo&keyword=bar&q=baz and have it do a full text search for baz on crates that have the category foo and the keyword bar.

And by pretty easy I mean that it's literally just removing the else from all the else ifs

Yeah I do want to do that eventually, but I think we also need to put some thought into which ordering takes precedence when, and how we convey what's going on in the UI as well. So it's not quite literally just that, but I'm glad to know the backend is closer at least :)

@carols10cents
Copy link
Member

Ok, fair enough :)

@carols10cents carols10cents merged commit 113ad2d into rust-lang:master Mar 11, 2017
@sgrif
Copy link
Contributor Author

sgrif commented Mar 11, 2017

Hopefully this will be the largest one. ❤️

@sgrif sgrif deleted the sg-port-crates-index2 branch March 11, 2017 21:18
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.

2 participants