I need to create a class which acts as a paginated list. My use case is like this:
I am writing a library which makes a service call to fetch a List<obj>
. Since the List<>
can be large, the service expects me to call with a PAGE_SIZE
. The service has also provided me with a TPS of x
which I need call it with.
I need to do two things:
- Rate Limit my calls to the Service
- Expose a PaginatedList<> from the library so that any client can use the Library and rate limit as per their TPS.
I was wondering whether the way I am implementing this PaginatedList is correct or if there is a better way.
public MyPaginatedList {
private static final PAGE_SIZE = 50;
private ServiceClient client;
private int pageToProcess = 0; //to keep track of which page we need to process next
private List<Data> data; // this is what the library exposes to outside world
public MyPaginatedList(ServiceClient client) {
this.client = client;
}
public MyPaginatedList getDataList(){
Servicerequest request = new ServiceRequest();
request.setIndex(PAGE_SIZE*pageToProcess++); // fetch the next set of items
this.data = client.APICall(request);
return this; // we return the current object
}
}
The public API exposed by this Library would use MyPaginatedList
like this:
class Library {
private ServiceClient client;
public Library(ServiceClient client) {
this.client = client;
}
public MyPaginatedList fetchData() {
return new MyPaginatedList(client).getDataList();
}
}
Any client of this library can use MyPaginatedList
and make Rate Limited Calls like this.
MyPaginatedList resultData = new Library().fetchData(); while(true) { for(Data d: resultData.getData()) // loop over the list exposed by MyPaginatedlist ... } RateLimiter.acquire(); // use guava rate limiter, would block till a token is available resultData = resultData.getDataList(); if(resultData.getData().isempty()) { break; } }
Edit:-
3 straightforward approaches come to my mind -
- The one described above. Where the
PaginatedList would expose a way to fetch next pages (batch of elements or List<>)
Let the Library expose 2 API's -
PaginatedList fetchData()
-> client would call this one initially
PaginatedList fetchNextPage(PaginatedList)
-> client would call this for sub-sequent pagesThis one is slightly modified version of approach 2. Let library expose a modified
fetchData()
PaginatedList fetchData(PaginatedList list)
-> initially client would need to create anew PaginatedList()
, which would initialize it's state likepageToProcess = 0;
This API kind of takes in the metadata associated with the service call to identify which page to get next
Any more suggestions or variations would be appreciated!