Search in sources :

Example 1 with CommandExecutionTask

use of net.robinfriedli.aiode.concurrent.CommandExecutionTask in project aiode by robinfriedli.

the class CommandManager method runCommand.

/**
 * Run command in a new thread, to be enqueued in the provided {@link ThreadExecutionQueue}.
 *
 * @param command        the command to run
 * @param executionQueue the target execution queue
 */
public void runCommand(Command command, ThreadExecutionQueue executionQueue) {
    CommandContext context = command.getContext();
    CommandExecutionTask commandExecutionTask = new CommandExecutionTask(command, executionQueue, this);
    commandExecutionTask.setName("command-execution-" + context);
    try {
        boolean queued = !executionQueue.add(commandExecutionTask, false);
        if (queued) {
            MessageService messageService = Aiode.get().getMessageService();
            messageService.sendError("Executing too many commands concurrently. This command will be executed after one has finished. " + "You may use the abort command to cancel queued commands and interrupt running commands.", context.getChannel());
            logger.warn(String.format("Guild %s has reached the max concurrent commands limit.", context.getGuild()));
        }
    } catch (RateLimitException e) {
        if (!e.isTimeout()) {
            throw new InvalidCommandException(e.getMessage());
        }
    }
}
Also used : CommandExecutionTask(net.robinfriedli.aiode.concurrent.CommandExecutionTask) RateLimitException(net.robinfriedli.aiode.exceptions.RateLimitException) InvalidCommandException(net.robinfriedli.aiode.exceptions.InvalidCommandException) MessageService(net.robinfriedli.aiode.discord.MessageService)

Example 2 with CommandExecutionTask

use of net.robinfriedli.aiode.concurrent.CommandExecutionTask in project aiode by robinfriedli.

the class AbortCommand method doRun.

@Override
public void doRun() {
    CommandExecutionTask commandExecutionTask = getTask();
    Thread abortThread = new Thread(() -> {
        if (commandExecutionTask != null) {
            try {
                commandExecutionTask.await();
            } catch (InterruptedException ignored) {
            }
        }
        CommandExecutionQueueManager executionQueueManager = Aiode.get().getExecutionQueueManager();
        GuildContext guildContext = getContext().getGuildContext();
        ThreadExecutionQueue executionQueue = executionQueueManager.getForGuild(getContext().getGuild());
        PooledTrackLoadingExecutor pooledTrackLoadingExecutor = guildContext.getPooledTrackLoadingExecutor();
        ReplaceableTrackLoadingExecutor replaceableTrackLoadingExecutor = guildContext.getReplaceableTrackLoadingExecutor();
        if (executionQueue.isIdle() && pooledTrackLoadingExecutor.isIdle() && replaceableTrackLoadingExecutor.isIdle()) {
            EmbedBuilder embedBuilder = new EmbedBuilder();
            embedBuilder.setDescription("No commands are currently running");
            getMessageService().sendTemporary(embedBuilder, getContext().getChannel());
            setFailed(true);
        } else {
            executionQueue.abortAll();
            pooledTrackLoadingExecutor.abortAll();
            replaceableTrackLoadingExecutor.abort();
            sendSuccess("Sent all currently running commands an interrupt signal and cancelled queued commands.");
        }
    });
    abortThread.setName("aiode abort thread");
    abortThread.setUncaughtExceptionHandler(new LoggingUncaughtExceptionHandler());
    abortThread.start();
}
Also used : CommandExecutionTask(net.robinfriedli.aiode.concurrent.CommandExecutionTask) GuildContext(net.robinfriedli.aiode.discord.GuildContext) PooledTrackLoadingExecutor(net.robinfriedli.aiode.audio.exec.PooledTrackLoadingExecutor) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) ReplaceableTrackLoadingExecutor(net.robinfriedli.aiode.audio.exec.ReplaceableTrackLoadingExecutor) ThreadExecutionQueue(net.robinfriedli.aiode.concurrent.ThreadExecutionQueue) LoggingUncaughtExceptionHandler(net.robinfriedli.aiode.exceptions.handler.handlers.LoggingUncaughtExceptionHandler) CommandExecutionQueueManager(net.robinfriedli.aiode.concurrent.CommandExecutionQueueManager)

