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
Add the ability to wrap an index searcher. #12364
Conversation
} | ||
|
||
@Inject | ||
public IndexSearcherWrappingService(Set<IndexSearcherWrapper> wrappers) { |
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.
Why a Set? The wrapping order below would then be in an indeterminate order. But why support multiple at all? Can't someone who wants to add multiple layers of IndexSearcher wrappers do it with a single IndexSearcherWrapper?
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.
Why a Set?
This gets injected via Guice and there is no list binder, just a set binder. We can add IndexSearcherWrapper#order()
that returns an integer and change the incoming Set to a list and sort based on the order?
Can't someone who wants to add multiple layers of IndexSearcher wrappers do it with a single IndexSearcherWrapper?
They could, but if multiple plugins like to independently decorate the IndexSearcher then that wouldn't possible if only a single instance can be specified. I don't have a concrete example... but I like to be flexible around this.
aad0463
to
f90165b
Compare
I updated the PR and added I think as a follow up issue we should implement a |
@@ -288,7 +282,7 @@ public final Searcher acquireSearcher(String source) throws EngineException { | |||
try { | |||
final Searcher retVal = newSearcher(source, searcher, manager); | |||
success = true; | |||
return retVal; | |||
return config().getWrappingService().wrap(retVal); |
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.
Would EngineSearcherFactory be a better place to do the wrapping? Otherwise I'm concerned we might not call incRef() and decRef() on the same index readers.
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.
unfortunately EngineSearcherFactory is only used once per refresh and not invoked each time a search is happening. The IndexSearcherWrapperService does delegate to the close method of the original Engine.Searcher do the ref counting should add up.
One issue I have with this change is that the IndexSearcher class is really hard to wrap. For instance, imagine you both need to wrap the underlying IndexReader being the searcher. Since IndexSearcher doesn't allow you to replace the wrapped reader, you need to create a new IndexSearcher around this wrapped reader. So if the original IndexSearcher was a sub-class of IndexSearcher that customized, say, how search() is implemented, then these changes will be lost. And you can't delegate to the original IndexSearcher since it is wrapping the wrong reader. Maybe one way to work around this issue would be to wrap readers and searchers separately: first you would wpply all reader wrappers, then all searcher wrappers? |
@jpountz good point. I changed the IndexSearcherWrapper interface to wrap directory readers and searcher independently. I think this resolves your concern. |
After talking with @jpountz we decided that it is for now better to allow only one IndexSearcherWrapper to wrap the underlying IndexSearcher from the engine. The order in which IndexSearcher get wrapped is too lenient, which can lead to confusing issues between plugins. Also an custom filtered IndexSearcher implementation needs to be really careful what methods to override. For example if IndexSearcher#rewrite gets overwritten than also IndexSearcher#createNormalizedWeight needs to be overwritten. |
// and I prefer to keep the `wrapper` field final. | ||
public IndexSearcherWrappingService(Set<IndexSearcherWrapper> wrappers) { | ||
if (wrappers.size() > 1) { | ||
throw new IllegalStateException("wrapping of the index searcher by more than one wrappers is forbidden"); |
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.
maybe add the set of wrappers to the message so taht it would be easier to debug
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.
+1
I think this can go in now. However can you add TODOs in the code that this stuff needs to be cleaned up and that we should make IndexSearcher more wrapping-friendly? |
LGTM |
This extension point allows one IndexSearcherWrapper instance to intercept the searcher from the Engine before it is used for a opertion.
a31d7c0
to
e997342
Compare
No description provided.