Kincir
Kincir is a Rust library that provides a unified interface for message streaming with support for multiple message broker backends. It offers a simple, consistent API for publishing and subscribing to messages across different messaging systems, with advanced routing capabilities.
📚 Online Documentation | 🦀 Crates.io | 💻 GitHub Repository
Features
- Unified messaging interface with support for multiple backends (Kafka, RabbitMQ)
- Message routing with customizable handlers
- Built-in logging support (optional via feature flag)
- Message UUID generation for tracking and identification
- Customizable message metadata support
- Async/await support
- Type-safe error handling
Installation
Add kincir to your Cargo.toml:
[]
= "0.1.6"
Feature Flags
Kincir provides feature flags to customize the library:
[]
# Default features (includes logging)
= "0.1.6"
# Without logging
= { = "0.1.6", = false }
# Explicitly enable logging
= { = "0.1.6", = ["logging"] }
# With Protocol Buffers support
= { = "0.1.6", = ["protobuf"] }
# With both logging and Protocol Buffers
= { = "0.1.6", = ["logging", "protobuf"] }
Build and Development
Using Make
The project includes a Makefile to simplify common development tasks:
# Build the project
# Run tests
# Format code and run linters
# Generate documentation
# Run benchmarks
# Show all available commands
Using Docker
The project includes Docker support for development and testing:
# Start the Docker environment
# Run the Kafka example
# Run the RabbitMQ example
# Show all available commands
For more details on Docker usage, see README.docker.md.
Usage
Basic Message Creation
use Message;
// Create a new message with payload
let payload = b"Hello, World!".to_vec;
let message = new;
// Add metadata to the message
let message = message.with_metadata;
Setting Up a Message Router
The Router is a central component that handles message flow between publishers and subscribers.
With Logging (Default)
use ;
use ;
use Router;
use Message;
use Arc;
async
Without Logging
When the logging feature is disabled, the Router is used without a logger:
use ;
use Router;
use Message;
use Arc;
async
Publishing Messages
use Publisher;
// Create messages to publish
let messages = vec!;
// Publish messages to a topic
async
Subscribing to Messages
use Subscriber;
// Subscribe and receive messages
async
Backend Implementations
Kafka
Kincir provides Kafka support through the kafka module:
use ;
use mpsc;
// Set up channels
let = channel;
// Configure Kafka publisher and subscriber (default with logging)
let publisher = new;
let subscriber = new;
// Without logging feature, the logger parameter is not needed
RabbitMQ
RabbitMQ support is available through the rabbitmq module:
use ;
// Configure RabbitMQ components
let publisher = new.await?;
let subscriber = new.await?;
// With logging feature, you can optionally add a logger
// publisher = publisher.with_logger(logger.clone());
// subscriber = subscriber.with_logger(logger);
Message Structure
Each message in Kincir consists of:
uuid: A unique identifier for the messagepayload: The actual message content as a byte vectormetadata: A hash map of string key-value pairs for additional message information
Message Encoding and Decoding
Protocol Buffers Support
When the protobuf feature is enabled, Kincir provides Protocol Buffers encoding/decoding capabilities:
use Message;
use ;
// Create a protobuf codec
let codec = new;
// Create a message
let message = new
.with_metadata;
// Encode the message to send over the wire
let encoded = codec.encode.unwrap;
// Later, decode the message
let decoded = codec.decode.unwrap;
Message Handler
Message handlers are async functions that process incoming messages and can produce zero or more output messages:
use Message;
// Define a message handler
let handler = ;
Protocol Buffers Support
When the protobuf feature flag is enabled, Kincir provides support for encoding and decoding messages using Protocol Buffers through the MessageCodec trait:
use ;
// Create a message
let message = new
.with_metadata;
// Create a Protocol Buffers codec
let codec = new;
// Encode the message to Protocol Buffers binary format
let encoded = codec.encode.unwrap;
// Decode the binary data back to a Message
let decoded = codec.decode.unwrap;
assert_eq!;
assert_eq!;
assert_eq!;
This is particularly useful when you need:
- Smaller message size compared to JSON
- Stricter schema validation
- Better performance for serialization and deserialization
- Language-agnostic message exchange
Roadmap to v1.0 🚀
Kincir is evolving towards feature parity with Watermill (Golang) while leveraging Rust's performance and safety. Below is our roadmap:
✅ v0.2 – Core Enhancements
- In-memory message broker for local testing
- Unified Ack/Nack handling across backends
- Correlation ID tracking for tracing
- Performance profiling and initial benchmarks
- Unit & integration tests for stability
🔄 v0.3 – Middleware & Backend Expansion
- Middleware framework: logging, retry, recovery, correlation
- Additional broker support (e.g., NATS, AWS SQS)
- Optimized async pipeline for lower latency
- Integration tests for middleware + new backends
📊 v0.4 – Distributed Tracing & Monitoring
- OpenTelemetry-based tracing for message flows
- Prometheus metrics for message processing
- Poison queue (dead-letter handling)
- Throttling & backpressure support
- Stress testing and performance benchmarking
🛠 v0.5 – Hardening & API Freeze
- API finalization for stability
- Cross-platform testing (Linux, macOS, Windows)
- Memory optimization and async efficiency improvements