Skip to content

Commit

Permalink
Add http timeout configuration for nodes (#22)
Browse files Browse the repository at this point in the history
* Add http timeout configuration for nodes

* add param in comment for httpTimeout

* Update src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkNode.kt

Co-authored-by: Duncan Sterken <contact@duncte123.me>

* add LavalinkNodeOptions

* remove some unused imports in LavalinkClient

* update nodeOptions constructor to private, update example JDA bot to use new NodeOptions builder

* update builder to set naming

---------

Co-authored-by: Duncan Sterken <contact@duncte123.me>
  • Loading branch information
kikkia and duncte123 authored Feb 19, 2024
1 parent 6c9bdc9 commit 08dabd4
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 28 deletions.
18 changes: 15 additions & 3 deletions src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkClient.kt
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,24 @@ class LavalinkClient(val userId: Long) : Closeable, Disposable {
* @param regionFilter (not currently used) Allows you to limit your node to a specific discord voice region
*/
@JvmOverloads
@Deprecated("Use NodeOptions instead",
ReplaceWith("addNode(NodeOptions.Builder()...build())")
)
fun addNode(name: String, address: URI, password: String, regionFilter: IRegionFilter? = null): LavalinkNode {
if (nodes.any { it.name == name }) {
throw IllegalStateException("Node with name '$name' already exists")
return addNode(NodeOptions.Builder().setName(name).setServerUri(address).setPassword(password).setRegionFilter(regionFilter).build())
}

/**
* Add a node to the client.
*
* @param nodeOptions a populated NodeOptionsObject
*/
fun addNode(nodeOptions: NodeOptions): LavalinkNode {
if (nodes.any { it.name == nodeOptions.name }) {
throw IllegalStateException("Node with name '${nodeOptions.name}' already exists")
}

val node = LavalinkNode(name, address, password, regionFilter, this)
val node = LavalinkNode(nodeOptions, this)
internalNodes.add(node)

listenForNodeEvent(node)
Expand Down
30 changes: 11 additions & 19 deletions src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkNode.kt
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package dev.arbjerg.lavalink.client

import dev.arbjerg.lavalink.client.http.HttpBuilder
import dev.arbjerg.lavalink.client.loadbalancing.IRegionFilter
import dev.arbjerg.lavalink.client.protocol.LavalinkLoadResult
import dev.arbjerg.lavalink.client.protocol.Track
import dev.arbjerg.lavalink.client.protocol.toCustom
import dev.arbjerg.lavalink.client.protocol.toLavalinkLoadResult
import dev.arbjerg.lavalink.internal.LavalinkRestClient
import dev.arbjerg.lavalink.internal.LavalinkSocket
import dev.arbjerg.lavalink.internal.*
import dev.arbjerg.lavalink.internal.error.RestException
import dev.arbjerg.lavalink.internal.fromRawJson
import dev.arbjerg.lavalink.internal.loadbalancing.Penalties
import dev.arbjerg.lavalink.internal.toLavalinkPlayer
import dev.arbjerg.lavalink.protocol.v4.*
Expand All @@ -28,28 +25,29 @@ import reactor.core.publisher.Sinks.Many
import reactor.kotlin.core.publisher.toMono
import java.io.Closeable
import java.io.IOException
import java.net.URI
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
import java.util.function.UnaryOperator

/**
* The Node is a physical instance of the lavalink server software.
*/
class LavalinkNode(
val name: String,
serverUri: URI,
val password: String,
val regionFilter: IRegionFilter?,
private val nodeOptions: NodeOptions,
val lavalink: LavalinkClient
) : Disposable, Closeable {
// "safe" uri with all paths removed
val baseUri = "${serverUri.scheme}://${serverUri.host}:${serverUri.port}"
val baseUri = "${nodeOptions.serverUri.scheme}://${nodeOptions.serverUri.host}:${nodeOptions.serverUri.port}"

val name = nodeOptions.name
val regionFilter = nodeOptions.regionFilter
val password = nodeOptions.password

var sessionId: String? = null
internal set

internal val httpClient = OkHttpClient()
internal val httpClient = OkHttpClient.Builder().callTimeout(nodeOptions.httpTimeout, TimeUnit.MILLISECONDS).build()

internal val sink: Many<ClientEvent<*>> = Sinks.many().multicast().onBackpressureBuffer()
val flux: Flux<ClientEvent<*>> = sink.asFlux()
Expand Down Expand Up @@ -420,19 +418,13 @@ class LavalinkNode(

other as LavalinkNode

if (name != other.name) return false
if (password != other.password) return false
if (regionFilter != other.regionFilter) return false
if (baseUri != other.baseUri) return false
if (nodeOptions != other.nodeOptions) return false
if (sessionId != other.sessionId) return false
return available == other.available
}

override fun hashCode(): Int {
var result = name.hashCode()
result = 31 * result + password.hashCode()
result = 31 * result + regionFilter.hashCode()
result = 31 * result + baseUri.hashCode()
var result = nodeOptions.hashCode()
result = 31 * result + sessionId.hashCode()
result = 31 * result + available.hashCode()
return result
Expand Down
61 changes: 61 additions & 0 deletions src/main/kotlin/dev/arbjerg/lavalink/client/NodeOptions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package dev.arbjerg.lavalink.client

import dev.arbjerg.lavalink.client.loadbalancing.IRegionFilter
import dev.arbjerg.lavalink.internal.TIMEOUT_MS
import java.net.URI

data class NodeOptions private constructor(val name: String,
val serverUri: URI,
val password: String,
val regionFilter: IRegionFilter?,
val httpTimeout: Long) {
data class Builder(
private var name: String? = null,
private var serverUri: URI? = null,
private var password: String? = null,
private var regionFilter: IRegionFilter? = null,
private var httpTimeout: Long = TIMEOUT_MS,
) {
fun setName(name: String) = apply { this.name = name }

/**
* Sets the server URI of the Lavalink Node.
* @param serverUriString - String representation of server uri
*/
fun setServerUri(serverUriString: String) = apply { this.serverUri = URI(serverUriString) }
/**
* Sets the server URI of the Lavalink Node.
* @param serverUri - Server uri
*/
fun setServerUri(serverUri: URI) = apply { this.serverUri = serverUri }
/**
* Sets the password to access the node.
* @param password - Server password
*/
fun setPassword(password: String) = apply { this.password = password }

/**
* Sets a region filter on the node for regional load balancing (Default: none)
*/
fun setRegionFilter(regionFilter: IRegionFilter?) = apply { this.regionFilter = regionFilter }

/**
* Sets the http total call timeout. (Default: 10000ms)
* @param httpTimeout - timeout in ms
*/
fun setHttpTimeout(httpTimeout: Long) = apply { this.httpTimeout = httpTimeout }

fun build(): NodeOptions {
requireNotNull(name) { "name is required" }
requireNotNull(serverUri) { "serverUri is required" }
requireNotNull(password) { "password is required" }

return NodeOptions(
name!!,
serverUri!!,
password!!,
regionFilter,
httpTimeout)
}
}
}
2 changes: 1 addition & 1 deletion src/main/kotlin/dev/arbjerg/lavalink/internal/constants.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package dev.arbjerg.lavalink.internal

internal const val TIMEOUT_MS = 5000
internal const val TIMEOUT_MS = 10000L
internal const val METRIC_MAX_HISTORY = 100
11 changes: 6 additions & 5 deletions src/test/java/JavaJDAExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,12 @@ private void registerLavalinkNodes() {
RegionGroup.EUROPE
),*/

client.addNode(
"Mac-mini",
URI.create("ws://mac-mini.local.duncte123.lgbt:2333/bepis"),
"youshallnotpass",
RegionGroup.US
client.addNode(new NodeOptions.Builder().setName("Mac-mini")
.setServerUri(URI.create("ws://mac-mini.local.duncte123.lgbt:2333/bepis"))
.setPassword("youshallnotpass")
.setRegionFilter(RegionGroup.US)
.setHttpTimeout(5000L)
.build()
)
).forEach((node) -> {
node.on(TrackStartEvent.class).subscribe((event) -> {
Expand Down

0 comments on commit 08dabd4

Please sign in to comment.