-
Notifications
You must be signed in to change notification settings - Fork 96
Add first and last pagination parameters #502
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
Conversation
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.
Overall pretty good. I think this could be a little more robust instead of using the -1
flag because we wouldn't want people passing that in as a value
if (parameter.equals(FIRST)) { | ||
return 1; | ||
} else if (parameter.equals(LAST)) { | ||
return LAST_PAGE; |
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 it might be better to make pagination parameters use an Either<Integer, PageResultsFlag>
. I know this is only really needed for the LAST
page case, but using -1
as a special flag could lead to some confusion later.
enum PageResultsFlag {
FIRST("first"),
LAST("last");
// You could also have a function to handle #getPage(resultSize) in here for both cases
}
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 don't know. I think using -1
opens up the possibility for doing python-style paging, where -1 is the last page, -2 is the second to last page, etc.
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 if we introduce python-style paging I would definitely be ok with this approach. I don't want to start using negative values as special flags though
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.
@archolewa Would you want to change this PR to be python-style paging + first
/last
keywords?
I would vote yes for that
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 wasn't sure what to do about this, so I just left it for now. I would be happy to make any changes.
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.
@kevinhinterlong I don't think we should officially support python-style pages just yet. I think that's a big enough change that we would want to discuss it with others first. Plus, as I think about it, I'm honestly not sure exactly how useful it would be. Really, I think we should hold off on that until some asks for the ability to easily get the "second-to-last" page.
I don't want to add an enum for the first and last page, because then we either need to have some sort of awkward either object that stores either a number or an enum, or we need to have two fields, one of which is guaranteed to be null
at any one time.
In my opinion, the first one introduces way too much awkward infrastructure for something that is very internal to the PaginationParameters
object, and the second is downright confusing.
Meanwhile, -1
is a commonly used sentinel value to represent the "last" number whatever that may mean(for example, it's often used to represent infinity in configuration parameters).
If we were passing the raw page number to other parts of the system, then the extra infrastructure would be worth it.
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 wasn't entirely sure how much the idea of pagination was exposed in the other parts of the system which is why my preference was towards the Either
.
I think -1
will be okay since it's not exposed but it should definitely be internal only and not be allowed in the api.
*/ | ||
private void validate(int parameter, String parameterName) throws BadPaginationException { | ||
if (parameter < MINIMAL_VALUE) { | ||
if (parameter < MINIMAL_VALUE && parameter != LAST_PAGE) { |
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.
For example one place this gets confusing is the validation. As it is now this lets us pass in perPage=-1
as a valid query parameter
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.
Which makes sense if you think about negatives as counting backwards.
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.
For sure but I would imagine this should still only apply to what page
your asking for not the elements perPage
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.
Yeah, I wasn't thinking about perPage
when I changed this method. I will fix it 😄
@@ -19,12 +19,15 @@ class PaginationParametersSpec extends Specification { | |||
|
|||
then: "The handler's perPage and page are as expected" | |||
handler.getPerPage() == expectedPerPage | |||
handler.getPage() == expectedPage | |||
handler.getPage(10) == expectedPage |
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.
Make this a parameter in the where:
section to add more tests
invalidPerPage << ["0", "-2", "1.0", "2.3", "$Long.MAX_VALUE", "1a", "AndrewIsMostlyHarmless."] | ||
} | ||
|
||
def "If the result set is empty and the page is last then getPage returns the first page"() { |
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.
You could combine this with build the correct handler when 'perPage' is #perPage and 'page' is #page
if you make the resultSize
a parameter
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.
We may want to move up our validation some. While it's simpler to just have some undocumented behavior that allows -1 to be a valid value, that does result in an API change (rather than an API addition).
This could lead to weird behavior if say a UI doesn't allow negative page numbers and relies on Fili to perform that check.
Instead, we should probably validate before we parse the page number. So while we internally use -1
to represent the last page, we don't allow the customer to specify a -1.
); | ||
hits = hitDocs.scoreDocs; | ||
documentCount = hitDocs.totalHits; | ||
int requestedPageNumber = paginationParameters.getPage(documentCount); |
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.
As I think about it, I'm not sure this will work.
We'll need to dig into the Lucene library some to be sure, but I'm afraid that the hitDocs
contains only the first page of data, so hitDocs.totalHits <= perPage
, not the total number of possible documents.
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.
Yay! totalHits
is really the total number of results, so this should work.
@@ -114,11 +122,37 @@ private void validate(int parameter, String parameterName) throws BadPaginationE | |||
} | |||
} | |||
|
|||
/** | |||
* Verifies that the page is positive or is -1 (last page). |
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.
Rather than saying "or is -1" we should say "or is the last page."
As far as this method is concerned, it shouldn't really care what value we use to represent the last page.
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 agree with Andrew's suggested changes, and as long as we can verify/fix it so that it works with Lucene then this will also need a docs/
update.
I'm not really sure if we have something in place already for marking what version a feature became available in the api but we'd need to make a note of it somehow
@mpardesh Can you rebase this on top of master? |
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 had some comments about the test cases which could be reverted, but I'm pretty sure this has the correct behavior so it's not super necessary and I'm still going to approve it.
Also this should probably update docs/end-user-api.md
or at least make a new issue for it
@@ -906,7 +908,7 @@ class DimensionsServletComponentSpec extends Specification { | |||
|
|||
def "test negative page number is handled correctly"() { | |||
setup: | |||
Map<String, String> queryParams = [page: -1, perPage: 3] | |||
Map<String, String> queryParams = [page: -2, perPage: 3] |
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.
Couldn't this be reverted to -1
@@ -38,11 +45,11 @@ class PaginationParametersSpec extends Specification { | |||
|
|||
where: | |||
perPage | page || expectedError | |||
"-1" | "-1" || errorMessage("perPage", "-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.
Same for these test cases
@@ -115,7 +122,7 @@ class PaginationParametersSpec extends Specification { | |||
thrown(BadPaginationException) | |||
|
|||
where: | |||
invalidPage << ["0", "-1", "1.0", "2.3", "$Long.MAX_VALUE", "1a", "AndrewIsMostlyHarmless."] | |||
invalidPage << ["0", "-2", "1.0", "2.3", "$Long.MAX_VALUE", "1a", "AndrewIsMostlyHarmless."] |
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.
And here
@@ -130,7 +137,7 @@ class PaginationParametersSpec extends Specification { | |||
thrown(BadPaginationException) | |||
|
|||
where: | |||
invalidPerPage << ["0", "-1", "1.0", "2.3", "$Long.MAX_VALUE", "1a", "AndrewIsMostlyHarmless."] | |||
invalidPerPage << ["0", "-2", "1.0", "2.3", "$Long.MAX_VALUE", "1a", "AndrewIsMostlyHarmless."] |
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.
And here
@mpardesh Could you please rebase this on top of master? |
I have added the "first" and "last" pagination parameters. #352