Interface PaginationAction<T,M extends PaginationAction<T,M>>
- Type Parameters:
M
- The current implementation used as chaining return valueT
- The type of entity to paginate
- All Superinterfaces:
Iterable<T>
,RestAction<@Unmodifiable List<T>>
- All Known Subinterfaces:
AuditLogPaginationAction
,BanPaginationAction
,EntitlementPaginationAction
,MessagePaginationAction
,PollVotersPaginationAction
,ReactionPaginationAction
,ScheduledEventMembersPaginationAction
,ThreadChannelPaginationAction
,ThreadMemberPaginationAction
RestAction
specification used
to retrieve entities for paginated endpoints (before, after, limit).
Note that this implementation is not considered thread-safe as modifications to the cache are not done with a lock. Calling methods on this class from multiple threads is not recommended.
Examples
/**
* Retrieves messages until the specified limit is reached. The messages will be limited after being filtered by the user.
* If the user hasn't sent enough messages this will go through all messages so it is recommended to add an additional end condition.
*/
public static List<Message> getMessagesByUser(MessageChannel channel, User user, int limit)
{
MessagePaginationAction action = channel.getIterableHistory();
Stream<Message> messageStream = action.stream()
.limit(limit * 2) // used to limit amount of messages to check, if user hasn't sent enough messages it would go on forever
.filter( message-> message.getAuthor().equals(user) )
.limit(limit); // limit on filtered stream will be checked independently from previous limit
return messageStream.collect(Collectors.toList());
}
/**
* Iterates messages in an async stream and stops once the limit has been reached.
*/
public static void onEachMessageAsync(MessageChannel channel, Consumer<Message> consumer, int limit)
{
if (limit< 1)
return;
MessagePaginationAction action = channel.getIterableHistory();
AtomicInteger counter = new AtomicInteger(limit);
action.forEachAsync( (message)->
{
consumer.accept(message);
// if false the iteration is terminated; else it continues
return counter.decrementAndGet() == 0;
});
}
- Since:
- 3.1
-
Nested Class Summary
Modifier and TypeInterfaceDescriptionstatic class
Iterator implementation for aPaginationAction
.static enum
Defines the pagination order for a pagination endpoint. -
Method Summary
Modifier and TypeMethodDescriptioncache
(boolean enableCache) Whether already retrieved entities should be stored within the internal cache.int
The current amount of cached entities for this PaginationActiondeadline
(long timestamp) Similar toRestAction.timeout(long, TimeUnit)
but schedules a deadline at which the request has to be completed.default CompletableFuture<?>
forEachAsync
(Procedure<? super T> action) Iterates over all entities until the provided action returnsfalse
!
This operation is different fromIterable.forEach(Consumer)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread.forEachAsync
(Procedure<? super T> action, Consumer<? super Throwable> failure) Iterates over all entities until the provided action returnsfalse
!
This operation is different fromIterable.forEach(Consumer)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread.void
forEachRemaining
(Procedure<? super T> action) Iterates over all remaining entities until the provided action returnsfalse
!
Skipping past already cached entities to iterate all remaining entities of this PaginationAction.default CompletableFuture<?>
forEachRemainingAsync
(Procedure<? super T> action) Iterates over all remaining entities until the provided action returnsfalse
!
This operation is different fromforEachRemaining(Procedure)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread.forEachRemainingAsync
(Procedure<? super T> action, Consumer<? super Throwable> failure) Iterates over all remaining entities until the provided action returnsfalse
!
This operation is different fromforEachRemaining(Procedure)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread.The currently cached entities of recent execution tasks.getFirst()
The first cached entity retrieved by this PaginationAction instancegetLast()
The most recent entity retrieved by this PaginationAction instancelong
The current iteration anchor used for pagination.int
getLimit()
The currently used limit.int
The maximum limit that can be used for this PaginationAction
Limits provided tolimit(int)
must not be greater than the returned value.int
The minimum limit that can be used for this PaginationAction
Limits provided tolimit(int)
must not be less than the returned value.getOrder()
The current iteration order.default EnumSet<PaginationAction.PaginationOrder>
The supportedPaginationOrders
for this pagination action.boolean
Whether retrieved entities are stored within an internal cache.boolean
isEmpty()
Whether the cache of this PaginationAction is empty.iterator()
PaginationIterator
that will iterate over all entities for this PaginationAction.limit
(int limit) Sets the limit that should be used in the next RestAction completion call.Configure thePaginationAction.PaginationOrder
of this pagination action.Returns a possibly parallelStream
with this PaginationAction as its source.default M
reverse()
Flips theorder(PaginationOrder)
of this pagination action.setCheck
(BooleanSupplier checks) Sets the last-second checks before finally executing the http request in the queue.skipTo
(long id) Skips past the specified ID for successive requests.default Spliterator<T>
stream()
A sequentialStream
with this PaginationAction as its source.takeAsync
(int amount) Convenience method to retrieve an amount of entities from this pagination action.takeRemainingAsync
(int amount) Convenience method to retrieve an amount of entities from this pagination action.default CompletableFuture<List<T>>
takeUntilAsync
(int limit, Predicate<? super T> rule) Retrieves elements until the specified condition is met.default CompletableFuture<List<T>>
takeUntilAsync
(Predicate<? super T> rule) Retrieves elements until the specified condition is met.default CompletableFuture<List<T>>
takeWhileAsync
(int limit, Predicate<? super T> rule) Retrieves elements while the specified condition is met.default CompletableFuture<List<T>>
takeWhileAsync
(Predicate<? super T> rule) Retrieves elements while the specified condition is met.Timeout for this RestAction instance.Methods inherited from interface net.dv8tion.jda.api.requests.RestAction
addCheck, and, and, complete, complete, completeAfter, delay, delay, delay, delay, flatMap, flatMap, getCheck, getJDA, map, mapToResult, onErrorFlatMap, onErrorFlatMap, onErrorMap, onErrorMap, onSuccess, queue, queue, queue, queueAfter, queueAfter, queueAfter, queueAfter, queueAfter, queueAfter, submit, submit, submitAfter, submitAfter, zip
-
Method Details
-
skipTo
Skips past the specified ID for successive requests. This will reset thegetLast()
entity and cause aNoSuchElementException
to be thrown when attempting to get the last entity until a new retrieve action has been done.
If cache is disabled this can be set to an arbitrary value irrelevant of the current last. Set this to0
to start from the most recent message.Fails if cache is enabled and the target id is newer than the current last id (id > last).
Example
public MessagePaginationAction getOlderThan(MessageChannel channel, long time) { final long timestamp = TimeUtil.getDiscordTimestamp(time); final MessagePaginationAction paginator = channel.getIterableHistory(); return paginator.skipTo(timestamp); } getOlderThan(channel, System.currentTimeMillis() - TimeUnit.DAYS.toMillis(14)) .forEachAsync((message) -> { boolean empty = message.getContentRaw().isEmpty(); if (!empty) System.out.printf("%#s%n", message); // means: print display content return !empty; // means: continue if not empty });
- Parameters:
id
- The snowflake ID to skip before, this is exclusive rather than inclusive- Returns:
- The current PaginationAction for chaining convenience
- Throws:
IllegalArgumentException
- If cache is enabled, and you are attempting to skip forward in time (id > last)- See Also:
-
getLastKey
long getLastKey()The current iteration anchor used for pagination.
This is updated by each retrieve action.- Returns:
- The current iteration anchor
- See Also:
-
setCheck
Description copied from interface:RestAction
Sets the last-second checks before finally executing the http request in the queue.
If the provided supplier evaluates tofalse
or throws an exception this will not be finished. When an exception is thrown from the supplier it will be provided to the failure callback.- Specified by:
setCheck
in interfaceRestAction<T>
- Parameters:
checks
- The checks to run before executing the request, ornull
to run no checks- Returns:
- The current RestAction for chaining convenience
- See Also:
-
timeout
Description copied from interface:RestAction
Timeout for this RestAction instance.
If the request doesn't get executed within the timeout it will fail.When a RestAction times out, it will fail with a
TimeoutException
. This is the same asdeadline(System.currentTimeMillis() + unit.toMillis(timeout))
.Example
action.timeout(10, TimeUnit.SECONDS) // 10 seconds from now .queueAfter(20, SECONDS); // request will not be executed within deadline and timeout immediately after 20 seconds
- Specified by:
timeout
in interfaceRestAction<T>
- Parameters:
timeout
- The timeout to useunit
-Unit
for the timeout value- Returns:
- The same RestAction instance with the applied timeout
- See Also:
-
deadline
Description copied from interface:RestAction
Similar toRestAction.timeout(long, TimeUnit)
but schedules a deadline at which the request has to be completed.
If the deadline is reached, the request will fail with aTimeoutException
.This does not mean that the request will immediately timeout when the deadline is reached. JDA will check the deadline right before executing the request or within intervals in a worker thread. This only means the request will timeout if the deadline has passed.
Example
action.deadline(System.currentTimeMillis() + 10000) // 10 seconds from now .queueAfter(20, SECONDS); // request will not be executed within deadline and timeout immediately after 20 seconds
- Specified by:
deadline
in interfaceRestAction<T>
- Parameters:
timestamp
- Millisecond timestamp at which the request will timeout- Returns:
- The same RestAction with the applied deadline
- See Also:
-
getSupportedOrders
The supportedPaginationOrders
for this pagination action.
All enum values that are not returned will cause a throw fororder(PaginationOrder)
.Most pagination endpoints only support a single order, however some endpoints such as message pagination supports both.
- Returns:
EnumSet
ofPaginationAction.PaginationOrder
(Modifying this set does not affect this class)
-
getOrder
The current iteration order.
This defaults toPaginationAction.PaginationOrder.BACKWARD
, meaning most recent first, for most pagination endpoints.- Returns:
- The
PaginationAction.PaginationOrder
- See Also:
-
order
Configure thePaginationAction.PaginationOrder
of this pagination action.You can only supply supported orders, see
getSupportedOrders()
.- Parameters:
order
- The pagination order- Returns:
- The current PaginationAction implementation instance
- Throws:
IllegalArgumentException
- If the provided pagination order is null or unsupportedIllegalStateException
- If this pagination action has already been used to retrieve entities- See Also:
-
reverse
Flips theorder(PaginationOrder)
of this pagination action.- Returns:
- The current PaginationAction implementation instance
- Throws:
IllegalArgumentException
- If this pagination action does not support the reversed order
-
cacheSize
int cacheSize()The current amount of cached entities for this PaginationAction- Returns:
- int size of currently cached entities
-
isEmpty
boolean isEmpty()Whether the cache of this PaginationAction is empty.
Logically equivalent tocacheSize() == 0
.- Returns:
- True, if no entities have been retrieved yet.
-
getCached
The currently cached entities of recent execution tasks.
EveryRestAction
success adds to this List. (Thread-Safe due toCopyOnWriteArrayList
)This does not contain all entities for the paginated endpoint unless the pagination has reached an end!
It only contains those entities which already have been retrieved.- Returns:
- Immutable
List
containing all currently cached entities for this PaginationAction
-
getLast
The most recent entity retrieved by this PaginationAction instance- Returns:
- The most recent cached entity
- Throws:
NoSuchElementException
- If no entities have been retrieved yet (seeisEmpty()
)
-
getFirst
The first cached entity retrieved by this PaginationAction instance- Returns:
- The very first cached entity
- Throws:
NoSuchElementException
- If no entities have been retrieved yet (seeisEmpty()
)
-
limit
Sets the limit that should be used in the next RestAction completion call.The specified limit may not be below the
Minimum Limit
nor above theMaximum Limit
. Unless these limits are specifically omitted. (See documentation of methods)This limit represents how many entities will be retrieved per request and NOT the maximum amount of entities that should be retrieved for iteration/sequencing.
action.limit(50).complete()
is not the same asaction.stream().limit(50).collect(collector)
- Parameters:
limit
- The limit to use- Returns:
- The current PaginationAction implementation instance
- Throws:
IllegalArgumentException
- If the provided limit is out of range
-
cache
Whether already retrieved entities should be stored within the internal cache. All cached entities will be available fromgetCached()
. Default: true
This being disabled allows unused entities to be removed from the memory heap by the garbage collector. If this is enabled this will not take place until all references to this PaginationAction have been cleared.- Parameters:
enableCache
- Whether to enable entity cache- Returns:
- The current PaginationAction implementation instance
-
isCacheEnabled
boolean isCacheEnabled()Whether retrieved entities are stored within an internal cache. If this isfalse
entities retrieved by the iterator or a call to aRestAction
terminal operation will not be retrievable fromgetCached()
.
This being disabled allows unused entities to be removed from the memory heap by the garbage collector. If this is enabled this will not take place until all references to this PaginationAction have been cleared.- Returns:
- True, If entities will be cached.
-
getMaxLimit
int getMaxLimit()The maximum limit that can be used for this PaginationAction
Limits provided tolimit(int)
must not be greater than the returned value.
If no maximum limit is used this will return0
. That means there is no upper border for limiting this PaginationAction- Returns:
- The maximum limit
-
getMinLimit
int getMinLimit()The minimum limit that can be used for this PaginationAction
Limits provided tolimit(int)
must not be less than the returned value.
If no minimum limit is used this will return0
. That means there is no lower border for limiting this PaginationAction- Returns:
- The minimum limit
-
getLimit
int getLimit()The currently used limit.
If this PaginationAction does not use limitation this will return0
- Returns:
- limit
-
takeWhileAsync
@Nonnull @CheckReturnValue default CompletableFuture<List<T>> takeWhileAsync(@Nonnull Predicate<? super T> rule) Retrieves elements while the specified condition is met.- Parameters:
rule
- The rule which must be fulfilled for an element to be added, returns false to discard the element and finish the task- Returns:
CompletableFuture
- Type:List
Future representing the fetch task, the list will be sorted most recent to oldest- Throws:
IllegalArgumentException
- If the provided rule isnull
- See Also:
-
takeWhileAsync
@Nonnull @CheckReturnValue default CompletableFuture<List<T>> takeWhileAsync(int limit, @Nonnull Predicate<? super T> rule) Retrieves elements while the specified condition is met.- Parameters:
limit
- The maximum amount of elements to collect or0
for no limitrule
- The rule which must be fulfilled for an element to be added, returns false to discard the element and finish the task- Returns:
CompletableFuture
- Type:List
Future representing the fetch task, the list will be sorted most recent to oldest- Throws:
IllegalArgumentException
- If the provided rule isnull
or the limit is negative- See Also:
-
takeUntilAsync
@Nonnull @CheckReturnValue default CompletableFuture<List<T>> takeUntilAsync(@Nonnull Predicate<? super T> rule) Retrieves elements until the specified condition is met.- Parameters:
rule
- The rule which must be fulfilled for an element to be discarded, returns true to discard the element and finish the task- Returns:
CompletableFuture
- Type:List
Future representing the fetch task, the list will be sorted most recent to oldest- Throws:
IllegalArgumentException
- If the provided rule isnull
- See Also:
-
takeUntilAsync
@Nonnull @CheckReturnValue default CompletableFuture<List<T>> takeUntilAsync(int limit, @Nonnull Predicate<? super T> rule) Retrieves elements until the specified condition is met.- Parameters:
limit
- The maximum amount of elements to collect or0
for no limitrule
- The rule which must be fulfilled for an element to be discarded, returns true to discard the element and finish the task- Returns:
CompletableFuture
- Type:List
Future representing the fetch task, the list will be sorted most recent to oldest- Throws:
IllegalArgumentException
- If the provided rule isnull
or the limit is negative- See Also:
-
takeAsync
Convenience method to retrieve an amount of entities from this pagination action.
This also includes already cached entities similar toforEachAsync(Procedure)
.- Parameters:
amount
- The maximum amount to retrieve- Returns:
CompletableFuture
- Type:List
- See Also:
-
takeRemainingAsync
Convenience method to retrieve an amount of entities from this pagination action.
UnliketakeAsync(int)
this does not include already cached entities.- Parameters:
amount
- The maximum amount to retrieve- Returns:
CompletableFuture
- Type:List
- See Also:
-
forEachAsync
@Nonnull @CheckReturnValue default CompletableFuture<?> forEachAsync(@Nonnull Procedure<? super T> action) Iterates over all entities until the provided action returnsfalse
!
This operation is different fromIterable.forEach(Consumer)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.This iteration will include already cached entities, in order to exclude cached entities use
forEachRemainingAsync(Procedure)
Example
//deletes messages until it finds a user that is still in guild public void cleanupMessages(MessagePaginationAction action) { action.forEachAsync( (message) -> { Guild guild = message.getGuild(); if (!guild.isMember(message.getAuthor())) message.delete().queue(); else return false; return true; }); }
- Parameters:
action
-Procedure
returningtrue
if iteration should continue!- Returns:
Future
that can be cancelled to stop iteration from outside!- Throws:
IllegalArgumentException
- If the provided Procedure isnull
-
forEachAsync
@Nonnull @CheckReturnValue CompletableFuture<?> forEachAsync(@Nonnull Procedure<? super T> action, @Nonnull Consumer<? super Throwable> failure) Iterates over all entities until the provided action returnsfalse
!
This operation is different fromIterable.forEach(Consumer)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.This iteration will include already cached entities, in order to exclude cached entities use
forEachRemainingAsync(Procedure, Consumer)
Example
//deletes messages until it finds a user that is still in guild public void cleanupMessages(MessagePaginationAction action) { action.forEachAsync( (message) -> { Guild guild = message.getGuild(); if (!guild.isMember(message.getAuthor())) message.delete().queue(); else return false; return true; }, Throwable::printStackTrace); }
- Parameters:
action
-Procedure
returningtrue
if iteration should continue!failure
-Consumer
that should handle any throwables from the action- Returns:
Future
that can be cancelled to stop iteration from outside!- Throws:
IllegalArgumentException
- If the provided Procedure or the failure Consumer isnull
-
forEachRemainingAsync
@Nonnull @CheckReturnValue default CompletableFuture<?> forEachRemainingAsync(@Nonnull Procedure<? super T> action) Iterates over all remaining entities until the provided action returnsfalse
!
This operation is different fromforEachRemaining(Procedure)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.This iteration will exclude already cached entities, in order to include cached entities use
forEachAsync(Procedure)
Example
//deletes messages until it finds a user that is still in guild public void cleanupMessages(MessagePaginationAction action) { action.forEachRemainingAsync( (message) -> { Guild guild = message.getGuild(); if (!guild.isMember(message.getAuthor())) message.delete().queue(); else return false; return true; }); }
- Parameters:
action
-Procedure
returningtrue
if iteration should continue!- Returns:
Future
that can be cancelled to stop iteration from outside!- Throws:
IllegalArgumentException
- If the provided Procedure isnull
-
forEachRemainingAsync
@Nonnull @CheckReturnValue CompletableFuture<?> forEachRemainingAsync(@Nonnull Procedure<? super T> action, @Nonnull Consumer<? super Throwable> failure) Iterates over all remaining entities until the provided action returnsfalse
!
This operation is different fromforEachRemaining(Procedure)
as it uses successiveRestAction.queue()
tasks to iterate each entity in callback threads instead of the calling active thread. This means that this method fully works on different threads to retrieve new entities.This iteration will exclude already cached entities, in order to include cached entities use
forEachAsync(Procedure, Consumer)
Example
//deletes messages until it finds a user that is still in guild public void cleanupMessages(MessagePaginationAction action) { action.forEachRemainingAsync( (message) -> { Guild guild = message.getGuild(); if (!guild.isMember(message.getAuthor())) message.delete().queue(); else return false; return true; }, Throwable::printStackTrace); }
- Parameters:
action
-Procedure
returningtrue
if iteration should continue!failure
-Consumer
that should handle any throwables from the action- Returns:
Future
that can be cancelled to stop iteration from outside!- Throws:
IllegalArgumentException
- If the provided Procedure or the failure Consumer isnull
-
forEachRemaining
Iterates over all remaining entities until the provided action returnsfalse
!
Skipping past already cached entities to iterate all remaining entities of this PaginationAction.This is a blocking operation that might take a while to complete
- Parameters:
action
- TheProcedure
which should returntrue
to continue iterating
-
spliterator
- Specified by:
spliterator
in interfaceIterable<T>
-
stream
A sequentialStream
with this PaginationAction as its source.- Returns:
- a sequential
Stream
over the elements in this PaginationAction
-
parallelStream
Returns a possibly parallelStream
with this PaginationAction as its source. It is allowable for this method to return a sequential stream.- Returns:
- a sequential
Stream
over the elements in this PaginationAction
-
iterator
PaginationIterator
that will iterate over all entities for this PaginationAction.
-