Skip to content

huhlig/bdrpc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

37 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Bi-Directional Remote Procedure Call (BDRPC)

License Rust Status Build Documentation

BDRPC is a Rust library for implementing bi-directional remote procedure calls (RPC) over TCP/IP connections. It provides a simple and efficient way to communicate between different processes or machines, enabling remote procedure calls and data exchange. It is designed to be straightforward to use, flexible, and highly performant, making it suitable for a wide range of applications, from simple client-server interactions to complex distributed systems. It supports various protocols and data formats, allowing seamless integration with existing systems and frameworks.

Features

Core Features

  • Bi-directional RPC: Both sides can call and respond
  • Type-safe Communication: Compile-time guarantees with #[bdrpc::service] macro
  • Multiple Serialization Formats: JSON, Postcard, rkyv support
  • High Performance: 4.02M messages/second throughput
  • Flexible Transports: TCP, TLS, Memory, with compression support

v0.2.0 Transport Management (In Development)

  • Multiple Transports: Run servers on multiple ports/protocols simultaneously
  • Named Connections: Reference transports by name for clarity and failover
  • Automatic Reconnection: Built-in reconnection with configurable strategies (exponential backoff, circuit breakers)
  • Transport Failover: Switch between transports automatically for high availability
  • Dynamic Management: Add/remove transports at runtime
  • Event-Driven: React to connection lifecycle events via TransportEventHandler
  • EndpointBuilder: Ergonomic API for configuring endpoints with transports

Additional Features

  • Built-in error handling and exception propagation
  • Comprehensive observability (metrics, tracing, health checks)
  • Backpressure and flow control
  • Dynamic channel creation and multiplexing
  • Protocol versioning and negotiation

Why BDRPC and not Other Libraries (gRPC, Cap'n'Proto, tarpc)?

BDRPC stands out from other RPC libraries due to its focus on bi-directional communication, robust error handling, and extensibility. While other libraries may offer similar features, BDRPC provides a more comprehensive solution that addresses the needs of modern peer to peer distributed systems. Its support for custom transports and serialization formats allows for seamless integration with existing systems, making it a versatile choice for a wide range of

Channel Types: In-Memory vs Network

BDRPC provides two types of channels for different use cases:

In-Memory Channels

Created with Channel::new_in_memory(), these channels:

  • โœ… Work within a single process only
  • โœ… Perfect for testing and examples
  • โœ… No network overhead
  • โŒ Cannot communicate across network boundaries

Use for:

  • Unit tests
  • In-process communication
  • Learning the channel API
  • Prototyping

Example:

use bdrpc::channel::{Channel, ChannelId, Protocol};

#[derive(Debug, Clone)]
enum MyProtocol { Ping }
impl Protocol for MyProtocol {
    fn method_name(&self) -> &'static str { "ping" }
    fn is_request(&self) -> bool { true }
}

let (sender, receiver) = Channel::<MyProtocol>::new_in_memory(ChannelId::new(), 100);

Network Channels

Created via the Endpoint API, these channels:

  • โœ… Work across network boundaries
  • โœ… Automatically wired to transports (TCP, etc.)
  • โœ… Support protocol negotiation
  • โœ… Handle serialization/deserialization

Use for:

  • Production applications
  • Client-server communication
  • Distributed systems
  • Real network RPC