Example 3 with CommandExecutionTask

use of net.robinfriedli.aiode.concurrent.CommandExecutionTask in project aiode by robinfriedli.

the class CommandMonitoringInterceptor method performChained.

@Override
public void performChained(Command command) {
    CommandContext context = command.getContext();
    CommandExecutionTask task = command.getTask();
    if (task == null) {
        return;
    }
    Future<?> monitoring = DaemonThreadPool.submit((LoggingRunnable) () -> {
        Thread thread = Thread.currentThread();
        String oldName = thread.getName();
        thread.setName("command-monitoring-" + context);
        CompletableFuture<Message> stillLoadingMessage = null;
        CompletableFuture<Message> warningMessage = null;
        try {
            task.await(MESSAGE_AFTER_THRESHOLD);
            if (!task.isDone()) {
                EmbedBuilder embedBuilder = new EmbedBuilder();
                embedBuilder.setDescription("Still loading...");
                stillLoadingMessage = messageService.send(embedBuilder, context.getChannel());
                task.await(LOGGER_WARNING_AFTER_THRESHOLD);
                if (!task.isDone()) {
                    EmbedBuilder warningEmbed = new EmbedBuilder();
                    warningEmbed.setColor(Color.RED);
                    warningEmbed.setTitle("Command timeout");
                    warningEmbed.setDescription(String.format("Your command '%s' is taking very long to execute. " + "If the command is not responding, consider interrupting it using the abort command.", command.display()));
                    warningMessage = messageService.send(warningEmbed.build(), context.getChannel());
                    logger.warn(String.format("Command [%s] on guild %s has exceeded the warn limit for execution duration of %d millis.", command.display(), context.getGuild(), MESSAGE_AFTER_THRESHOLD + LOGGER_WARNING_AFTER_THRESHOLD));
                }
                task.await();
                deleteMessages(stillLoadingMessage, warningMessage);
            }
        } catch (InterruptedException e) {
            // CommandExecutionInterceptor interrupts monitoring in post command
            deleteMessages(stillLoadingMessage, warningMessage);
        } finally {
            thread.setName(oldName);
        }
    });
    context.registerMonitoring(monitoring);
}
Also used : CommandExecutionTask(net.robinfriedli.aiode.concurrent.CommandExecutionTask) CompletableFuture(java.util.concurrent.CompletableFuture) EmbedBuilder(net.dv8tion.jda.api.EmbedBuilder) CommandContext(net.robinfriedli.aiode.command.CommandContext)

Aggregations

CommandExecutionTask (net.robinfriedli.aiode.concurrent.CommandExecutionTask)3 EmbedBuilder (net.dv8tion.jda.api.EmbedBuilder)2 CompletableFuture (java.util.concurrent.CompletableFuture)1 PooledTrackLoadingExecutor (net.robinfriedli.aiode.audio.exec.PooledTrackLoadingExecutor)1 ReplaceableTrackLoadingExecutor (net.robinfriedli.aiode.audio.exec.ReplaceableTrackLoadingExecutor)1 CommandContext (net.robinfriedli.aiode.command.CommandContext)1 CommandExecutionQueueManager (net.robinfriedli.aiode.concurrent.CommandExecutionQueueManager)1 ThreadExecutionQueue (net.robinfriedli.aiode.concurrent.ThreadExecutionQueue)1 GuildContext (net.robinfriedli.aiode.discord.GuildContext)1 MessageService (net.robinfriedli.aiode.discord.MessageService)1 InvalidCommandException (net.robinfriedli.aiode.exceptions.InvalidCommandException)1 RateLimitException (net.robinfriedli.aiode.exceptions.RateLimitException)1 LoggingUncaughtExceptionHandler (net.robinfriedli.aiode.exceptions.handler.handlers.LoggingUncaughtExceptionHandler)1