diff --git a/src/main/java/com/github/ygimenez/listener/EventHandler.java b/src/main/java/com/github/ygimenez/listener/EventHandler.java index b14223d..14b9b2d 100644 --- a/src/main/java/com/github/ygimenez/listener/EventHandler.java +++ b/src/main/java/com/github/ygimenez/listener/EventHandler.java @@ -45,13 +45,12 @@ public EventHandler() { * Adds an event to the handler, which will be executed whenever a button with the same * ID is pressed. * - * @param msg The {@link Message} to hold the event. + * @param id The event ID. * @param act The action to be executed when the button is pressed. * @return An {@link ActionReference} pointing to this event. This is useful if you need to track whether an event * is still being processed or was already removed (i.e. garbage collected). */ - public ActionReference addEvent(@NotNull Message msg, @NotNull ThrowingBiConsumer act) { - String id = getEventId(msg); + public ActionReference addEvent(@NotNull String id, @NotNull ThrowingBiConsumer act) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Added event with ID " + id + " and Consumer hash " + Integer.toHexString(act.hashCode())); events.put(id, act); @@ -61,10 +60,9 @@ public ActionReference addEvent(@NotNull Message msg, @NotNull ThrowingBiConsume /** * Removes an event from the handler. * - * @param msg The {@link Message} which had attached events. + * @param id The event ID. */ - public void removeEvent(@NotNull Message msg) { - String id = getEventId(msg); + public void removeEvent(@NotNull String id) { Pages.getPaginator().log(PUtilsConfig.LogLevel.LEVEL_3, "Removed event with ID " + id); events.remove(id); dropdownValues.remove(id); diff --git a/src/main/java/com/github/ygimenez/method/Pages.java b/src/main/java/com/github/ygimenez/method/Pages.java index 583808a..46d4a4f 100644 --- a/src/main/java/com/github/ygimenez/method/Pages.java +++ b/src/main/java/com/github/ygimenez/method/Pages.java @@ -42,7 +42,7 @@ * to {@link #paginate}, {@link #categorize}, {@link #buttonize} and {@link #lazyPaginate}. */ public abstract class Pages { - private static final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); + private static final TaskScheduler scheduler = new TaskScheduler(); private static final EventHandler handler = new EventHandler(); private static Paginator paginator; @@ -573,7 +573,8 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe addReactions(msg, helper.getSkipAmount() > 1, helper.isFastForward()); } - return handler.addEvent(msg, new ThrowingBiConsumer<>() { + String evt = handler.getEventId(msg); + return handler.addEvent(evt, new ThrowingBiConsumer<>() { private final int maxP = pgs.size() - 1; private int p = 0; private ScheduledFuture timeout; @@ -582,7 +583,7 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe timeout.cancel(true); } - handler.removeEvent(msg); + handler.removeEvent(evt); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; @@ -591,7 +592,7 @@ public static ActionReference paginate(@NotNull Message msg, @NotNull PaginateHe { if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } } @@ -680,7 +681,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe timeout.cancel(true); } if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { @@ -849,7 +850,8 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Categori msg.addReaction(paginator.getEmoji(CANCEL)).submit(); } - return handler.addEvent(msg, new ThrowingBiConsumer<>() { + String evt = handler.getEventId(msg); + return handler.addEvent(evt, new ThrowingBiConsumer<>() { private ButtonId currCat = null; private ScheduledFuture timeout; private final Consumer success = s -> { @@ -857,13 +859,13 @@ public static ActionReference categorize(@NotNull Message msg, @NotNull Categori timeout.cancel(true); } - handler.removeEvent(msg); + handler.removeEvent(evt); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; { if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } } @@ -916,7 +918,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe timeout.cancel(true); } if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { @@ -1165,21 +1167,22 @@ public static ActionReference buttonize(@NotNull Message msg, @NotNull Buttonize } } - return handler.addEvent(msg, new ThrowingBiConsumer<>() { + String evt = handler.getEventId(msg); + return handler.addEvent(evt, new ThrowingBiConsumer<>() { private ScheduledFuture timeout; private final Consumer success = s -> { if (timeout != null) { timeout.cancel(true); } - handler.removeEvent(msg); + handler.removeEvent(evt); if (helper.getOnFinalization() != null) helper.getOnFinalization().accept(msg); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; { if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } } @@ -1243,7 +1246,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe timeout.cancel(true); } if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { @@ -1507,7 +1510,8 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa addReactions(msg, false, false); } - return handler.addEvent(msg, new ThrowingBiConsumer<>() { + String evt = handler.getEventId(msg); + return handler.addEvent(evt, new ThrowingBiConsumer<>() { private int p = 0; private ScheduledFuture timeout; private final Consumer success = s -> { @@ -1515,7 +1519,7 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa timeout.cancel(true); } - handler.removeEvent(msg); + handler.removeEvent(evt); if (paginator.isDeleteOnCancel()) msg.delete().submit(); }; @@ -1523,7 +1527,7 @@ public static ActionReference lazyPaginate(@NotNull Message msg, @NotNull LazyPa { if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } } @@ -1601,7 +1605,7 @@ public void acceptThrows(@NotNull User u, @NotNull PaginationEventWrapper wrappe timeout.cancel(true); } if (helper.getTimeout() > 0) { - timeout = worker.schedule(() -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); + timeout = scheduler.schedule(evt, () -> finalizeEvent(msg, success), helper.getTimeout(), TimeUnit.MILLISECONDS); } if (wrapper.isFromGuild() && wrapper.getSource() instanceof MessageReactionAddEvent && paginator.isRemoveOnReact()) { diff --git a/src/main/java/com/github/ygimenez/model/TaskScheduler.java b/src/main/java/com/github/ygimenez/model/TaskScheduler.java new file mode 100644 index 0000000..9f449f4 --- /dev/null +++ b/src/main/java/com/github/ygimenez/model/TaskScheduler.java @@ -0,0 +1,32 @@ +package com.github.ygimenez.model; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.*; + +/** + * Task manager for pagination events' expiration + */ +public class TaskScheduler { + private final ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor(); + private final Map> tasks = new HashMap<>(); + + /** + * Schedule a new task, cancelling and replacing the previous if exists. + * + * @param id The task identifier. + * @param task The task itself. + * @param time The time for the timeout. + * @param unit The unit for the timeout. + * @return + */ + public ScheduledFuture schedule(String id, Runnable task, long time, TimeUnit unit) { + ScheduledFuture t = worker.schedule(task, time, unit); + ScheduledFuture prev = tasks.put(id, t); + if (prev != null) { + prev.cancel(true); + } + + return t; + } +}