### Basic Publish Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Demonstrates publishing multiple messages to a specified exchange with a routing key. This example publishes 'Hello World!' ten times. ```kotlin rabbitmq { repeat(10) { basicPublish { exchange = "demo-exchange" routingKey = "demo-routing-key" message { "Hello World!" } } } } ``` -------------------------------- ### Bind Queue Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Example demonstrating how to bind a queue to an exchange with a specified routing key, including declaring the queue and exchange if they don't exist. ```kotlin rabbitmq { queueBind { queue = "demo-queue" exchange = "demo-exchange" routingKey = "demo-routing-key" queueDeclare { queue = "demo-queue" durable = true } exchangeDeclare { exchange = "demo-exchange" type = "direct" } } } ``` -------------------------------- ### Install RabbitMQ Plugin Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Installs the RabbitMQ plugin and configures the connection URI, number of connection attempts, and the delay between attempts. ```APIDOC ## Install RabbitMQ Plugin ### Description Installs the RabbitMQ plugin and configures the connection URI, number of connection attempts, and the delay between attempts. ### Usage ```kotlin import io.ktor.server.application.* import io.github.damir.denis.tudor.ktor.server.rabbitmq.* fun Application.module() { install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" connectionAttempts = 10 attemptDelay = 5 } } ``` ``` -------------------------------- ### Basic RabbitMQ Plugin Installation Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/configuration.md Installs the RabbitMQ plugin with essential connection parameters like URI, default connection name, retry attempts, delay, and dispatcher thread pool size. ```kotlin import io.ktor.server.application.* fun Application.module() { install(RabbitMQ) { uri = "amqp://user:password@rabbitmq.example.com:5672" defaultConnectionName = "main" connectionAttempts = 20 attemptDelay = 10 dispatcherThreadPollSize = 4 } } ``` -------------------------------- ### Ktor RabbitMQ Plugin Configuration Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/plugin-context.md This snippet shows a complete example of configuring the RabbitMQ plugin within a Ktor application. It demonstrates setting up queue bindings, declaring exchanges and queues, configuring a producer connection to send messages, and setting up a consumer connection to process messages with acknowledgments. It also includes an example of direct library access for getting messages. ```kotlin import io.ktor.server.application.* fun Application.module() { install(RabbitMQ) rabbitmq { // Setup infrastructure queueBind { queue = "main-queue" exchange = "main-exchange" routingKey = "main" queueDeclare { queue = "main-queue" durable = true } exchangeDeclare { exchange = "main-exchange" type = "direct" } } // Producer connection connection(id = "producer") { repeat(10) { basicPublish { exchange = "main-exchange" routingKey = "main" message { "Message #$it" } } } } // Consumer connection with multiple channels connection(id = "consumer") { channel(id = 1) { basicConsume { queue = "main-queue" autoAck = false deliverCallback { println("Processed: ${it.body}") basicAck { deliveryTag = it.envelope.deliveryTag } } } } } // Raw library access libChannel(id = 10) { val result = basicGet("main-queue", false) println("Got message: ${result.body.decodeToString()}") } } } ``` -------------------------------- ### Basic Get Operation Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/types.md Demonstrates how to retrieve a message from a queue using `basicGet`. It prints the message body and remaining count, then acknowledges the message if one was received. Handles the case where the queue is empty. ```kotlin rabbitmq { basicGet { queue = "jobs" autoAck = false }?.let { response -> println("Message: ${response.body.decodeToString()}") println("Remaining: ${response.messageCount}") basicAck { deliveryTag = response.envelope.deliveryTag } } ?: println("Queue is empty") } ``` -------------------------------- ### Ktor RabbitMQ Dead Letter Queue Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md This example demonstrates setting up a dead-letter queue (DLQ) by configuring a queue with arguments that specify a dead-letter exchange and routing key. It shows how to reject messages to trigger the DLQ and consume messages from both the main queue and the DLQ. ```kotlin @Serializable data class Message( var content: String ) fun Application.module() { install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" dispatcherThreadPollSize = 3 } rabbitmq { queueBind { queue = "dlq" exchange = "dlx" routingKey = "dlq-dlx" queueDeclare { queue = "dlq" durable = true } exchangeDeclare { exchange = "dlx" type = "direct" } } queueBind { queue = "test-queue" exchange = "test-exchange" queueDeclare { queue = "test-queue" arguments = mapOf( "x-dead-letter-exchange" to "dlx", "x-dead-letter-routing-key" to "dlq-dlx" ) } exchangeDeclare { exchange = "test-exchange" type = "fanout" } } } rabbitmq { repeat(100) { basicPublish { exchange = "test-exchange" message { Message(content = "Hello world!") } } } } rabbitmq { basicConsume { queue = "test-queue" autoAck = false deliverCallback { basicReject { deliveryTag = it.envelope.deliveryTag requeue = false } } } basicConsume { queue = "dlq" autoAck = true deliverCallback { println("Received message in dead letter queue: ${it.body}") } } } } ``` -------------------------------- ### Install RabbitMQ Plugin Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md Install the RabbitMQ plugin in your Ktor application and configure the connection URI and other parameters. ```kotlin import io.ktor.server.application.* import io.github.damir.denis.tudor.ktor.server.rabbitmq.* fun Application.module() { install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" defaultConnectionName = "default" connectionAttempts = 10 attemptDelay = 5 dispatcherThreadPollSize = 4 } } ``` -------------------------------- ### Setup Queue, Exchange, and Bindings Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Declare a durable queue, a direct exchange, and bind the queue to the exchange with a specific routing key. ```kotlin rabbitmq { queueDeclare { queue = "my-queue" durable = true } exchangeDeclare { exchange = "my-exchange" type = "direct" } queueBind { queue = "my-queue" exchange = "my-exchange" routingKey = "routing.key" } } ``` -------------------------------- ### Basic Consume Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Sets up a basic consumer to receive messages from a queue. Messages are automatically acknowledged and logged upon receipt. ```kotlin rabbitmq { basicConsume { autoAck = true queue = "demo-queue" deliverCallback {\n logger.info("Received message: $message") } } } ``` -------------------------------- ### RabbitMQ Plugin Installation with Custom Coroutine Scope Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/configuration.md Installs the RabbitMQ plugin using a custom CoroutineScope, allowing for custom exception handling and supervisor jobs for RabbitMQ operations. ```kotlin import io.ktor.server.application.* import kotlinx.coroutines.* fun Application.module() { val exceptionHandler = CoroutineExceptionHandler { _, exception -> println("RabbitMQ exception: $exception") } val customScope = CoroutineScope(SupervisorJob() + exceptionHandler) install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" scope = customScope dispatcherThreadPollSize = 8 } } ``` -------------------------------- ### Ktor RabbitMQ Validation Chain Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/architecture.md Illustrates the validation chain for RabbitMQ configuration within Ktor, starting with installation and ending with constraint verification. ```text install(RabbitMQ) { config } ↓ ConnectionConfig.verify() ↓ Validate all constraints ↓ Throw IllegalArgumentException if invalid ``` -------------------------------- ### Configure Multiple RabbitMQ Connections Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md Install and configure multiple independent RabbitMQ instances, each with a unique name, for distinct producer and consumer roles. ```kotlin install(RabbitMQ(instanceName = "producer")) { ... } install(RabbitMQ(instanceName = "consumer")) { ... } rabbitmq(instanceName = "producer") { ... } rabbitmq(instanceName = "consumer") { ... } ``` -------------------------------- ### Queue Declare Operation Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/types.md Shows how to declare a queue with specific properties and then print the details of the declared queue, including its name, message count, and consumer count. ```kotlin rabbitmq { val result = queueDeclare { queue = "my-queue" durable = true } println("Queue: ${result.queue}") println("Messages: ${result.messageCount}") println("Consumers: ${result.consumerCount}") } ``` -------------------------------- ### Basic Publish Example with Custom Properties Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/types.md Shows how to publish a message with custom AMQP properties. The `basicProperties` builder allows setting various fields like `contentType`, `deliveryMode`, and custom `headers`. Ensure the exchange and routing key are correctly configured. ```kotlin rabbitmq { val props = basicProperties { contentType = "application/json" contentEncoding = "utf-8" deliveryMode = 2 // Persistent priority = 5 correlationId = "req-123" replyTo = "reply-queue" expiration = "60000" // 60 seconds headers = mapOf( "x-custom-header" to "custom-value", "x-version" to 1 ) } basicPublish { exchange = "events" routingKey = "event.created" properties = props message { "Event data" } } } ``` -------------------------------- ### Install RabbitMQ Feature Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Configure the RabbitMQ feature with connection details such as URI, connection name, retry attempts, delay, and TLS settings. ```kotlin install(RabbitMQ) { uri = "amqp://:@
:" defaultConnectionName = "" connectionAttempts = 20 attemptDelay = 10 dispatcherThreadPollSize = 4 tlsEnabled = false } ``` -------------------------------- ### Basic Consume Example with Message Handling Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/types.md Demonstrates how to consume messages from a queue using `basicConsume`. It shows how to access message body, consumer tag, and envelope details within the `deliverCallback`. Ensure the queue is declared and accessible. ```kotlin rabbitmq { basicConsume { queue = "messages" autoAck = false deliverCallback { message: Message -> println("Received: ${message.body}") println("Tag: ${message.consumerTag}") println("Exchange: ${message.envelope.exchange}") println("Routing Key: ${message.envelope.routingKey}") println("Redeliver: ${message.envelope.isRedeliver}") } } } ``` -------------------------------- ### Configure RabbitMQ in Application Scope Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/application-context.md Configures RabbitMQ within the `Application` scope. Use this for global RabbitMQ setup. ```kotlin import io.ktor.server.application.* fun Application.module() { install(RabbitMQ) rabbitmq { queueBind { queue = "orders" exchange = "orders-exchange" routingKey = "order.created" queueDeclare { queue = "orders" durable = true } exchangeDeclare { exchange = "orders-exchange" type = "direct" } } } } ``` -------------------------------- ### Multiple RabbitMQ Instances Configuration Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/configuration.md Demonstrates how to install and configure multiple independent RabbitMQ instances within a Ktor application, each with a unique instance name and specific connection details. ```kotlin import io.ktor.server.application.* fun Application.module() { // Production cluster install(RabbitMQ(instanceName = "production")) { uri = "amqp://prod-user:prod-pass@prod-rabbitmq:5672" dispatcherThreadPollSize = 8 } // Analytics cluster install(RabbitMQ(instanceName = "analytics")) { uri = "amqp://analytics-user:analytics-pass@analytics-rabbitmq:5672" dispatcherThreadPollSize = 4 } } ``` -------------------------------- ### Configure Multiple RabbitMQ Instances Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Installs and configures multiple RabbitMQ instances with distinct URIs and thread pool sizes. Sets up queues and exchanges for each instance and defines message consumption logic. ```kotlin fun Application.module() { // Production RabbitMQ cluster install(RabbitMQ(instanceName = "production")) { uri = "amqp://prod-user:prod-pass@prod-rabbitmq:5672" dispatcherThreadPollSize = 8 } // Analytics RabbitMQ cluster install(RabbitMQ(instanceName = "analytics")) { uri = "amqp://analytics-user:analytics-pass@analytics-rabbitmq:5672" dispatcherThreadPollSize = 4 } // Setup production queues rabbitmq(instanceName = "production") { queueBind { queue = "orders" exchange = "orders-exchange" routingKey = "order.created" queueDeclare { queue = "orders" durable = true } exchangeDeclare { exchange = "orders-exchange" type = "direct" } } } // Setup analytics queues rabbitmq(instanceName = "analytics") { queueBind { queue = "events" exchange = "analytics-exchange" routingKey = "user.action" queueDeclare { queue = "events" durable = false } exchangeDeclare { exchange = "analytics-exchange" type = "topic" } } } // Process critical orders rabbitmq(instanceName = "production") { basicConsume { queue = "orders" autoAck = false deliverCallback { // Process order processOrder(message.body) basicAck { deliveryTag = message.envelope.deliveryTag } // Send analytics event rabbitmq(instanceName = "analytics") { basicPublish { exchange = "analytics-exchange" routingKey = "user.action" message { "Order processed: ${message.body}" } } } } } } } ``` -------------------------------- ### Basic Get Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Retrieves a single message from a queue. ```APIDOC ## Basic Get ### Description Retrieves a single message from a queue. ### API Reference - **Function**: `basicGet()` - **Location**: [Channel Context](./api-reference/channel-context.md) - **Returns**: `GetResponse?` ``` -------------------------------- ### Library Channel Publish and Consume Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Example using the library's channel abstraction to publish a message and set up a consumer using the raw RabbitMQ Java client's DefaultConsumer. ```kotlin rabbitmq { libChannel(id = 2) { basicPublish("demo-queue", "demo-routing-key", null, "Hello!".toByteArray()) val consumer = object : DefaultConsumer(channel) { override fun handleDelivery( consumerTag: String?, envelope: Envelope?, properties: AMQP.BasicProperties?, body: ByteArray? ) { } } basicConsume("demo-queue", true, consumer) } } ``` -------------------------------- ### RabbitMQ Basic Consume with Shutdown Signal Callback Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/types.md Example demonstrating how to configure a basic consumer in RabbitMQ, including a shutdown signal callback to handle both hard errors and graceful shutdowns. ```kotlin rabbitmq { basicConsume { queue = "messages" autoAck = true deliverCallback { message -> println("Message: ${message.body}") } shutdownSignalCallback { tag, signal -> if (signal.hardError) { println("Hard error: connection closed unexpectedly") } else { println("Graceful shutdown: ${signal.reason}") } } } } ``` -------------------------------- ### RabbitMQ Plugin Installation with TLS Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/configuration.md Configures the RabbitMQ plugin for secure connections using TLS/SSL, specifying the connection URI and paths to keystore and truststore files along with their passwords. ```kotlin import io.ktor.server.application.* fun Application.module() { install(RabbitMQ) { uri = "amqps://user:password@rabbitmq.example.com:5671" tlsEnabled = true tlsKeystorePath = "/etc/rabbitmq/client-keystore.jks" tlsKeystorePassword = "keystorepass" tlsTruststorePath = "/etc/rabbitmq/client-truststore.jks" tlsTruststorePassword = "truststorepass" } } ``` -------------------------------- ### Builder Validation Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Demonstrates how the RabbitMQ builder validates required fields. Publishing without a routing key or message will result in an exception. ```kotlin rabbitmq { // This will fail with clear error if required fields are missing try { basicPublish { exchange = "events" // Missing: routingKey // Missing: message } } catch (e: Exception) { println("Publish error: ${e.message}") } } ``` -------------------------------- ### Handle IllegalStateException for Uninstalled RabbitMQ Instance Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Demonstrates catching IllegalStateException when attempting to use a RabbitMQ instance that has not been installed. Verify that the correct instanceName is used when calling rabbitmq(). ```kotlin fun Application.module() { install(RabbitMQ(instanceName = "main")) rabbitmq(instanceName = "other") { // "other" instance not installed // This will throw } } // Throws: IllegalStateException: "RabbitMQ instance 'other' is not installed" ``` -------------------------------- ### Basic Consume with JSON Deserialization and Failure Callback Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md This example shows how to consume messages with automatic JSON deserialization using kotlinx.serialization. It includes a `deliverFailureCallback` to handle messages that fail to deserialize. ```kotlin import kotlinx.serialization.Serializable @Serializable data class OrderEvent(val orderId: String, val amount: Double) rabbitmq { basicConsume { queue = "orders" autoAck = false deliverCallback { println("Order ${it.body.orderId}: $${it.body.amount}") basicAck { deliveryTag = it.envelope.deliveryTag } } deliverFailureCallback { println("Failed to deserialize: ${it.body.decodeToString()}") } } } ``` -------------------------------- ### Ktor RabbitMQ Serialization Fallback Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md This snippet shows how to configure RabbitMQ, bind queues and exchanges, and publish messages. It includes a `deliverFailureCallback` to handle messages that cannot be deserialized into the expected `Message` type, printing them as byte arrays instead. ```kotlin @Serializable data class Message( var content: String ) fun Application.module() { install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" dispatcherThreadPollSize = 3 } rabbitmq { queueBind { queue = "test-queue" exchange = "test-exchange" queueDeclare { queue = "test-queue" arguments = mapOf( "x-dead-letter-exchange" to "dlx", "x-dead-letter-routing-key" to "dlq-dlx" ) } exchangeDeclare { exchange = "test-exchange" type = "fanout" } } } rabbitmq { repeat(10) { basicPublish { exchange = "test-exchange" message { Message(content = "Hello world!") } } } repeat(10) { basicPublish { exchange = "test-exchange" message { "Hello world!" } } } } rabbitmq { basicConsume { queue = "test-queue" autoAck = false deliverCallback { println("Received as Message: ${it.body}") } deliverFailureCallback { println("Could not serialize, received as ByteArray: ${it.body}") } } } } ``` -------------------------------- ### Ktor RabbitMQ Plugin API Hierarchy Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/README.md Illustrates the hierarchical structure for accessing RabbitMQ functionalities within the Ktor plugin, from installation to raw Java API access. ```text install(RabbitMQ) ── plugin installation ↓ Application.rabbitmq() ── entry point, accesses PluginContext ├─ Default connection + default channel ├─ Direct operations (publish, consume, declare, etc.) │ ├─ PluginContext.channel() ── new numbered channel │ └─ Channel-scoped operations │ ├─ PluginContext.connection() ── new named connection │ ├─ Default channel + connection-level context │ ├─ ConnectionContext.channel() ── new channel in this connection │ └─ ConnectionContext.libChannel() ── raw channel access │ ├─ PluginContext.libChannel() ── raw channel (Java API) └─ PluginContext.libConnection() ── raw connection (Java API) ``` -------------------------------- ### Enable Detailed RabbitMQ Logging Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Configure your logging framework to DEBUG level for the RabbitMQ integration package to get detailed insights into its operations. ```xml ``` -------------------------------- ### Configure RabbitMQ Plugin in Ktor Application Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/README.md Install the RabbitMQ plugin in your Ktor application's module function. Configure the RabbitMQ connection URI using the `uri` property. ```kotlin import io.ktor.server.application.* import io.github.damir.denis.tudor.ktor.server.rabbitmq.* fun Application.module() { install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" } } ``` -------------------------------- ### Basic Get a Single Message with Manual Acknowledgment Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md Use `basicGet` to retrieve a single message from a queue without establishing a persistent consumer. This is useful for one-off message retrieval or polling scenarios. Manual acknowledgment is demonstrated. ```kotlin rabbitmq { basicGet { queue = "jobs" autoAck = false }?.let { println("Got message: ${it.body.decodeToString()}") println("Remaining in queue: ${it.messageCount}") basicAck { deliveryTag = it.envelope.deliveryTag } } ?: run { println("Queue is empty") } } ``` -------------------------------- ### Using Default and Specific Connections Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/connection-context.md Demonstrates how to perform basic publish operations on both the default RabbitMQ connection and a specifically named connection within the Ktor server. ```kotlin rabbitmq { // Default channel operations on default connection basicPublish { exchange = "main" routingKey = "default" message { "On default connection" } } // Specific connection connection(id = "worker") { // Now operating within "worker" connection basicPublish { exchange = "worker" routingKey = "work" message { "On worker connection" } } } } ``` -------------------------------- ### Get Connection Channel Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Operates on the default channel of a connection. ```APIDOC ## Get Connection Channel ### Description Operates on the default channel of a connection. ### API Reference - **Function**: `channel()` - **Location**: [Connection Context](./api-reference/connection-context.md) - **Returns**: `Channel` ``` -------------------------------- ### Kotlin - Using connection for producer and consumer Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/plugin-context.md Demonstrates how to use the `connection` function to set up separate connections for publishing messages to an 'orders' exchange and consuming from an 'orders' queue. ```kotlin rabbitmq { connection(id = "producer") { repeat(100) { basicPublish { exchange = "orders" routingKey = "order.created" message { "Order #$it" } } } } connection(id = "consumer") { basicConsume { queue = "orders" autoAck = false deliverCallback { println("Processing: ${message.body}") basicAck { deliveryTag = message.envelope.deliveryTag } } } } } ``` -------------------------------- ### consumerCount() Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md Gets the number of active consumers for a specified queue. ```APIDOC ## consumerCount() ### Description Gets the number of active consumers for a specified queue. ### Method `suspend fun ChannelContext.consumerCount(block: suspend ConsumerCountBuilder.() -> Unit): Long` ### Parameters (within the block) #### Path Parameters - **queue** (String) - Required - Queue name ### Returns Number of active consumers ``` -------------------------------- ### messageCount() Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md Gets the number of messages currently in a specified queue. ```APIDOC ## messageCount() ### Description Gets the number of messages currently in a specified queue. ### Method `suspend fun ChannelContext.messageCount(block: suspend MessageCountBuilder.() -> Unit): Long` ### Parameters (within the block) #### Path Parameters - **queue** (String) - Required - Queue name ### Returns Number of messages in the queue ### Request Example ```kotlin rabbitmq { val count = messageCount { queue = "pending-jobs" } println("Pending jobs: $count") } ``` ``` -------------------------------- ### Builder Pattern for Basic Publish Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Demonstrates the fluent builder pattern used for constructing and executing basic publish operations in RabbitMQ. ```text BasicPublishBuilder ├─ exchange: String (required) ├─ routingKey: String (optional) ├─ message: ByteArray (required) ├─ properties: Properties (optional) └─ build() → execute ``` -------------------------------- ### Get Connection Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Operates on a named connection within the plugin context. ```APIDOC ## Get Connection ### Description Operates on a named connection within the plugin context. ### API Reference - **Function**: `connection()` - **Location**: [Plugin Context](./api-reference/plugin-context.md) - **Returns**: — ``` -------------------------------- ### Get Channel Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Operates on the default channel within the plugin context. ```APIDOC ## Get Channel ### Description Operates on the default channel within the plugin context. ### API Reference - **Function**: `channel()` - **Location**: [Plugin Context](./api-reference/plugin-context.md) - **Returns**: `Channel` ``` -------------------------------- ### Get Raw Connection Channel Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Provides raw access to a channel within a connection. ```APIDOC ## Get Raw Connection Channel ### Description Provides raw access to a channel within a connection. ### API Reference - **Function**: `libChannel()` - **Location**: [Connection Context](./api-reference/connection-context.md) - **Returns**: `Channel` ``` -------------------------------- ### Get Raw Connection Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Provides raw access to a connection within the plugin context. ```APIDOC ## Get Raw Connection ### Description Provides raw access to a connection within the plugin context. ### API Reference - **Function**: `libConnection()` - **Location**: [Plugin Context](./api-reference/plugin-context.md) - **Returns**: — ``` -------------------------------- ### Get Raw Channel Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Provides raw access to a channel within the plugin context. ```APIDOC ## Get Raw Channel ### Description Provides raw access to a channel within the plugin context. ### API Reference - **Function**: `libChannel()` - **Location**: [Plugin Context](./api-reference/plugin-context.md) - **Returns**: `Channel` ``` -------------------------------- ### Library Connection Create Channel Publish and Consume Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Demonstrates creating a channel via a library connection, publishing a message, and setting up a consumer using the raw RabbitMQ Java client's DefaultConsumer. ```kotlin rabbitmq { libConnection(id = "lib-connection") { val channel = createChannel() channel.basicPublish("demo-queue", "demo-routing-key", null, "Hello!".toByteArray()) val consumer = object : DefaultConsumer(channel) { override fun handleDelivery( consumerTag: String?, envelope: Envelope?, properties: AMQP.BasicProperties?, body: ByteArray? ) { } } channel.basicConsume("demo-queue", true, consumer) } } ``` -------------------------------- ### Get Connection Numbered Channel Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Operates on a specific numbered channel of a connection, with an option to auto-close. ```APIDOC ## Get Connection Numbered Channel ### Description Operates on a specific numbered channel of a connection, with an option to auto-close. ### API Reference - **Function**: `channel(id, autoClose)` - **Location**: [Connection Context](./api-reference/connection-context.md) - **Returns**: `Channel` ``` -------------------------------- ### Get Numbered Channel Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/INDEX.md Operates on a specific numbered channel within the plugin context, with an option to auto-close. ```APIDOC ## Get Numbered Channel ### Description Operates on a specific numbered channel within the plugin context, with an option to auto-close. ### API Reference - **Function**: `channel(id, autoClose)` - **Location**: [Plugin Context](./api-reference/plugin-context.md) - **Returns**: `Channel` ``` -------------------------------- ### Get Message Count in a Queue Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md Use messageCount to retrieve the number of messages currently in a specified queue. ```kotlin rabbitmq { val count = messageCount { queue = "pending-jobs" } println("Pending jobs: $count") } ``` -------------------------------- ### Configure Channel QoS Settings Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md Use basicQos to set prefetch count and other quality of service parameters for consumers. This helps manage message flow and prevent consumers from being overwhelmed. ```kotlin rabbitmq { basicQos { prefetchCount = 10 global = false // Per-consumer setting } basicConsume { queue = "high-load-queue" autoAck = false deliverCallback { processHeavyMessage(message.body) } } } ``` -------------------------------- ### Configuring Basic Message Properties Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md Demonstrates how to set standard message properties like content type, encoding, delivery mode, priority, and expiration. ```kotlin basicProperties { contentType = "application/json" contentEncoding = "utf-8" deliveryMode = 2 // 1: non-persistent, 2: persistent priority = 5 correlationId = "id-123" replyTo = "reply-queue" expiration = "60000" messageId = "msg-123" timestamp = System.currentTimeMillis() type = "order.created" userId = "user-123" appId = "my-app" headers = mapOf("custom" to "value") } ``` -------------------------------- ### Configure Multiple RabbitMQ Connections Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/README.md Sets up a default RabbitMQ connection and then defines separate connections for producers and consumers with specific configurations. Includes queue binding and message publishing/consuming logic. ```kotlin fun Application.module() { install(RabbitMQ) { uri = "amqp://guest:guest@localhost:5672" defaultConnectionName = "default" } rabbitmq { // Setup queues and exchanges queueBind { queue = "orders-queue" exchange = "orders-exchange" routingKey = "order.created" queueDeclare { queue = "orders-queue" durable = true } exchangeDeclare { exchange = "orders-exchange" type = "direct" } } } // Producer connection rabbitmq { connection(id = "producer") { repeat(100) { basicPublish { exchange = "orders-exchange" routingKey = "order.created" message { "Order #$it created" } } } } } // Consumer connection with high throughput rabbitmq { connection(id = "consumer") { basicConsume { queue = "orders-queue" autoAck = false dispatcher = Dispatchers.IO coroutinePollSize = 10 deliverCallback { // Process order println("Processing: ${message.body}") delay(100) // Simulate processing time basicAck { deliveryTag = message.envelope.deliveryTag } } } } } } ``` -------------------------------- ### Configure Basic QoS Settings Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Use this snippet to set Quality of Service parameters for message consumption, such as the number of messages to prefetch. Ensure `prefetchCount` is provided as it is a required property. ```kotlin basicQos { prefetchCount = 10 global = false } ``` -------------------------------- ### Delegator Pattern Error Example Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Illustrates the IllegalStateException thrown when a required property, like 'exchange', is not initialized in a builder using the Delegator pattern. ```kotlin IllegalStateException: Property 'exchange' was not initialized ``` -------------------------------- ### Defining Queue Arguments Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md Illustrates how to specify arguments when declaring a queue, including dead-letter exchange, message TTL, max length, and queue type. ```kotlin queueDeclare { queue = "my-queue" arguments = mapOf( "x-dead-letter-exchange" to "dlx", "x-dead-letter-routing-key" to "dlq", "x-message-ttl" to 3600000, "x-max-length" to 10000, "x-queue-type" to "classic" ) } ``` -------------------------------- ### Channel Context RabbitMQ Message Operations Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/architecture.md Suspendable functions for performing basic message operations like publishing, consuming, and getting messages. ```kotlin suspend fun basicPublish(block) ``` ```kotlin suspend fun basicConsume(block): String ``` ```kotlin suspend fun basicGet(block): GetResponse? ``` -------------------------------- ### Handle ShutdownSignalException in Consumer Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Demonstrates how to use the shutdownSignalCallback to detect and react to broker-initiated shutdowns within a consumer. Implement reconnection logic here for critical errors. ```kotlin rabbitmq { basicConsume { queue = "important" autoAck = true deliverCallback { message -> println("Received: ${message.body}") } shutdownSignalCallback { tag, signal -> if (signal.hardError) { println("CRITICAL: Unexpected broker disconnection") println("Error: ${signal.reason}") // Implement reconnection logic } else if (signal.initiatedByApplication) { println("Channel closed by application") } else { println("Normal shutdown: ${signal.reason}") } } } } ``` -------------------------------- ### Validate RabbitMQ Configuration Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Ensures that essential RabbitMQ configuration, like the URI, is present before attempting to install the plugin. Throws IllegalArgumentException if configuration is missing. ```kotlin fun Application.module() { try { install(RabbitMQ) { uri = environment.config.tryGetString("rabbitmq.uri") ?: error("RABBITMQ_URI not set") connectionAttempts = 10 attemptDelay = 5 } } catch (e: IllegalArgumentException) { logger.error("Invalid RabbitMQ configuration: ${e.message}") throw e } } ``` -------------------------------- ### Basic Publish Builder Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md Use the correct fields when building a basic publish message. Ensure exchange, routing key, and message content are provided. ```kotlin // ❌ Will fail basicPublish { } // ✅ Correct basicPublish { exchange = "test" routingKey = "test" message { "data" } } ``` -------------------------------- ### Get Consumer Count for Queue Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Use this snippet to find out how many consumers are currently connected to a specific RabbitMQ queue. The 'orders' queue should be active. ```kotlin val consumers = consumerCount { queue = "orders" } println("Active consumers: $consumers") ``` -------------------------------- ### Get Message Count in Queue Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Use this snippet to retrieve the number of messages currently in a specified RabbitMQ queue. Ensure the 'pending' queue exists. ```kotlin val count = messageCount { queue = "pending" } println("Pending messages: $count") ``` -------------------------------- ### Kotlin - Using libConnection for raw channel operations Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/plugin-context.md Illustrates using `libConnection` to obtain a raw `Channel` object for direct interaction with the RabbitMQ client library, including publishing a message and closing the channel. ```kotlin import com.rabbitmq.client.Channel rabbitmq { libConnection(id = "advanced") { val channel: Channel = createChannel() channel.basicPublish("exchange", "routing-key", null, "Raw message".toByteArray()) channel.close() } } ``` -------------------------------- ### Basic Consume with Manual Acknowledgment and Error Handling Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md This snippet demonstrates manual message acknowledgment and nack for robust error handling. Use it when you need to explicitly confirm message processing or requeue messages on failure. ```kotlin rabbitmq { basicConsume { queue = "orders" autoAck = false deliverCallback { try { processOrder(it.body) basicAck { deliveryTag = it.envelope.deliveryTag } } catch (e: Exception) { basicNack { deliveryTag = it.envelope.deliveryTag requeue = true } } } } } ``` -------------------------------- ### basicQos() Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/channel-context.md Sets Quality of Service (QoS) settings for the channel, controlling message flow and consumer load balancing. ```APIDOC ## basicQos() ### Description Sets Quality of Service (QoS) settings for the channel, controlling message flow and consumer load balancing. ### Method `suspend fun ChannelContext.basicQos(block: suspend BasicQosBuilder.() -> Unit)` ### Parameters (within the block) #### Path Parameters (Not applicable) #### Query Parameters (Not applicable) #### Request Body (Not applicable) ### Request Example ```kotlin rabbitmq { basicQos { prefetchCount = 10 global = false // Per-consumer setting } basicConsume { queue = "high-load-queue" autoAck = false deliverCallback { message -> processHeavyMessage(message.body) } } } ``` ### Response #### Success Response (Unit) Returns `Unit`. #### Response Example (Not applicable) ``` -------------------------------- ### Basic Consume with AutoAck and Reject Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md When using `autoAck = true` with `basicConsume`, do not use `basicReject` as the message is already acknowledged. Set `autoAck = false` if manual acknowledgment or rejection is needed. ```kotlin // ❌ Will fail - message already acked basicConsume { autoAck = true deliverCallback { msg -> basicReject { deliveryTag = msg.envelope.deliveryTag } } } // ✅ Correct basicConsume { autoAck = false deliverCallback { msg -> basicReject { deliveryTag = msg.envelope.deliveryTag } } } ``` -------------------------------- ### BasicQosBuilder Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Sets Quality of Service settings for message consumption. This builder allows configuration of prefetch size and count, and whether the settings apply globally to all consumers. ```APIDOC ## basicQos ### Description Sets Quality of Service settings for message consumption, allowing configuration of prefetch size and count, and whether the settings apply globally. ### Method `suspend fun ChannelContext.basicQos(block: suspend BasicQosBuilder.() -> Unit)` ### Parameters #### Properties - **prefetchSize** (`Int`) - Optional - Bytes to prefetch (0 = unlimited) - **prefetchCount** (`Int`) - Required - Messages to prefetch - **global** (`Boolean`) - Optional - Apply to all consumers ### Request Example ```kotlin basicQos { prefetchCount = 10 global = false } ``` ### Response #### Success Response `Unit` ``` -------------------------------- ### Common Ktor RabbitMQ Imports Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/quick-reference.md Import necessary classes for Ktor server, routing, and RabbitMQ integration, including message models and serialization. ```kotlin import io.ktor.server.application.* import io.ktor.server.routing.* import io.github.damir.denis.tudor.ktor.server.rabbitmq.* import io.github.damir.denis.tudor.ktor.server.rabbitmq.model.dto.Message import kotlinx.serialization.Serializable ``` -------------------------------- ### Application.rabbitmq() Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/application-context.md Configures RabbitMQ within the Application scope. It takes an optional instance name and a suspendable block for RabbitMQ operations, launching a background coroutine. ```APIDOC ## Application.rabbitmq() ### Description Configures RabbitMQ within the `Application` scope. This function provides access to a `PluginContext` which extends `ChannelContext` and enables queue setup and message operations within the default connection and channel. ### Method Extension Function ### Endpoint N/A (Ktor Plugin Configuration) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```kotlin import io.ktor.server.application.* fun Application.module() { install(RabbitMQ) rabbitmq { queueBind { queue = "orders" exchange = "orders-exchange" routingKey = "order.created" queueDeclare { queue = "orders" durable = true } exchangeDeclare { exchange = "orders-exchange" type = "direct" } } } } ``` ### Response #### Success Response `Unit` (launches a background coroutine) #### Response Example N/A ``` -------------------------------- ### Get a Single Message with BasicGetBuilder Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Retrieves a single message from a specified queue. Set autoAck to false to manually acknowledge messages. The response contains the message body and count, and requires manual acknowledgment. ```kotlin basicGet { queue = "jobs" autoAck = false }?.let { println("Got: ${it.body.decodeToString()}") println("Remaining: ${it.messageCount}") basicAck { deliveryTag = it.envelope.deliveryTag } } ``` -------------------------------- ### Multiple RabbitMQ Connections Pattern Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/connection-context.md Demonstrates setting up distinct producer and consumer connections within a single RabbitMQ configuration block. This pattern is useful for isolating concerns and managing resources efficiently. ```kotlin import io.ktor.server.application.* fun Application.module() { install(RabbitMQ) rabbitmq { // Setup exchanges and queues exchangeDeclare { exchange = "orders" type = "direct" durable = true } queueDeclare { queue = "orders-queue" durable = true } queueBind { exchange = "orders" queue = "orders-queue" routingKey = "order.#" } // Producer connection: Dedicated for publishing connection(id = "producer") { basicPublish { exchange = "orders" routingKey = "order.created" message { "Order #123 created" } } } // Consumer connection: Dedicated for consuming connection(id = "consumer") { basicQos { prefetchCount = 10 } basicConsume { queue = "orders-queue" autoAck = false deliverCallback { message -> println("Processing: ${message.body}") basicAck { deliveryTag = message.envelope.deliveryTag } } } } } } ``` -------------------------------- ### Configure Connection Retries for Startup Stability Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Configure the RabbitMQ plugin to automatically retry establishing a connection to the RabbitMQ server during application startup. This prevents startup failures due to temporary network issues or RabbitMQ unavailability. ```kotlin install(RabbitMQ) { uri = "amqp://rabbitmq:5672" connectionAttempts = 30 // Try for ~2.5 minutes with default delay attemptDelay = 5 // 5 seconds between attempts } ``` -------------------------------- ### Bind Queue to Exchange with Routing Key Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/builders.md Use QueueBindBuilder to bind the 'orders' queue to the 'orders-exchange' with a routing key pattern 'order.#'. This allows messages with a routing key starting with 'order.' to be routed to this queue. ```kotlin queueBind { queue = "orders" exchange = "orders-exchange" routingKey = "order.#" } ``` -------------------------------- ### Declare Exchange, Queue, and Bindings for Message Routing Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/errors.md Ensure that the exchange, queue, and their bindings are correctly configured before publishing messages. This snippet demonstrates how to declare a direct exchange, a queue, and bind them with a routing key. ```kotlin rabbitmq { // Ensure exchange and binding exist exchangeDeclare { exchange = "orders" type = "direct" } queueDeclare { queue = "orders-queue" } queueBind { exchange = "orders" queue = "orders-queue" routingKey = "order.#" } // Now publish basicPublish { exchange = "orders" routingKey = "order.created" message { "Order #123" } } } ``` -------------------------------- ### Error Handling with ConnectionContext and ChannelContext Source: https://github.com/damirdenis-tudor/ktor-server-rabbitmq/blob/main/_autodocs/api-reference/connection-context.md Illustrates how to implement error handling for message consumption within a specific connection and channel. It shows how to use try-catch blocks for processing messages and handling channel-level errors, including nacking and requeuing messages. ```kotlin rabbitmq { connection(id = "resilient") { channel(id = 1) { try { basicConsume { queue = "important" autoAck = false deliverCallback { try { processImportant(it.body) basicAck { deliveryTag = it.envelope.deliveryTag } } catch (e: Exception) { basicNack { deliveryTag = it.envelope.deliveryTag requeue = true } } } cancelCallback { tag -> println("Consumer $tag was cancelled") } shutdownSignalCallback { tag, signal -> println("Channel shutdown: ${signal.reason}") } } } catch (e: Exception) { println("Connection error: ${e.message}") } } } } ```