-
Notifications
You must be signed in to change notification settings - Fork 494
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
avoid expensive Solr join for public dvObjects in search (experimental) #10555
Conversation
This comment has been minimized.
This comment has been minimized.
@pdurbin Tried it on the perf. system, with the feature flag enabled, started a reindex. It powered through the first 40K or so datasets; then started failing for every dataset (or most of them?). For the first failure the process-failures error message looked like this:
for the last one (right before I killed the reindex this morning:
Seems like a simple matter of the new flag being added multiple times (?). On the search side, everything worked as advertised, with the guest user only seeing the datasets and collections with the new public flag added. We're not going to know just how fast these guest search queries are going to be for a full database until we get it fully re-indexed, but the early results were very promising. |
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
@@ -1006,6 +1007,14 @@ private String getPermissionFilterQuery(DataverseRequest dataverseRequest, SolrQ | |||
// Yes, see if GuestUser is part of any groups such as IP Groups. | |||
// ---------------------------------------------------- | |||
if (user instanceof GuestUser) { | |||
if (FeatureFlags.AVOID_EXPENSIVE_SOLR_JOIN.enabled()) { |
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.
Could you just check to see if groupsFromProviders (or any other reason to not use the public_object) here?
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.
@qqmyers I'm not sure I follow.
My goal is to do a quick check to see if a feature flag is set or not. If set, return early without a join.
You're proposing something else?
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.
If the flag and no groupsFromProviders (or the subset of those that are IP groups) which is calculated right after this, then skip the join. Guessing that would make this work in all circumstances?
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.
Are we only talking about making an extra effort NOT to treat members of IP groups as plain guest users here? (I remember very little about how IP groups are supposed to work; I'll let you guys figure it out)
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.
@qqmyers what is the problem you are trying to solve? What are you concerned about?
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.
"However, dvObjects that would have been found by IP Groups will no longer be found." If a user is a member of an IP group, why can't you skip adding the SearchFields.PUBLIC_OBJECT + ":" + true;
test and just do the normal join? That doesn't give the speedup if everyone is in an IP group, but if that's only a subset of users, you'd get the speedup for others and not break IP groups.
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.
Ok, I think I get it. I haven't tested the code below, but is it closer to what you're thinking?
// ----------------------------------------------------
// (1) Is this a GuestUser?
// Yes, see if GuestUser is part of any groups such as IP Groups.
// ----------------------------------------------------
if (user instanceof GuestUser) {
String groupsFromProviders = "";
Set<Group> groups = groupService.collectAncestors(groupService.groupsFor(dataverseRequest));
StringBuilder sb = new StringBuilder();
for (Group group : groups) {
logger.fine("found group " + group.getIdentifier() + " with alias " + group.getAlias());
String groupAlias = group.getAlias();
if (groupAlias != null && !groupAlias.isEmpty()) {
sb.append(" OR ");
// i.e. group_builtIn/all-users, ip/ipGroup3
sb.append(IndexServiceBean.getGroupPrefix()).append(groupAlias);
}
}
groupsFromProviders = sb.toString();
logger.fine("groupsFromProviders:" + groupsFromProviders);
// Check if any groups from providers were found.
if ("".equals(groupsFromProviders)) {
if (FeatureFlags.AVOID_EXPENSIVE_SOLR_JOIN.enabled()) {
/**
* Now that we know that there are no groupsFromProviders
* (such as IP Groups) involved, instead of doing an
* expensive join, narrow down to only public objects. This
* field is indexed on the content document itself, rather
* than a permission document.
*/
return SearchFields.PUBLIC_OBJECT + ":" + true;
}
}
/**
* Return the expensive join if groups from providers (IP Groups)
* were found or if the feature flag isn't enabled.
*/
String guestWithGroups = "{!join from=" + SearchFields.DEFINITION_POINT + " to=id}" + SearchFields.DISCOVERABLE_BY + ":(" + IndexServiceBean.getPublicGroupString() + groupsFromProviders + ")";
logger.fine(guestWithGroups);
return guestWithGroups;
}
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 quite awesome. As I mentioned in slack, this PR has a huge positive effect-to-effort invested ratio.
Jim's soft commit fixes from 10547; A quick experiment, replacing join on public objects with a boolean publicObject_b:true for logged-in users as well (with a join added for just for their own personal documents; groups are ignored for now). #10554
This comment has been minimized.
This comment has been minimized.
…ublicObject" flag for published documents - now for logged-in users, AND with support for groups. Group support experimental, but appears to be working. #10554
This comment has been minimized.
This comment has been minimized.
@pdurbin I moved it back into in progress temporarily, for some last minute touches/cleanup. That fall-through for a guest user in an ip group I can quickly add myself, if you want. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
search optimization feture that was no longer true. #10554
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…separated from the flag that enables the search-side optimization; Fixed the groups sub-query for the guest user. #10554
This comment has been minimized.
This comment has been minimized.
2 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
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 did a little cleanup of docs and javadoc.
Tests are failing but @landreev are looking into it.
I'll go ahead and drag this into ready for QA. The code changes seem fine to me. I haven't tested them, but I've been following along in Slack.
This comment has been minimized.
This comment has been minimized.
Yeah, the last few Jenkins failures were on account of the ConfirmEmail test; for which we have a merged fix now. Updated the branch, keeping an eye on it. |
📦 Pushed preview images as
🚢 See on GHCR. Use by referencing with full name as printed above, mind the registry name. |
Happy to see that the tests finally passed on this one. :) (and to see it merged, yay) |
What this PR does / why we need it:
We were advised yesterday by a Solr expert that we should avoid Solr joins whenever possible because they can impact performance.
This pull requests removes the join used when Guest users search. However, dvObjects that would have been found by IP Groups will no longer be found. In addition, a full reindex is required as the new field, a dynamic field of boolean type called
publicObject_b
, is located on the content documents themselves (dvObjects) rather than permission documents (which we join with).[Edit from Leonid:] The scope of the PR has been expanded to cover ALL the searches - not just for Guest users - and always rely on the newly-added boolean for selecting publicly-available objects. When the user initiating the search, whether a Guest or an AuthenticatedUser, is also a member of one or more groups (remember, Guests can be parts of some groups, such as IP groups), a join is added that is limited in scope to just these restricted groups. I was able to figure out a query that works on a combination of this boolean
publicObject_b:true
AND an additional limited join. See under "How to test" on how to observe the effect of these changes.Which issue(s) this PR closes:
This is related to the ongoing Solr perf effort:
Special notes for your reviewer:
For simplicity, I implemented a single experimental feature flag but we can certainly change this to multiple settings: one to tell Dataverse to start indexing content documents with
publicObject_b
and another setting to switch search over to start using them (and avoid the join). [Edit from Leonid: this has been done, there are now 2 separate feature flags]I did very light testing on this (and didn't test IP Groups at all). I did ensure that SearchIT passed on my machine.
Suggestions on how to test this:
After enabling the feature:
[Edit from Leonid:] The QA needs to involve confirming that searches are still working exactly the same as before, without these new experimental feature flags enabled. I'm fairly confident that the code handling that has been left unchanged; but it had to be at least moved around a little, so should be prudent to confirm.
In order to see the full impact of the new optimization in searches, the PR must be tested on the perf. test system, or a similar-size instance.
The "before" part, confirming the scale of performance degradation on an instance the size of ours, with the current implementation:
http://localhost:8080/api/admin/index
). Watch the load time for collection pages become abysmal, for both the guest an a logged in non-superuser. Note that for the superuser,dataverseAdmin
the performance will still be somewhat ok - because no permission joins are performed for such.The "after" part:
Notes:
publicObject:true
in them.dataverseAdmin
user, then make your local user an admin (under "Permissions"), who can then proceed creating datasets etc. in it.domain.xml
.Does this PR introduce a user interface change? If mockups are available, please link/include them here:
No.
Is there a release notes update needed for this change?:
Yes, included.
Additional documentation:
Included.