From 08dabd4105e41817a0d3e0ea3181a957cdfa9597 Mon Sep 17 00:00:00 2001 From: Kikkia Date: Mon, 19 Feb 2024 04:23:49 -0800 Subject: [PATCH] Add http timeout configuration for nodes (#22) * 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 * 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 --- .../arbjerg/lavalink/client/LavalinkClient.kt | 18 +++++- .../arbjerg/lavalink/client/LavalinkNode.kt | 30 ++++----- .../arbjerg/lavalink/client/NodeOptions.kt | 61 +++++++++++++++++++ .../arbjerg/lavalink/internal/constants.kt | 2 +- src/test/java/JavaJDAExample.java | 11 ++-- 5 files changed, 94 insertions(+), 28 deletions(-) create mode 100644 src/main/kotlin/dev/arbjerg/lavalink/client/NodeOptions.kt diff --git a/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkClient.kt b/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkClient.kt index 2d6007a..ad69a0d 100644 --- a/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkClient.kt +++ b/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkClient.kt @@ -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) diff --git a/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkNode.kt b/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkNode.kt index a1bab14..9489fd6 100644 --- a/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkNode.kt +++ b/src/main/kotlin/dev/arbjerg/lavalink/client/LavalinkNode.kt @@ -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.* @@ -28,8 +25,8 @@ 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 @@ -37,19 +34,20 @@ 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> = Sinks.many().multicast().onBackpressureBuffer() val flux: Flux> = sink.asFlux() @@ -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 diff --git a/src/main/kotlin/dev/arbjerg/lavalink/client/NodeOptions.kt b/src/main/kotlin/dev/arbjerg/lavalink/client/NodeOptions.kt new file mode 100644 index 0000000..ae62745 --- /dev/null +++ b/src/main/kotlin/dev/arbjerg/lavalink/client/NodeOptions.kt @@ -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) + } + } +} diff --git a/src/main/kotlin/dev/arbjerg/lavalink/internal/constants.kt b/src/main/kotlin/dev/arbjerg/lavalink/internal/constants.kt index e0faf8e..ee09e93 100644 --- a/src/main/kotlin/dev/arbjerg/lavalink/internal/constants.kt +++ b/src/main/kotlin/dev/arbjerg/lavalink/internal/constants.kt @@ -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 diff --git a/src/test/java/JavaJDAExample.java b/src/test/java/JavaJDAExample.java index 68a31e4..c3c0ad4 100644 --- a/src/test/java/JavaJDAExample.java +++ b/src/test/java/JavaJDAExample.java @@ -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) -> {