Skip to content

Quafka is a non-blocking Kafka client library built on top of the Apache Kafka Java client, designed for Kotlin with first-class coroutine support.

License

Notifications You must be signed in to change notification settings

Trendyol/quafka

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

21 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

OpenSSF Scorecard

Quafka
Quafka

A non-blocking Kafka client library for Kotlin with first-class coroutine support

codecov License

Features โ€ข Getting Started โ€ข Examples โ€ข Documentation โ€ข Contributing


About

Quafka is a non-blocking Kafka client library built on top of the Apache Kafka Java client, designed for Kotlin with first-class coroutine support. It separates polling from processing, preserves per-partition ordering, and provides flexible single and batch message handling, backpressure control, and a fluent, type-safe configuration DSL.

Quafka also ships with an extensions module that adds higher-level capabilities like retry orchestration, delayed processing, and a middleware pipeline for consumer logic.

Features

Core Features

  • ๐Ÿš€ Non-Blocking & Coroutine-First

    • Fully supports Kotlin coroutines, enabling highly efficient, asynchronous operations
    • Ensures your Kafka client remains responsive and scalable under heavy loads without thread management complexity
  • ๐Ÿ”„ Separated Polling and Processing Model

    • Decoupled threading model where polling and processing happen independently
    • Prevents consumer group rebalancing due to slow processing
    • Ensures consistent throughput even for long-running tasks
  • โšก Worker per Topic and Partition

    • Dedicated workers for each topic-partition pair
    • Sequential processing within a partition for order preservation
    • Maximum parallelism across partitions for optimal resource utilization
  • ๐Ÿ“ฆ Batch and Single Message Handling

    • Seamless support for both batch and individual message processing
    • Flexible callbacks to choose the most efficient approach
    • Reduced boilerplate code
  • ๐ŸŽ›๏ธ Backpressure Management

    • Advanced backpressure controls that dynamically adjust message fetching
    • Prevents memory overload and ensures graceful degradation
    • Configurable using message count, timeouts, or both
  • ๐Ÿ”ง Fluent and Safe Configuration

    • Developer-friendly configuration DSL
    • Type-safe defaults and validations
    • Step-by-step guidance for setup
  • ๐Ÿ“ค Batch Publishing

    • Efficiently publish multiple messages in a single operation
    • Reduced network overhead for improved performance
    • Ideal for high-throughput scenarios
  • ๐Ÿ›ก๏ธ Error Handling

    • Robust error handling with automatic retries
    • Error callbacks and configurable failure strategies
    • Graceful recovery from unexpected issues

Why Quafka?

Compared to Apache Kafka Java Client

Feature Quafka Apache Kafka Java Client
Coroutine Support โœ… Native coroutine APIs โŒ Blocking/callback-based
Boilerplate โœ… Minimal with builders โŒ Verbose configuration
Poll/Process Separation โœ… Built-in decoupling โŒ Manual implementation
Backpressure โœ… Simple configuration โŒ Manual implementation
Retry Mechanism โœ… Built-in with extensions โŒ Custom implementation needed

Compared to Spring Kafka

Feature Quafka Spring Kafka
API Style โœ… Lightweight Kotlin API โš ๏ธ Spring-based abstractions
Threading Model โœ… Coroutine-based โš ๏ธ Spring threading
Control โœ… Explicit per-topic DSL โš ๏ธ Annotation-based
Framework Coupling โœ… None required โŒ Requires Spring
Extensions โœ… Opt-in middleware โš ๏ธ Framework-tied

Choose Quafka when you want a coroutine-first, lean, and highly controllable Kafka client with strong defaults and optional high-level extensions.

Getting Started

Installation

Add the following dependency to your build.gradle.kts:

dependencies {
    implementation("com.trendyol:quafka:0.2.0")
}

For extensions (retry, pipelines, etc.):

dependencies {
    implementation("com.trendyol:quafka-extensions:0.2.0")
}

Try the Interactive Demo ๐ŸŽฎ

The fastest way to explore Quafka is through our interactive console application:

cd examples/console
export Q_SERVERS="localhost:9092"
./gradlew run

The console app provides a menu-driven interface to try all producer and consumer patterns. Perfect for learning and testing!

See the Console Demo README for details.

Quick Start

Simple Consumer

import com.trendyol.quafka.consumer.configuration.*
import org.apache.kafka.common.serialization.StringDeserializer

val props = mapOf(
    "bootstrap.servers" to "localhost:9092",
    "group.id" to "example-group"
)

val consumer = QuafkaConsumerBuilder<String, String>(props)
    .withDeserializer(StringDeserializer(), StringDeserializer())
    .subscribe("example-topic") {
        withSingleMessageHandler { message, context ->
            println("Received: ${message.value}")
            message.ack()
        }
    }
    .build()

consumer.start()

Simple Producer

