KubeMQ
Client SDKsKotlinHow-to guidesConnection

Custom Timeouts

Configure connection timeouts, keep-alive, reconnection backoff, and RPC timeouts on a KubeMQ Kotlin client.

Overview

Every client operation has an implicit deadline — how long to wait for the initial connection, how long before a dead socket is detected, how long reconnection retries wait between attempts, how long an individual RPC blocks before giving up. The defaults are reasonable for a healthy local network, but they're wrong for high-latency links, connections that pass through load balancers or NAT gateways, or servers that occasionally run slow under load. Tuning timeouts explicitly is how you trade fast-fail behavior against tolerance for transient slowness.

Each timeout targets a different phase of the client lifecycle. ensureConnectedTimeoutMs bounds how long the client waits for the initial connection; pingIntervalSeconds / pingTimeoutSeconds configure gRPC keep-alive probes that detect a stale connection before you try to use it; the reconnection { } DSL block's initialBackoffMs / maxBackoffMs / multiplier govern exponential backoff between reconnection attempts; and unaryTimeoutMs bounds individual unary RPCs like ping(). Gotchas: a unaryTimeoutMs shorter than the server's real processing time causes spurious failures, not faster detection of a genuinely broken call; an aggressive pingIntervalSeconds can flag a slow-but-healthy link as dead; and the reconnection { } backoff has no attempt cap by default, so it will keep retrying against a server that's down for good unless you bound it yourself.

Prerequisites

  • KubeMQ server running on localhost:50000
  • Kotlin SDK installed (implementation("io.kubemq.sdk:kubemq-sdk-kotlin:1.0.1"))

Code

CustomTimeoutsExample.kt
package io.kubemq.sdk.examples.connection

import io.kubemq.sdk.client.KubeMQClient
import kotlinx.coroutines.runBlocking

private const val ADDRESS = "localhost:50000"
private const val CLIENT_ID = "kotlin-connection-custom-timeouts"

fun main() = runBlocking {
    connectionTimeoutExample()
    keepAliveTimeoutsExample()
    reconnectionTimeoutExample()
    unaryTimeoutExample()
    println("Custom timeouts examples completed.")
}

private suspend fun connectionTimeoutExample() {
    println("=== Connection Timeout Configuration ===\n")

    // ensureConnectedTimeoutMs controls how long to wait for connection
    val client = KubeMQClient.queues {
        address = ADDRESS
        clientId = "$CLIENT_ID-conn-timeout"
        ensureConnectedTimeoutMs = 10_000 // 10 seconds
    }
    client.use {
        val info = it.ping()
        println("Connected with 10s connection timeout.")
        println("Server: ${info.host}\n")
    }
}

private suspend fun keepAliveTimeoutsExample() {
    println("=== Keep-Alive Timeout Configuration ===\n")

    val client = KubeMQClient.pubSub {
        address = ADDRESS
        clientId = "$CLIENT_ID-keepalive"
        keepAlive = true
        pingIntervalSeconds = 15
        pingTimeoutSeconds = 5
    }
    client.use {
        val info = it.ping()
        println("Connected with custom keep-alive:")
        println("  Ping Interval: 15 seconds")
        println("  Ping Timeout: 5 seconds")
        println("  Server: ${info.host}\n")
    }
}

private suspend fun reconnectionTimeoutExample() {
    println("=== Reconnection Interval Configuration ===\n")

    val client = KubeMQClient.cq {
        address = ADDRESS
        clientId = "$CLIENT_ID-reconnect"
        reconnection {
            initialBackoffMs = 2000
            maxBackoffMs = 60_000
            multiplier = 2.0
        }
    }
    client.use {
        val info = it.ping()
        println("Connected with 2s base reconnect interval.")
        println("  Backoff: 2s, 4s, 8s, 16s, ... up to 60s")
        println("  Server: ${info.host}\n")
    }
}

private suspend fun unaryTimeoutExample() {
    println("=== Unary Timeout Configuration ===\n")

    // unaryTimeoutMs controls timeout for unary gRPC calls
    val client = KubeMQClient.queues {
        address = ADDRESS
        clientId = "$CLIENT_ID-unary"
        unaryTimeoutMs = 30_000 // 30 seconds
    }
    client.use {
        val info = it.ping()
        println("Connected with 30s unary timeout.")
        println("Server: ${info.host}\n")
    }
}

How It Works

  • ensureConnectedTimeoutMs controls how long the client waits for the initial connection to be established.
  • pingIntervalSeconds and pingTimeoutSeconds configure gRPC keep-alive probes.
  • The reconnection { } DSL block configures exponential backoff: initialBackoffMs, maxBackoffMs, and multiplier.
  • unaryTimeoutMs sets the deadline for individual unary gRPC calls (ping, send, etc.).

Was this page helpful?

On this page