Example (using #[bdrpc::service] macro - recommended):

// See examples/calculator_service.rs for a complete working example
use bdrpc::service;
use bdrpc::endpoint::{Endpoint, EndpointConfig};
use bdrpc::serialization::JsonSerializer;

// Define your service with the macro
#[service(direction = "bidirectional")]
trait Calculator {
    async fn add(&self, a: i32, b: i32) -> Result<i32, String>;
    async fn subtract(&self, a: i32, b: i32) -> Result<i32, String>;
}

// Implement the generated server trait
struct MyCalculator;

impl CalculatorServer for MyCalculator {
    async fn add(&self, a: i32, b: i32) -> Result<i32, String> {
        Ok(a + b)
    }
    
    async fn subtract(&self, a: i32, b: i32) -> Result<i32, String> {
        Ok(a - b)
    }
}

async fn example() -> Result<(), Box<dyn std::error::Error>> {
    // Server side
    let mut server_endpoint = Endpoint::new(JsonSerializer::default(), EndpointConfig::default());
    server_endpoint.register_bidirectional("Calculator", 1).await?;
    server_endpoint.listen("127.0.0.1:8080").await?;

    // Client side
    let mut client_endpoint = Endpoint::new(JsonSerializer::default(), EndpointConfig::default());
    client_endpoint.register_bidirectional("Calculator", 1).await?;
    let connection = client_endpoint.connect("127.0.0.1:8080").await?;

    // Get typed channels for the protocol
    let (sender, receiver) = client_endpoint.get_channels::<CalculatorProtocol>(
        connection.id(),
        "Calculator"
    ).await?;

    // Create client and make RPC calls
    let client = CalculatorClient::new(sender, receiver);
    let result = client.add(5, 3).await??;
    println!("5 + 3 = {}", result);
    Ok(())
}

Manual example (without macro):

// See examples/calculator_manual.rs for a complete working example
use bdrpc::endpoint::{Endpoint, EndpointConfig};
use bdrpc::serialization::JsonSerializer;
use bdrpc::channel::{ChannelId, Protocol};

// Define protocol enum manually
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
enum CalculatorProtocol {
    AddRequest { a: i32, b: i32 },
    AddResponse { result: i32 },
    SubtractRequest { a: i32, b: i32 },
    SubtractResponse { result: i32 },
}

impl Protocol for CalculatorProtocol {
    fn method_name(&self) -> &'static str {
        match self {
            Self::AddRequest { .. } => "add",
            Self::AddResponse { .. } => "add",
            Self::SubtractRequest { .. } => "subtract",
            Self::SubtractResponse { .. } => "subtract",
        }
    }
    
    fn is_request(&self) -> bool {
        matches!(self, Self::AddRequest { .. } | Self::SubtractRequest { .. })
    }
}

async fn example() -> Result<(), Box<dyn std::error::Error>> {
    // Server side
    let mut server_endpoint = Endpoint::new(JsonSerializer::default(), EndpointConfig::default());
    server_endpoint.register_bidirectional("Calculator", 1).await?;
    server_endpoint.listen("127.0.0.1:8080").await?;

    // Client side
    let mut client_endpoint = Endpoint::new(JsonSerializer::default(), EndpointConfig::default());
    client_endpoint.register_bidirectional("Calculator", 1).await?;
    let connection = client_endpoint.connect("127.0.0.1:8080").await?;

    // Get typed channels for the protocol
    let (sender, mut receiver) = client_endpoint.get_channels::<CalculatorProtocol>(
        connection.id(),
        "Calculator"
    ).await?;

    // Make request manually
    sender.send(CalculatorProtocol::AddRequest { a: 5, b: 3 }).await?;

    // Wait for response
    if let Some(CalculatorProtocol::AddResponse { result }) = receiver.recv().await {
        println!("5 + 3 = {}", result);
    }
    Ok(())
}

Example Guide

BDRPC provides examples in two forms to demonstrate different approaches:

๐ŸŽฏ Getting Started Examples

Example Description Key Concepts
hello_world_service.rs Simplest RPC using #[bdrpc::service] macro Service traits, generated client/server, type-safe RPC
hello_world_manual.rs Same functionality with manual protocol Protocol enum, manual routing, full control
channel_basics.rs In-memory channel fundamentals Channel creation, send/recv, FIFO ordering

๐Ÿงฎ RPC Pattern Examples

Example Service Macro Version Manual Protocol Version
Calculator calculator_service.rs - Type-safe math operations with generated client/dispatcher calculator_manual.rs - Manual protocol enum with match-based routing
Chat Server chat_server_service.rs - Multi-client chat with generated service API chat_server_manual.rs - Manual message broadcasting and client management
File Transfer file_transfer_service.rs - Streaming large files with progress tracking file_transfer_manual.rs - Manual chunked transfer with CRC32 verification

๐ŸŒ Advanced Patterns

Example Description Key Features
dynamic_channels_service.rs โญ Multiplexing gateway with service macro System protocol, dynamic channel creation, type-safe multi-service gateway
dynamic_channels_manual.rs Same gateway pattern with manual protocols Full control over channel lifecycle, custom routing logic
network_chat.rs โญ Real network communication pattern Endpoint API, TCP transport, protocol negotiation
mtls_demo.rs ๐Ÿ” Mutual TLS configuration guide mTLS setup, client certificates, CA trust stores, reconnection strategies
advanced_channels.rs Channel management techniques Channel lifecycle, error handling, cleanup
service_macro_demo.rs Detailed macro explanation Code generation, dispatcher internals, best practices

๐Ÿš€ Transport Management (v0.2.0+)

Example Description Key Features
multi_transport_server.rs โญ Server with multiple listeners Multiple TCP listeners, automatic connection acceptance, EndpointBuilder
auto_reconnect_client.rs โญ Client with automatic reconnection Named transports, exponential backoff, connection resilience
transport_failover.rs โญ Client with transport failover Multiple transports, automatic failover, high availability patterns
endpoint_builder.rs EndpointBuilder API demonstration Transport configuration, reconnection strategies, preset configurations

