Skip to content

Commit b428c13

Browse files
committed
Make links and nodes thread-safe + add a getter for links
1 parent 63aa962 commit b428c13

File tree

1 file changed

+19
-8
lines changed

1 file changed

+19
-8
lines changed

src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkClient.kt

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,26 @@ import reactor.core.publisher.Flux
1111
import reactor.core.publisher.Sinks
1212
import java.io.Closeable
1313
import java.net.URI
14+
import java.util.concurrent.ConcurrentHashMap
15+
import java.util.concurrent.CopyOnWriteArrayList
1416
import java.util.concurrent.Executors
1517
import java.util.concurrent.TimeUnit
1618

1719
/**
1820
* @param userId ID of the bot for authenticating with Discord
1921
*/
2022
class LavalinkClient(val userId: Long) : Closeable, Disposable {
21-
private val internalNodes = mutableListOf<LavalinkNode>()
22-
private val links = mutableMapOf<Long, Link>()
23+
private val internalNodes = CopyOnWriteArrayList<LavalinkNode>()
24+
private val linkMap = ConcurrentHashMap<Long, Link>()
2325
private var clientOpen = true
2426

2527
// Immutable public list
2628
val nodes: List<LavalinkNode>
2729
get() = internalNodes.toList()
2830

31+
val links: List<Link>
32+
get() = linkMap.values.toList()
33+
2934
// Events forwarded from all nodes.
3035
private val sink: Sinks.Many<ClientEvent<*>> = Sinks.many().multicast().onBackpressureBuffer()
3136
val flux: Flux<ClientEvent<*>> = sink.asFlux()
@@ -70,6 +75,9 @@ class LavalinkClient(val userId: Long) : Closeable, Disposable {
7075
return node
7176
}
7277

78+
/**
79+
* Remove a node by its [name].
80+
*/
7381
fun removeNode(name: String): Boolean {
7482
val node = nodes.firstOrNull { it.name == name }
7583

@@ -80,6 +88,9 @@ class LavalinkClient(val userId: Long) : Closeable, Disposable {
8088
return removeNode(node)
8189
}
8290

91+
/**
92+
* Disconnect and remove a node the client.
93+
*/
8394
fun removeNode(node: LavalinkNode): Boolean {
8495
if (node !in internalNodes) {
8596
return false
@@ -100,19 +111,19 @@ class LavalinkClient(val userId: Long) : Closeable, Disposable {
100111
*/
101112
@JvmOverloads
102113
fun getLink(guildId: Long, region: VoiceRegion? = null): Link {
103-
if (guildId !in links) {
114+
if (!linkMap.containsKey(guildId)) {
104115
val bestNode = loadBalancer.selectNode(region)
105-
links[guildId] = Link(guildId, bestNode)
116+
linkMap[guildId] = Link(guildId, bestNode)
106117
}
107118

108-
return links[guildId]!!
119+
return linkMap[guildId]!!
109120
}
110121

111122
/**
112123
* Returns a [Link] if it exists in the cache.
113124
* If we select a link for voice updates, we don't know the region yet.
114125
*/
115-
fun getLinkIfCached(guildId: Long): Link? = links[guildId]
126+
fun getLinkIfCached(guildId: Long): Link? = linkMap[guildId]
116127

117128
internal fun onNodeDisconnected(node: LavalinkNode) {
118129
// Don't do anything if we are shutting down.
@@ -121,13 +132,13 @@ class LavalinkClient(val userId: Long) : Closeable, Disposable {
121132
}
122133

123134
if (nodes.size == 1) {
124-
links.forEach { (_, link) ->
135+
linkMap.forEach { (_, link) ->
125136
link.state = LinkState.DISCONNECTED
126137
}
127138
return
128139
}
129140

130-
links.forEach { (_, link) ->
141+
linkMap.forEach { (_, link) ->
131142
if (link.node == node) {
132143
link.transferNode(loadBalancer.selectNode(region = null))
133144
}

0 commit comments

Comments
 (0)