Automatically leave voice channel after some time spent idle#42
Automatically leave voice channel after some time spent idle#42SriRamanujam wants to merge 4 commits intofreyacodes:masterfrom
Conversation
freyacodes
left a comment
There was a problem hiding this comment.
You've changed the bot so that it will leave once the queue is empty after approximately 10 minutes without explanation
This is probably not what all Ukulele users want. This feature should default to be disabled.
| var game: String = "", | ||
| var trackDurationLimit: Int = 0 | ||
| var trackDurationLimit: Int = 0, | ||
| var idleTimeMinutes: Int = 10 |
There was a problem hiding this comment.
I think this should be disabled by default
| var idleTimeMinutes: Int = 10 | |
| var idleTimeMinutes: Int = 0 |
|
Okay, so in the process of reworking the PR with code review feedback I discovered a race condition of sorts. Basically, oftentimes the I tried a couple things to resolve the issue. I first tried implementing |
| class Player( | ||
| private val beans: Beans, | ||
| guildProperties: GuildProperties, | ||
| private val leaveOnIdleService: LeaveOnIdleService, |
There was a problem hiding this comment.
You're actually supposed to put this value in the Beans class and not change PlayerRegistry at all
| * Create a new timer which will start counting from the current moment and cancel any existing timers | ||
| * associated with this guild. | ||
| */ | ||
| fun maybeCreateTimer(guild: Guild) { |
There was a problem hiding this comment.
A more appropriate name is onQueueEmpty. The player doesn't control this service
| /** | ||
| * If a timer exists for this guild, cancel it. | ||
| */ | ||
| fun maybeDestroyTimer(guild: Guild) { |
There was a problem hiding this comment.
destroyTimer sounds better. We don't need to communicate that there might not be a timer to destroy
| // don't do anything if idleTimeMinutes is not set | ||
| if (botProps.idleTimeMinutes <= 0) return | ||
|
|
||
| timers[guild.idLong]?.let { |
There was a problem hiding this comment.
You can do timers.remove(guild.idLong)?.let { ... } and delete the other remove call
| * a player in a guild has spent idling. | ||
| */ | ||
| class IdleTask(val guild: Guild, private val idleTimeMinutes: Int) : Runnable { | ||
| private var numberOfMinutesIdleElapsed = -1 |
There was a problem hiding this comment.
It's a bit odd to me that you're using a counter and not a unix timestamp, but I suppose this works too.
There was a problem hiding this comment.
On second thought, could you not just schedule the voice leave after idleTimeMinutes minutes?
| * Runnable that gets passed to the Spring TaskScheduler. Used to keep track of how many minutes | ||
| * a player in a guild has spent idling. | ||
| */ | ||
| class IdleTask(val guild: Guild, private val idleTimeMinutes: Int) : Runnable { |
There was a problem hiding this comment.
If you make this an inner class you don't need to pass idleTimeMinutes
|
Hi, anything else I can do to move this along? I believed I've addressed all the comments from the last round of review. |
|
Hi SriRamanujam, Freya is currently focusing her time on her bachelor project until the 4th of January, I would probably expect replies to be sparse until then |
freyacodes
left a comment
There was a problem hiding this comment.
Sorry for the wait! There's one small thing I want you to change still
src/main/kotlin/dev/arbjerg/ukulele/features/LeaveOnIdleService.kt
Outdated
Show resolved
Hide resolved
Unfortunately, trying to model the task as a duration-based timeout saw race conditions where the callback to determine whether to start a timer was called before the callback to add a new track to the player had run. This caused an issue where the code believed that no track was playing when in fact a track would be queued mere milliseconds later. When the video in question was under a minute long, this led to a state where the bot would leave the channel a minute early. I've re-implemented the functionality such that it is invoked as part of the onTrackStart and onTrackEnd callbacks of Player. This guarantees that the idle timer kickoff logic runs _after_ all other Player state updates have completed, which neatly avoids race/ordering bugs.
* put leaveOnIdleService in Player.Beans * better names for leaveOnIdleService's callbacks * Directly call timers.remove() * Schedule VC leave task directly, rather than periodically calling timer * Clean up redundant comments
a54c36c to
b623ad2
Compare
This PR enables the bot to leave a voice channel after some time spent idle. Upon joining a channel, a scheduled task will fire every minute that checks to see if the player is idle. If it is, the task will increment an internal timer. After some configurable amount of time (
idleTimeMinutesinukulele.yml, defaults to 10 minutes) the task will have the bot automatically leave the voice channel.First time working with Kotlin and Spring, so please do point out any stylistic foibles. If there's a linter I should run, I can do that no problem.
Fixes #26