Choosing Your Approach

Use Service Macro (#[bdrpc::service]) when:

  • โœ… Building standard RPC services
  • โœ… Want type-safe client APIs
  • โœ… Prefer less boilerplate code
  • โœ… Need automatic request routing
  • โœ… Value compile-time checking

Use Manual Protocol when:

  • โœ… Need custom message structures
  • โœ… Require non-standard communication patterns
  • โœ… Want maximum control over protocol details
  • โœ… Integrating with existing protocol definitions
  • โœ… Building specialized streaming patterns

๐Ÿš€ Running Examples

# Service macro examples (recommended for most use cases)
cargo run --example hello_world_service --features serde
cargo run --example calculator_service --features serde
cargo run --example chat_server_service --features serde
cargo run --example file_transfer_service --features serde
cargo run --example dynamic_channels_service --features serde

# Manual protocol examples (for learning or custom patterns)
cargo run --example hello_world_manual --features serde
cargo run --example calculator_manual --features serde
cargo run --example chat_server_manual --features serde
cargo run --example file_transfer_manual --features serde
cargo run --example dynamic_channels_manual --features serde

# Network communication (production pattern)
cargo run --example network_chat --features serde

# Security and TLS examples
cargo run --example mtls_demo --features tls,serde

# Transport management examples (v0.2.0+)
cargo run --example multi_transport_server --features serde
cargo run --example auto_reconnect_client --features serde
cargo run --example transport_failover --features serde
cargo run --example endpoint_builder --features serde

๐Ÿ’ก Example Comparison

Each paired example (service vs manual) demonstrates the same functionality using different approaches:

Aspect Service Macro Manual Protocol
Code Volume ~200 lines ~400 lines
Type Safety Compile-time checked Runtime matching
Boilerplate Minimal (generated) More (explicit)
Flexibility Structured patterns Maximum control
Learning Curve Easier to start Shows internals
Best For Production services Custom protocols

For production use, always use the Endpoint API as shown in network_chat.rs for proper network communication.

Project Structure

bdrpc/
+-- bdrpc/                      # Main library crate
    +-- src/
        +-- backpressure/      # Flow control and backpressure management
        +-- channel/           # Channel abstraction and management
        +-- endpoint/          # Connection and protocol negotiation
        +-- observability/     # Metrics, health checks, and correlation
        +-- reconnection/      # Reconnection strategies and circuit breakers
        +-- serialization/     # Serialization formats (JSON, Postcard, rkyv)
        +-- transport/         # Transport layer (TCP, TLS, Memory, Compression)
    +-- examples/              # Comprehensive examples
    +-- benches/               # Performance benchmarks
    +-- tests/                 # Integration tests
+-- bdrpc-macros/              # Procedural macros for code generation
+-- docs/                      # Documentation
    +-- adr/                   # Architecture Decision Records

Documentation

Project Status

Current Version: v0.2.0 (In Development - 68.75% Complete)

BDRPC v0.1.0 has been released! v0.2.0 is currently in development with enhanced transport management features. See the transport manager enhancement plan for detailed progress.

v0.1.0 Features (Released):

  • โœ… Core channel and transport abstractions
  • โœ… Multiple serialization formats (JSON, Postcard, rkyv)
  • โœ… TCP and TLS transports
  • โœ… Compression support (Gzip, Zstd, LZ4)
  • โœ… Reconnection strategies and circuit breakers
  • โœ… Backpressure and flow control
  • โœ… Endpoint API with protocol negotiation
  • โœ… System protocol for dynamic channel creation
  • โœ… Comprehensive examples and documentation
  • โœ… Observability (metrics, tracing, health checks)
  • โœ… Performance optimization (4.02M msg/s throughput)
  • โœ… 462 tests passing with high code coverage

v0.2.0 Features (In Development - 68.75% Complete):

  • โœ… Enhanced TransportManager with multiple transport support
  • โœ… Named transport connections for failover
  • โœ… Automatic reconnection per transport
  • โœ… Transport lifecycle event callbacks
  • โœ… EndpointBuilder with transport configuration
  • โœ… Dynamic transport management (add/remove at runtime)
  • โณ Comprehensive documentation updates (87.5% complete)
  • โณ Testing and hardening (pending)
  • โณ Migration tools and final polish (pending)

Planned for Future Releases:

  • ๐Ÿ”œ WebSocket transport
  • ๐Ÿ”œ QUIC transport
  • ๐Ÿ”œ Enhanced fuzz and stress testing
  • ๐Ÿ”œ Service mesh integration

About

BDRPC is a Rust library for implementing bi-directional remote procedure calls (RPC) over TCP/IP connections.

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages