Skip to content
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

Revert the order of page_restrictions rev key #718

Merged
merged 5 commits into from Nov 9, 2017

Conversation

Pchelolo
Copy link
Contributor

@Pchelolo Pchelolo commented Nov 18, 2016

Final polish needed to enable the restrictions table. Still need to reload the data to the new table and backfill the redirects, but overall we're good to go. All unit tests pass (sqlite depends on wikimedia/restbase-mod-table-sqlite#37)

Done a quite extensive testing pass in vagrant, all looks good. Vagrant depends on https://gerrit.wikimedia.org/r/#/c/322358/

Bug: https://phabricator.wikimedia.org/T149965

@@ -32,7 +32,7 @@ const tableName = 'title_revisions';
* @type {string}
* @const
*/
const restrictionsTableName = 'restrictions';
const restrictionsTableName = 'page_restrictions';
Copy link
Member

Choose a reason for hiding this comment

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

A better name in any case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gwicke Ye, we've needed to rename it anyways..

sys/parsoid.js Outdated
@@ -318,7 +318,8 @@ class ParsoidService {
// This revision is actually a redirect. Pass redirect target
// to caller, and let it rewrite the location header.
resp.status = 302;
resp.headers.location = encodeURIComponent(redirectTarget);
// Filter will take care of uri-encoding
resp.headers.location = redirectTarget;
Copy link
Member

Choose a reason for hiding this comment

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

This strikes me as a bit brittle. Is this mainly meant as a performance optimization, or is there another reason to defer encoding?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gwicke To be able to share the same codepath within the filter

Copy link
Member

Choose a reason for hiding this comment

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

Could the decoding be done once in the filter & the result be stored in a local variable? The performance impact should be pretty small, and in exchange we'd avoid introducing an exception to the "regular HTTP headers" principle & assumptions about which filters are active.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

A that's possible. But that would mean doing encode-decode-encode cycle instead of just one encode

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, but a) redirects are rare, and b) encoding & decoding a small string is fairly cheap. IMHO, consistency & lack of coupling is more important.

@@ -261,7 +262,8 @@ class PRS {
storePageDeletion(hyper, req, revision) {
return this.storeRestrictions(hyper, req, {
title: req.params.title,
rev: req.params.revision || revision.rev,
// We're storing page_deletions with magic 0 rev just to update the static column
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps also worth mentioning that 0 is chosen so that it will always match for any query for less-or-equal some revision greater than 0.

Copy link
Member

Choose a reason for hiding this comment

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

{{done}}

@@ -64,6 +66,9 @@ module.exports = (hyper, req, next, options, specInfo) => {
}

return contentPromise.then((content) => redirect(content, location, options));
} else if (content.status === 302) {
Copy link
Member

Choose a reason for hiding this comment

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

Is the intention here to override stored redirects?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We return 302 when content's not in storage && it's a redirect. For ?redirect=false and some other conditions we don't what 302 but want 200 instead

Copy link
Member

Choose a reason for hiding this comment

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

To me it looks as if this condition would fire when content was in storage, but the restriction table did not have the redirect. Is that intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gwicke nono. We're only setting 302 in parsoid.js when the content was not in storage because in that case restriction table update would be concurrent with the content request because we've just parsed out the redirect.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

When we're taking the content from the storage we don't set 302 and rely on the filter to get it from the restrictions table

Copy link
Member

Choose a reason for hiding this comment

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

I see -- that's pretty subtle. Do you think an explaining comment here could be helpful to remind ourselves about how this interacts with parsoid.js?

Copy link
Contributor Author

@Pchelolo Pchelolo Nov 22, 2016

Choose a reason for hiding this comment

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

I think that in the perfect world we wouldn't have such a weird hard dependency at all, but I couldn't think of a way to get rid of it. I'd add a comment

@gwicke
Copy link
Member

gwicke commented Nov 22, 2016

LGTM overall, just a couple of questions in line.

@Pchelolo
Copy link
Contributor Author

@gwicke Updated to address your comments

@Pchelolo
Copy link
Contributor Author

I've rebased the PR on top of the latest master. The tests are currently failing, see the Phablet ticket for an explanation why are they failing and a discussion on what to do with that.

@Pchelolo
Copy link
Contributor Author

Pchelolo commented Sep 29, 2017

I've adapted the patch to the new storage (we don't need to supply a tacky artificial fixed _tid any more!!) and made the tests pass by making them sequential. The tests need more attention, see discussion on the ticket.

Also this one already starts using the new filter to demonstrate that the tests are passing. However, we need to revert that part before deploying because we don't have the restrictions filled in and also we wanna make a proxy to run both filters in parallel in the beginning and check that the results are correct. Before building the proxy filter I will do some manual correctness testing though.

@Pchelolo
Copy link
Contributor Author

Pchelolo commented Sep 29, 2017

I did manually test this locally and in vagrant for various scenarios of page creation/renaming/deleting/redirecting etc and it seems to work correct for all the cases I'm managed to imagine.

TODO: Create a proxy that will run both filters and compare the results.

@@ -64,6 +67,12 @@ module.exports = (hyper, req, next, options, specInfo) => {
}

return contentPromise.then(content => redirect(content, location, options));
} else if (content.status === 302) {
// Parsoid.js emits a redirect when the new content is parsed because
// there could be a race condition with updating a restriction table.
Copy link
Member

Choose a reason for hiding this comment

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

Is this about the time window between a new restriction being created (ex: revision suppressed), and the update for this being processed in ChangeProp?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup.

@gwicke
Copy link
Member

gwicke commented Oct 2, 2017

👍

@Pchelolo
Copy link
Contributor Author

Pchelolo commented Nov 8, 2017

Finally ready!

Change-Id: I84e22519126bf9677ed9e17ec1d52a32227a0c20
Copy link
Contributor

@d00rman d00rman left a comment

Choose a reason for hiding this comment

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

LGTM in general, one in-lined question. Also, it would be best if we created the Cass3 tables before we merge this, so as not to shoot ourselves in the foot.

} else if (content.status === 302) {
// Parsoid.js emits a redirect when the new content is parsed because
// there could be a race condition with updating a restriction table.
// If the client doesn't want a redirect - remove it.
Copy link
Contributor

Choose a reason for hiding this comment

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

How can we know for sure that the client doesn't want a redirect here simply based on the status code (which implies otherwise) ?

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 inside an else-if clause, if client wanted a redirect or we wanted to provide it - we wouldn've going into the if clause and never even evaluated this condition comparing the status to 302

@d00rman d00rman merged commit e17288c into wikimedia:master Nov 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
3 participants