Fixed a thread stuck scenario while trying to load unknown sources

Fixed /skip command not executing because of a negation in the if statement
Improved skip command by using the duplicate track detection
This commit is contained in:
anthorob committed 2022-10-01 11:41:07 -04:00
1 parent 63556d6081
commit 90455b90c3
7 files changed
+57 -53

No files matched your search

@@ -74,7 +74,7 @@ public class SkipCommand extends AbstractMusicCommand {
int skips = context.getEvent().getOption("skip", 0, OptionMapping::getAsInt); int skips = context.getEvent().getOption("skip", 0, OptionMapping::getAsInt);
context.ackAndWait(); context.ackAndWait();
if (!MusicUtils.checkIfConnected(manager, context)) { if (MusicUtils.checkIfConnected(manager, context)) {
if (skips > 0) { if (skips > 0) {
context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : "")); context.reply("Skipping %s track%s", skips, (skips > 1 ? "s" : ""));
manager.getScheduler().getQueueManager().skip(skips); manager.getScheduler().getQueueManager().skip(skips);
@@ -42,7 +42,7 @@ public class MusicManager {
private final static Logger logger = LoggerFactory.getLogger(MusicManager.class); private final static Logger logger = LoggerFactory.getLogger(MusicManager.class);
private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>(); private final static Map<String, MusicManager> managers = new ConcurrentHashMap<>();
private final static ScheduledExecutorService executor = (ScheduledExecutorService) ThreadManager.getExecutor("music", ThreadManager.ExecutorType.SCHEDULED); private final static ScheduledExecutorService executor = ThreadManager.getMusicExecutor();
private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager(); private final static AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
private final Guild guild; private final Guild guild;
@@ -46,16 +46,6 @@ public class QueueManager {
} }
} }
public void toggleSkip(Member member) {
if (hasSkip(member)) {
logger.debug("VoteSkip: user={}, skip already exist, before={}, after={}", member.getId(), skips.size(), skips.size() - 1);
skips.remove(member.getId());
} else {
logger.debug("VoteSkip: user={}, skip doesn't exist, before={}, after={}", member.getId(), skips.size(), skips.size() + 1);
skips.add(member.getId());
}
}
public boolean hasSkip(Member member) { public boolean hasSkip(Member member) {
return skips.contains(member.getId()); return skips.contains(member.getId());
} }
@@ -134,9 +124,9 @@ public class QueueManager {
} }
} }
public TrackInfo pollHeadOfQueue() { public void removeHeadOfQueue() {
synchronized (queue) { synchronized (queue) {
return queue.poll(); queue.poll();
} }
} }
@@ -207,7 +197,7 @@ public class QueueManager {
} }
} }
public void playNextTrack(AudioPlayer player) { public void startNextTrack() {
synchronized (queue) { synchronized (queue) {
TrackInfo last = queue.poll(); TrackInfo last = queue.poll();
TrackInfo next = queue.peek(); TrackInfo next = queue.peek();
@@ -215,7 +205,7 @@ public class QueueManager {
if (next != null) { if (next != null) {
if (last != null && last.getTrack().equals(next.getTrack())) { if (last != null && last.getTrack().equals(next.getTrack())) {
logger.debug("Guild {}: duplicate track in queue found, skipping to next. last={}, next={}", guild.getId(), last.getTrack().getIdentifier(), next.getTrack().getIdentifier()); logger.debug("Guild {}: duplicate track in queue found, skipping to next. last={}, next={}", guild.getId(), last.getTrack().getIdentifier(), next.getTrack().getIdentifier());
playNextTrack(player); startNextTrack();
} else { } else {
player.startTrack(next.getTrack(), false); player.startTrack(next.getTrack(), false);
} }
@@ -223,7 +213,10 @@ public class QueueManager {
player.stopTrack(); player.stopTrack();
} }
} }
}
public void skip() {
skip(1);
} }
public void skip(int nbTrack) { public void skip(int nbTrack) {
@@ -241,18 +234,12 @@ public class QueueManager {
nbTrack = 1; nbTrack = 1;
} }
logger.debug("Guild {}: skipping tracks, toSkip={}", guild.getId(), nbTrack); logger.debug("Guild {}: skipping {} tracks", guild.getId(), nbTrack);
for (int i = 0; i < nbTrack; i++) { for (int i = 1; i < nbTrack; i++) {
TrackInfo last = queue.poll(); queue.poll();
}
TrackInfo current = queue.peek();
if (current != null) {
player.startTrack(current.getTrack(), false);
} else {
player.stopTrack();
} }
startNextTrack();
} }
} }
@@ -13,11 +13,14 @@ import netneutrality.music.loadable.CachedSource;
import netneutrality.music.loadable.LoadableMusicSource; import netneutrality.music.loadable.LoadableMusicSource;
import netneutrality.music.loadable.LoadableSong; import netneutrality.music.loadable.LoadableSong;
import netneutrality.thread.ThreadManager; import netneutrality.thread.ThreadManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
public class TrackLoader implements Runnable { public class TrackLoader implements Runnable {
private final Logger logger = LoggerFactory.getLogger(TrackLoader.class);
private final CommandContext context; private final CommandContext context;
private final MusicManager musicManager; private final MusicManager musicManager;
private final AudioPlayerManager audioPlayerManager; private final AudioPlayerManager audioPlayerManager;
@@ -40,10 +43,10 @@ public class TrackLoader implements Runnable {
public void loadAllSongs(List<LoadableSong> songs) { public void loadAllSongs(List<LoadableSong> songs) {
this.songs = songs; this.songs = songs;
if (songs.size() > 1) { if (songs.size() > 1) {
silent = true; this.silent = true;
} }
ThreadManager.getExecutor("Track loader").submit(this); ThreadManager.getMusicExecutor().submit(this);
} }
public void loadAllSongs(CachedSource cachedSource) { public void loadAllSongs(CachedSource cachedSource) {
@@ -81,7 +84,7 @@ public class TrackLoader implements Runnable {
totalNumberOfTracks++; totalNumberOfTracks++;
System.out.println("notify, loaded: " + numberOfTracksLoaded + ", total: " + totalNumberOfTracks); logger.debug("callback notify; total={}, loaded={}", totalNumberOfTracks, numberOfTracksLoaded);
sync.notify(); sync.notify();
} }
@@ -90,6 +93,8 @@ public class TrackLoader implements Runnable {
audioPlayerManager.loadItemOrdered(this, identifier, loadingHandler); audioPlayerManager.loadItemOrdered(this, identifier, loadingHandler);
} else { } else {
totalNumberOfTracks++;
if (songs.size() == 1) { if (songs.size() == 1) {
context.replyToMessage("No source found to play the given url"); context.replyToMessage("No source found to play the given url");
} }
@@ -99,7 +104,7 @@ public class TrackLoader implements Runnable {
try { try {
synchronized (sync) { synchronized (sync) {
while (!(songs.size() == totalNumberOfTracks)) { while (!(songs.size() == totalNumberOfTracks)) {
System.out.println("wait"); logger.debug("waiting for load; size={}, total={}, loaded={}", songs.size(), totalNumberOfTracks, numberOfTracksLoaded);
sync.wait(); sync.wait();
} }
@@ -109,6 +114,7 @@ public class TrackLoader implements Runnable {
} }
} }
} catch (InterruptedException exception) { } catch (InterruptedException exception) {
stopLoading();
LogHandler.log(exception); LogHandler.log(exception);
} }
@@ -71,7 +71,7 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
} }
@Override @Override
public void playlistLoaded(AudioPlaylist audioPlaylist) { public void playlistLoaded(AudioPlaylist playlist) {
if (loadConsumer != null) { if (loadConsumer != null) {
loadConsumer.accept(true); loadConsumer.accept(true);
} }
@@ -81,29 +81,29 @@ public class TrackLoadingHandler implements AudioLoadResultHandler {
} }
logger.debug("Guild {}: playlist loaded: {}", guild.getId(), identifier); logger.debug("Guild {}: playlist loaded: {}", guild.getId(), identifier);
if (!audioPlaylist.getTracks().isEmpty()) { if (!playlist.getTracks().isEmpty()) {
if (audioPlaylist.isSearchResult()) { if (playlist.isSearchResult()) {
AudioTrack track = audioPlaylist.getTracks().get(0);
AudioTrack track = playlist.getTracks().get(0);
scheduler.getQueueManager().queue(track, context.getGuildUser()); scheduler.getQueueManager().queue(track, context.getGuildUser());
if (!silent) { if (!silent) {
context.reply(MessageFunction.buildAddingTrackMessage(track, type)); context.reply(MessageFunction.buildAddingTrackMessage(track, type));
} }
return; } else {
} context.deleteMessage();
if (!silent) {
context.deleteMessage(); context.reply(MessageFunction.buildAddingPlaylistMessage(playlist, identifier, type));
if (!silent) {
context.reply(MessageFunction.buildAddingPlaylistMessage(audioPlaylist, identifier, type));
}
for (AudioTrack track : audioPlaylist.getTracks()) {
if (loadingDisabled) {
break;
} }
scheduler.getQueueManager().queue(track, context.getGuildUser()); for (AudioTrack track : playlist.getTracks()) {
if (loadingDisabled) {
break;
}
scheduler.getQueueManager().queue(track, context.getGuildUser());
}
} }
} }
} }
@@ -99,11 +99,11 @@ public class TrackScheduler extends AudioEventAdapter {
// check if mayStartNext // check if mayStartNext
if (endReason == AudioTrackEndReason.FINISHED || endReason == AudioTrackEndReason.LOAD_FAILED) { if (endReason == AudioTrackEndReason.FINISHED || endReason == AudioTrackEndReason.LOAD_FAILED) {
queueManager.playNextTrack(player); queueManager.startNextTrack();
} }
if (endReason == AudioTrackEndReason.STOPPED) { if (endReason == AudioTrackEndReason.STOPPED) {
queueManager.pollHeadOfQueue(); queueManager.removeHeadOfQueue();
} }
// endReason == FINISHED: A track finished or died by an exception (mayStartNext = true). // endReason == FINISHED: A track finished or died by an exception (mayStartNext = true).
@@ -125,6 +125,6 @@ public class TrackScheduler extends AudioEventAdapter {
public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) { public void onTrackStuck(AudioPlayer player, AudioTrack track, long thresholdMs) {
logger.debug("Guild {}: currently playing track is stuck: {}", guild.getId(), track.getIdentifier()); logger.debug("Guild {}: currently playing track is stuck: {}", guild.getId(), track.getIdentifier());
sendMessageToChannel("Current track is stuck, skipping to next"); sendMessageToChannel("Current track is stuck, skipping to next");
queueManager.playNextTrack(player); queueManager.startNextTrack();
} }
} }
@@ -7,10 +7,7 @@ package netneutrality.thread;
*/ */
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadManager { public class ThreadManager {
@@ -20,6 +17,20 @@ public class ThreadManager {
private static final Map<String, ExecutorService> executors = new ConcurrentHashMap<>(); private static final Map<String, ExecutorService> executors = new ConcurrentHashMap<>();
public static ScheduledExecutorService getMusicExecutor() {
return (ScheduledExecutorService) executors.computeIfAbsent(
"music-executor",
s -> Executors.newScheduledThreadPool(
Runtime.getRuntime().availableProcessors(),
new BaseThreadFactory("music-executor")
)
);
}
public static ExecutorService getExecutor() {
return executors.computeIfAbsent("general-executor", s -> Executors.newCachedThreadPool(new BaseThreadFactory("general-executor")));
}
public static ExecutorService getExecutor(String name) { public static ExecutorService getExecutor(String name) {
return executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name))); return executors.computeIfAbsent(name, s -> Executors.newSingleThreadExecutor(new BaseThreadFactory(name)));
} }