KubeMQ
Client SDKsKotlinHow-to guidesConnection

Close a KubeMQ Kotlin Client

Close a KubeMQ Kotlin client cleanly to release the gRPC connection and free server-side resources.

Overview

Closing a client isn't an afterthought — it tells the broker and your own process that this connection is done, so both sides release what they were holding for it. A KubeMQ client is more than a socket: it's a gRPC channel plus whatever subscriptions and in-flight sends it's servicing. Skip the close and those linger — subscriptions keep streaming, the channel stays open — and in short-lived processes or test suites you leak connections until the process is killed.

Kotlin's use { } block is the idiomatic way to guarantee close() runs when the block exits, even on exception, since every client type (PubSubClient, QueuesClient, CQClient) implements Closeable. Calling close() explicitly, in a finally block, gives the same guarantee with more control over when shutdown happens.

Gotchas: the drain window is bounded, not unlimited, so a slow consumer can still lose the tail of a burst if you close mid-stream; a closed client is dead forever — no reconnect on the same instance, build a new one; and when managing multiple clients, close them in reverse creation order so nothing gets routed to a channel that's already tearing down.

Prerequisites

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

Code

CloseExample.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-close"

fun main() = runBlocking {
    useBlockExample()
    explicitCloseExample()
    multiClientCloseExample()
    println("\nClose examples completed.")
}

private suspend fun useBlockExample() {
    println("=== Kotlin use { } Pattern (try-with-resources) ===\n")

    // Client auto-closes when leaving use block
    KubeMQClient.queues {
        address = ADDRESS
        clientId = "$CLIENT_ID-use"
    }.use { client ->
        val info = client.ping()
        println("Connected: ${info.host}")
        println("Client will be auto-closed when leaving this block.\n")
    }
    println("Client has been automatically closed.\n")
}

private suspend fun explicitCloseExample() {
    println("=== Explicit Close Pattern ===\n")

    var client: io.kubemq.sdk.pubsub.PubSubClient? = null
    try {
        client = KubeMQClient.pubSub {
            address = ADDRESS
            clientId = "$CLIENT_ID-explicit"
        }
        val info = client.ping()
        println("Connected: ${info.host}")
    } catch (e: Exception) {
        println("Error: ${e.message}")
    } finally {
        client?.close()
        println("Client explicitly closed.\n")
    }
}

private suspend fun multiClientCloseExample() {
    println("=== Multi-Client Close ===\n")

    var pubSubClient: io.kubemq.sdk.pubsub.PubSubClient? = null
    var queuesClient: io.kubemq.sdk.queues.QueuesClient? = null
    var cqClient: io.kubemq.sdk.cq.CQClient? = null

    try {
        pubSubClient = KubeMQClient.pubSub {
            address = ADDRESS
            clientId = "$CLIENT_ID-pubsub"
        }
        queuesClient = KubeMQClient.queues {
            address = ADDRESS
            clientId = "$CLIENT_ID-queues"
        }
        cqClient = KubeMQClient.cq {
            address = ADDRESS
            clientId = "$CLIENT_ID-cq"
        }

        println("Three clients created.")
        pubSubClient.ping()
        queuesClient.ping()
        cqClient.ping()
        println("All clients connected.\n")
    } catch (e: Exception) {
        println("Error: ${e.message}")
    } finally {
        // Close in reverse order
        cqClient?.close()
        println("CQClient closed.")
        queuesClient?.close()
        println("QueuesClient closed.")
        pubSubClient?.close()
        println("PubSubClient closed.")
    }
}

How It Works

  • The use { } block is the idiomatic Kotlin approach -- the client is automatically closed when the block exits, even on exceptions.
  • Explicit close() in a finally block provides the same guarantee with more control.
  • When managing multiple clients, close them in reverse creation order to avoid dependency issues.
  • All client types (PubSubClient, QueuesClient, CQClient) implement Closeable.

Was this page helpful?

On this page