import com.trendyol.quafka.producer.*
import com.trendyol.quafka.producer.configuration.QuafkaProducerBuilder
import org.apache.kafka.common.serialization.StringSerializer

val props = mapOf("bootstrap.servers" to "localhost:9092")

val producer = QuafkaProducerBuilder<String?, String?>(props)
    .withSerializer(StringSerializer(), StringSerializer())
    .build()

val result = producer.send(
    OutgoingMessage.create(
        topic = "test-topic",
        key = "key",
        value = "Hello, Quafka!"
    )
)

Examples

๐Ÿ“– Consumer Examples

Single Message Processing

Batch Message Processing

๐Ÿ“ค Producer Examples

โš™๏ธ Advanced Features

Backpressure Control

import kotlin.time.Duration.Companion.minutes

val consumer = QuafkaConsumerBuilder<String, String>(props)
    .withDeserializer(StringDeserializer(), StringDeserializer())
    .subscribe("example-topic") {
        withSingleMessageHandler { msg, ctx ->
            // Slow processing work
            processMessage(msg)
            msg.ack()
        }.withBackpressure(
            backpressureBufferSize = 10_000,
            backpressureReleaseTimeout = 1.minutes
        )
    }
    .build()

Batch Publishing

val messages = (1..100).map { index ->
    OutgoingMessage.create(
        topic = "test-topic",
        key = "key-$index",
        value = "value-$index"
    )
}

val results: Collection<DeliveryResult> = producer.sendAll(messages)

Quafka Extensions

Quafka-Extensions is a companion module that provides advanced, high-level features:

๐Ÿ”„ Serialization / Deserialization

  • Built-in support for JSON and common formats
  • Extensible design for custom serialization strategies
  • Type-safe serialization leveraging Kotlin's type system

โฐ Message Delayer

  • Schedule message processing with fine-grained delay control
  • Fixed and dynamic delay strategies
  • Perfect for delayed retries and scheduled workflows

๐Ÿ” Advanced Retry Mechanism

  • In-Memory Retry: Lightweight retry for transient failures
  • Multi-Topic Retry: Forward to dedicated retry topics with configurable backoff
  • Flexible Policies: Exponential backoff, max attempts, custom retry logic

๐Ÿ”— Messaging Pipeline

Middleware-style architecture for composable message processing:

import com.trendyol.quafka.extensions.consumer.single.pipelines.PipelineMessageHandler.Companion.usePipelineMessageHandler

val consumer = QuafkaConsumerBuilder<String, String>(props)
    .withDeserializer(StringDeserializer(), StringDeserializer())
    .subscribe("example-topic") {
        usePipelineMessageHandler {
            // Logging middleware
            use { envelope, next ->
                logger.info("Processing: ${envelope.message.offset}")
                next()
            }
            
            // Validation middleware
            use { envelope, next ->
                if (isValid(envelope.message.value)) {
                    next()
                } else {
                    logger.warn("Invalid message")
                }
            }
            
            // Business logic
            use { envelope, next ->
                processMessage(envelope.message.value)
                envelope.message.ack()
                next()
            }
        }
    }
    .build()

Available Pipeline Steps:

  • TracingPipelineStep: Distributed tracing integration
  • LoggingPipelineStep: Detailed logging for each stage
  • ErrorHandlerPipelineStep: Centralized error management
  • DeserializationPipelineStep: Type-safe deserialization
  • Custom Middleware: Create your own reusable steps

Documentation

๐Ÿ“š Core Documentation

๐Ÿ“– Example Guides

๐Ÿ”ง Extensions Documentation

๐ŸŽฎ Interactive Demo

  • Console Demo Application - Interactive CLI for testing all Quafka patterns
    • Producer examples (Basic, Batch, JSON, Headers)
    • Single consumer examples (Basic, Backpressure, Pipeline, Retry)
    • Batch consumer examples (8 different patterns)
    • Easy-to-use menu-driven interface

Status

Warning

While Quafka is production-ready and extensively used at Trendyol, the API is not yet fully stabilized. Breaking changes may occur in minor releases, but migration guides will always be provided.

Note

Report any issue or bug in the GitHub repository.

Contributing

Contributions are welcome! We appreciate:

  • ๐Ÿ› Bug reports - Help us identify and fix issues
  • ๐Ÿ’ก Feature requests - Share your ideas for improvements
  • ๐Ÿ“– Documentation improvements - Help make our docs better
  • ๐Ÿš€ Code contributions - Submit pull requests

Please read our Contributing Guidelines before submitting a pull request.

License

Quafka is licensed under the Apache License 2.0. See the LICENSE file for details.


Made with โค๏ธ by Trendyol

About

Quafka is a non-blocking Kafka client library built on top of the Apache Kafka Java client, designed for Kotlin with first-class coroutine support.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors 2

  •  
  •