-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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 paging support #5518
add paging support #5518
Conversation
src/main/java/org/jabref/logic/importer/PagedSearchBasedFetcher.java
Outdated
Show resolved
Hide resolved
Cool that you provide a first draft of the interface before jumping ahead and changing everything! The proposed interface looks good to me. The only suggestion I have is that the different |
This looks good. I'm not sure if the How do you want to continue? Add the UI support as part of this PR or as a next one? |
I think I will open a separate one. And I will open a issue with a list of fetchers that have to implement the new interfaces. |
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.
In general: LGTM. -- Some nitpick comments remain 😇
src/test/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystemTest.java
Outdated
Show resolved
Hide resolved
import org.jabref.model.entry.BibEntry; | ||
import org.jabref.model.paging.Page; | ||
|
||
public interface PagedSearchBasedFetcher extends SearchBasedFetcher { |
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 add some JavaDoc here about the idea?
I see that one can
a) jump to arbitrary pages
b) the page size supported is pre-defined
Would there also be a method setPageSize()
make sense? Maybe a sub interface PagedSearchBasedFetcherWithVariablePageSize
?
The alternative solution could have been iterate
as jcabi github does it. However, with your approach, one can directly jump to a certain page and is not forced to query sequentially.
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 tried to keep the fetcher as stateless as possible. If thats is not required, i can provide an interface for that purpose.
It probably depends where we want configure the page size. In the application settings or as a dropdown?
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 would like to see it in a drop down. Internally, it can be persisted as preference, so that at a restart of JabRef, the value is the same.
I can imagine that with pagination we need to be stateful. If I as user go back and forth in the UI, I want to have quick responses. If there is a request sent to the server each time, this will be slow.
I am aware that this will require a "refresh search results" button in the UI, which just resets the factory to trigger new searches.
I would even use Google Guava Cache for caching different search results over different fetchers. -- The search results for publications won't differ from hour to hour, but merely from day to day or even week to week. Having the possibility to limit the cache by memory size. - I also find the loading pretty nice. see https://github.com/google/guava/wiki/CachesExplained#from-a-callable:
CacheLoader<Key, Graph> loader = CacheLoader.from(key -> createExpensiveGraph(key));
Source: https://guava.dev/releases/snapshot/api/docs/com/google/common/cache/CacheLoader.html
WDYT?
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 would let each fetcher decide the appropriate page size. Some fetchers might not support a variable page size, and even if they do there might be restrictions (for example some fetchers get a list of ids and then fetch details for every id; in this case you probably want to have only a small page size).
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 would like to see it in a drop down. Internally, it can be persisted as preference, so that at a restart of JabRef, the value is the same.
Then I think we dont need a setSize method, because how the getSize is implemented is up to the fetcher. The fetcher can then use the Preference API.
I can imagine that with pagination we need to be stateful. If I as user go back and forth in the UI, I want to have quick responses. If there is a request sent to the server each time, this will be slow.
I would argue that the fetcher doesn't need to be stateless but should be stateless. It's solely responsibility is to fetch results. The ViewModel can then cache the results. Caching is possible in the fetcher as well, but the Viewmodel is statefull anyway, therefore we don't add too much new complexity.
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 would even use Google Guava Cache for caching different search results over different fetchers. -- The search results for publications won't differ from hour to hour, but merely from day to day or even week to week. Having the possibility to limit the cache by memory size. - I also find the loading pretty nice. see https://github.com/google/guava/wiki/CachesExplained#from-a-callable:
That's another reason to do it in the viewmodel
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 I can implement a cache decorator for the fetchers. That way caching becomes very easy. But instanceof checks will fail
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 was thinking, that query optimization can be done best at the result provider. Thus, if I query 1000 elements at once as JabRef, following can happen:
- Provider supports 1000 entrie at once --> they are returned -(query optimization there)
- Provider supports 50 entries at once --> jabref does 20 calls to the provider (nearly no query optimization at the provider)
My thoughts with the factory were driven with the idea that the first setting should be supported.
That leads me to the idea that we might need maxPageSize
and pageSize
. Maybe even different page sizes for the view and for the fetcher...
We can surely separate the the basic fetcher and some layer inbetween.
UI --> caching layer --> fetcher
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.
Caching is a nice idea, but not thaaaat important. I would say, first focus on the paging UI and then we can have a look at how to implement caching.
@Test | ||
public void performSearchByQueryPaged_twoPagesNotEqual() throws Exception { | ||
Page<BibEntry> page = fetcher.performSearchPaged("author:\"A\"", 0); | ||
Page<BibEntry> page2 = fetcher.performSearchPaged("author:\"A\"", 1); |
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 think, in the UI it will be hard to always pass the query. Why not adding an intermediate layer searchPagesFactory = fetcher.searchPagesFactory("author:...")
and then searchPagesFactory.getPage(0)
?
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 stateless argument applies here too. I would prefer the viewmodel to handle state
src/test/java/org/jabref/logic/importer/fetcher/AstrophysicsDataSystemTest.java
Show resolved
Hide resolved
I've create a branch |
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'll merge this now. I guess further changes are necessary but that will depend on the GUI implementation. For the moment this is good to go.
Before i implement this, i want to discuss the interfaces i created.
#5507