Skip to content

Conversation

@countradooku
Copy link
Collaborator

Introduces a binary protocol for inter-node communication using bincode and xxhash for efficient serialization and fast routing. Updates NATS, Redis, and Redis Cluster transports to use the new binary protocol instead of JSON for broadcast, request, and response messages. Adds comprehensive tests for binary protocol conversions and message parsing. Updates dependencies to include bincode and xxhash-rust.

Description

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Performance improvement
  • Code refactoring

Testing

  • Unit tests pass
  • Integration tests pass
  • Manual testing completed

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

Build Artifacts

Additional Notes

Introduces a binary protocol for inter-node communication using bincode and xxhash for efficient serialization and fast routing. Updates NATS, Redis, and Redis Cluster transports to use the new binary protocol instead of JSON for broadcast, request, and response messages. Adds comprehensive tests for binary protocol conversions and message parsing. Updates dependencies to include bincode and xxhash-rust.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @countradooku, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a fundamental change to how nodes communicate within the system by implementing a new binary protocol. This strategic move from JSON to "bincode" serialization, coupled with "xxhash" for optimized routing, is designed to enhance the efficiency and speed of inter-node messaging. The change is applied across key adapter transports (NATS, Redis, Redis Cluster) to ensure a consistent and performant communication layer, ultimately leading to a more scalable and responsive distributed architecture.

Highlights

  • Binary Protocol Introduction: A new binary protocol has been implemented for efficient inter-node communication, leveraging "bincode" for serialization and "xxhash" for fast channel routing.
  • Transport Migration: NATS, Redis, and Redis Cluster transports have been updated to utilize the new binary protocol for broadcast, request, and response messages, replacing the previous JSON-based serialization.
  • Performance Enhancements: The shift to a binary protocol aims to significantly reduce message sizes and improve routing efficiency, contributing to overall performance gains in horizontal scaling.
  • Extensive Testing: Comprehensive unit tests have been added to validate the correctness and integrity of the binary protocol conversions and message parsing.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a binary protocol for inter-node communication using bincode and xxhash, which is a great performance enhancement over the previous JSON-based protocol. The implementation is well-structured, with a dedicated binary_protocol module and updates to the NATS and Redis transports. The addition of comprehensive tests is also commendable.

My review focuses on improving error handling and making the code more robust. I've identified a few places where errors are silently ignored, which could make debugging difficult. Specifically, I've suggested changes to propagate errors during message conversion and to add logging in the transport listeners when deserialization or conversion fails. I've also pointed out a couple of tests that could be improved by adding assertions to make them fully automated.

Comment on lines +152 to +171
impl From<BroadcastMessage> for BinaryBroadcastMessage {
fn from(msg: BroadcastMessage) -> Self {
let node_id_bytes = uuid_to_bytes(&msg.node_id).unwrap_or([0u8; 16]);
let channel_hash = calculate_channel_hash(&msg.channel);

// The message field contains the JSON string that should be sent to clients
let raw_client_json = msg.message.into_bytes();

Self {
version: BINARY_PROTOCOL_VERSION,
channel_hash,
channel: msg.channel,
node_id_bytes,
app_id: msg.app_id,
raw_client_json,
except_socket_id: msg.except_socket_id,
timestamp_ms: msg.timestamp_ms,
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The From implementation for BinaryBroadcastMessage uses .unwrap_or([0u8; 16]) when converting the node_id. This will silently replace an invalid UUID with a zeroed-out one, which could lead to hard-to-debug issues like message loss or mis-routing. For consistency with other fallible conversions in this module (like for RequestBody), this should be converted to an impl TryFrom, propagating any parsing errors. This change will require updating the call sites to use try_into()?.

impl TryFrom<BroadcastMessage> for BinaryBroadcastMessage {
    type Error = Error;

    fn try_from(msg: BroadcastMessage) -> Result<Self> {
        let node_id_bytes = uuid_to_bytes(&msg.node_id)?;
        let channel_hash = calculate_channel_hash(&msg.channel);

        // The message field contains the JSON string that should be sent to clients
        let raw_client_json = msg.message.into_bytes();

        Ok(Self {
            version: BINARY_PROTOCOL_VERSION,
            channel_hash,
            channel: msg.channel,
            node_id_bytes,
            app_id: msg.app_id,
            raw_client_json,
            except_socket_id: msg.except_socket_id,
            timestamp_ms: msg.timestamp_ms,
        })
    }
}

Comment on lines 191 to 209
if let Ok(binary_req) = bincode::deserialize::<BinaryRequestBody>(&msg.payload) {
if let Ok(request) = RequestBody::try_from(binary_req) {
let response_result = request_handler(request).await;

if let Ok(response) = response_result {
// Serialize response to binary
if let Ok(binary_resp) = BinaryResponseBody::try_from(response) {
if let Ok(response_data) = bincode::serialize(&binary_resp) {
let _ = response_client
.publish(
Subject::from(response_subject.clone()),
response_data.into(),
)
.await;
}
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The request handling logic contains deeply nested if let statements. This pattern makes the code hard to read and, more importantly, it silently swallows errors. If any of the try_from or serialize calls fail, the message is simply dropped without any logging, which can make debugging very difficult. The error handling should be explicit, and failures should be logged to aid in debugging.

                let binary_req = match bincode::deserialize::<BinaryRequestBody>(&msg.payload) {
                    Ok(req) => req,
                    Err(e) => {
                        warn!("Failed to deserialize binary request: {}", e);
                        continue;
                    }
                };

                let request = match RequestBody::try_from(binary_req) {
                    Ok(req) => req,
                    Err(e) => {
                        warn!("Failed to convert binary request to request body: {}", e);
                        continue;
                    }
                };

                if let Ok(response) = request_handler(request).await {
                    let binary_resp = match BinaryResponseBody::try_from(response) {
                        Ok(resp) => resp,
                        Err(e) => {
                            warn!("Failed to convert response to binary format: {}", e);
                            continue;
                        }
                    };

                    let response_data = match bincode::serialize(&binary_resp) {
                        Ok(data) => data,
                        Err(e) => {
                            warn!("Failed to serialize binary response: {}", e);
                            continue;
                        }
                    };

                    let _ = response_client
                        .publish(
                            Subject::from(response_subject.clone()),
                            response_data.into(),
                        )
                        .await;
                }

Comment on lines 233 to 260
if let Ok(binary_req) =
bincode::deserialize::<BinaryRequestBody>(&payload_bytes)
{
if let Ok(request) = RequestBody::try_from(binary_req) {
let response_result = request_handler(request).await;

if let Ok(response) = response_result {
// Serialize response to binary
if let Ok(binary_resp) = BinaryResponseBody::try_from(response)
{
if let Ok(response_bytes) = bincode::serialize(&binary_resp)
{
// Use client's connection pooling for response publishing
if let Ok(mut conn) =
client_clone.get_async_connection().await
{
let _ = conn
.publish::<_, _, ()>(
&response_channel_clone,
response_bytes,
)
.await;
}
}
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The request handling logic contains deeply nested if let statements. This pattern makes the code hard to read and, more importantly, it silently swallows errors. If any of the try_from or serialize calls fail, the message is simply dropped without any logging, which can make debugging very difficult. The error handling should be explicit, and failures should be logged.

                        let binary_req = match bincode::deserialize::<BinaryRequestBody>(&payload_bytes) {
                            Ok(req) => req,
                            Err(e) => {
                                warn!("Failed to deserialize binary request: {}", e);
                                return;
                            }
                        };

                        let request = match RequestBody::try_from(binary_req) {
                            Ok(req) => req,
                            Err(e) => {
                                warn!("Failed to convert binary request to request body: {}", e);
                                return;
                            }
                        };

                        if let Ok(response) = request_handler(request).await {
                            let binary_resp = match BinaryResponseBody::try_from(response) {
                                Ok(resp) => resp,
                                Err(e) => {
                                    warn!("Failed to convert response to binary format: {}", e);
                                    return;
                                }
                            };

                            let response_bytes = match bincode::serialize(&binary_resp) {
                                Ok(data) => data,
                                Err(e) => {
                                    warn!("Failed to serialize binary response: {}", e);
                                    return;
                                }
                            };

                            if let Ok(mut conn) = client_clone.get_async_connection().await {
                                let _ = conn
                                    .publish::<_, _, ()>(
                                        &response_channel_clone,
                                        response_bytes,
                                    )
                                    .await;
                            } else {
                                warn!("Failed to get redis connection to publish response");
                            }
                        }

Comment on lines 259 to 284
if let Ok(binary_req) =
bincode::deserialize::<BinaryRequestBody>(payload.as_bytes())
{
if let Ok(request) = RequestBody::try_from(binary_req) {
let response_result = request_handler(request).await;

if let Ok(response) = response_result {
// Serialize response to binary
if let Ok(binary_resp) =
BinaryResponseBody::try_from(response)
{
if let Ok(response_bytes) =
bincode::serialize(&binary_resp)
{
let mut conn = pub_connection_clone.clone();
let _ = conn
.publish::<_, _, ()>(
&response_channel_clone,
response_bytes,
)
.await;
}
}
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The request handling logic contains deeply nested if let statements. This pattern makes the code hard to read and, more importantly, it silently swallows errors. If any of the try_from or serialize calls fail, the message is simply dropped without any logging, which can make debugging very difficult. The error handling should be explicit, and failures should be logged.

                                let binary_req =
                                    match bincode::deserialize::<BinaryRequestBody>(payload.as_bytes()) {
                                        Ok(req) => req,
                                        Err(e) => {
                                            warn!("Failed to deserialize binary request: {}", e);
                                            return;
                                        }
                                    };

                                let request = match RequestBody::try_from(binary_req) {
                                    Ok(req) => req,
                                    Err(e) => {
                                        warn!("Failed to convert binary request to request body: {}", e);
                                        return;
                                    }
                                };

                                if let Ok(response) = request_handler(request).await {
                                    let binary_resp = match BinaryResponseBody::try_from(response) {
                                        Ok(resp) => resp,
                                        Err(e) => {
                                            warn!("Failed to convert response to binary format: {}", e);
                                            return;
                                        }
                                    };

                                    let response_bytes = match bincode::serialize(&binary_resp) {
                                        Ok(data) => data,
                                        Err(e) => {
                                            warn!("Failed to serialize binary response: {}", e);
                                            return;
                                        }
                                    };

                                    let mut conn = pub_connection_clone.clone();
                                    let _ = conn
                                        .publish::<_, _, ()>(
                                            &response_channel_clone,
                                            response_bytes,
                                        )
                                        .await;
                                }

let binary_size = bincode::serialize(&binary).unwrap().len();

// Binary should be smaller or similar in size
println!("JSON size: {}, Binary size: {}", json_size, binary_size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test test_bincode_serialization_size currently only prints the JSON and binary sizes to the console. This makes it a manual check rather than an automated test. To make this a useful regression test, an assertion should be added to ensure the binary format remains efficient. For this test case, the binary size should be smaller than the JSON size.

        println!("JSON size: {}, Binary size: {}", json_size, binary_size);
        assert!(binary_size < json_size);

Comment on lines 217 to 223
if let Ok(binary_resp) = bincode::deserialize::<BinaryResponseBody>(&msg.payload) {
if let Ok(response) = ResponseBody::try_from(binary_resp) {
response_handler(response).await;
}
} else {
warn!("Failed to parse binary response message");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If bincode::deserialize succeeds but ResponseBody::try_from fails, the error is silently ignored. This can happen during rolling updates if there's a version mismatch or other data format issues. It's important to log this failure to aid in debugging.

                if let Ok(binary_resp) = bincode::deserialize::<BinaryResponseBody>(&msg.payload) {
                    if let Ok(response) = ResponseBody::try_from(binary_resp) {
                        response_handler(response).await;
                    } else {
                        warn!("Failed to convert binary response to response body");
                    }
                } else {
                    warn!("Failed to parse binary response message");
                }

Comment on lines 263 to 271
if let Ok(binary_resp) =
bincode::deserialize::<BinaryResponseBody>(&payload_bytes)
{
if let Ok(response) = ResponseBody::try_from(binary_resp) {
response_handler(response).await;
}
} else {
warn!("Failed to parse binary response message");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If bincode::deserialize succeeds but ResponseBody::try_from fails, the error is silently ignored. This can happen during rolling updates if there's a version mismatch. It's important to log this failure to aid in debugging.

                        if let Ok(binary_resp) =
                            bincode::deserialize::<BinaryResponseBody>(&payload_bytes)
                        {
                            if let Ok(response) = ResponseBody::try_from(binary_resp) {
                                response_handler(response).await;
                            } else {
                                warn!("Failed to convert binary response to response body");
                            }
                        } else {
                            warn!("Failed to parse binary response message");
                        }

Comment on lines 287 to 295
if let Ok(binary_resp) =
bincode::deserialize::<BinaryResponseBody>(payload.as_bytes())
{
response_handler(response).await;
if let Ok(response) = ResponseBody::try_from(binary_resp) {
response_handler(response).await;
}
} else {
warn!("Failed to parse response message: {}", payload);
warn!("Failed to parse binary response message");
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If bincode::deserialize succeeds but ResponseBody::try_from fails, the error is silently ignored. This can happen during rolling updates if there's a version mismatch. It's important to log this failure to aid in debugging. Additionally, the warning for a failed deserialization no longer includes the error details, which is a regression from the previous implementation.

                                match bincode::deserialize::<BinaryResponseBody>(payload.as_bytes()) {
                                    Ok(binary_resp) => {
                                        if let Ok(response) = ResponseBody::try_from(binary_resp) {
                                            response_handler(response).await;
                                        } else {
                                            warn!("Failed to convert binary response to response body");
                                        }
                                    }
                                    Err(e) => {
                                        warn!("Failed to parse binary response message: {}", e);
                                    }
                                }

Comment on lines +147 to +152
println!("JSON size: {} bytes", json_bytes.len());
println!("Binary size: {} bytes", binary_bytes.len());

// Binary should be competitive or better
// Note: For very small messages, overhead might make binary slightly larger,
// but for typical messages with longer payloads, binary will be smaller
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The test test_bincode_size_reduction currently only prints the JSON and binary sizes to the console. This makes it a manual check rather than an automated test. To make this a useful regression test, an assertion should be added to ensure the binary format remains efficient.

Suggested change
println!("JSON size: {} bytes", json_bytes.len());
println!("Binary size: {} bytes", binary_bytes.len());
// Binary should be competitive or better
// Note: For very small messages, overhead might make binary slightly larger,
// but for typical messages with longer payloads, binary will be smaller
println!("JSON size: {} bytes", json_bytes.len());
println!("Binary size: {} bytes", binary_bytes.len());
// Binary should be competitive or better. For this payload, it should be smaller.
assert!(binary_bytes.len() < json_bytes.len());

@countradooku
Copy link
Collaborator Author

/gemini review

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a binary protocol for inter-node communication, replacing JSON with bincode for serialization and xxhash for routing. This is a significant performance improvement. The changes are well-contained within a new binary_protocol.rs module and are consistently applied across the NATS, Redis, and Redis Cluster transports. The addition of comprehensive tests is also great.

My review focuses on a few key areas to enhance robustness and maintainability:

  • Ensuring error propagation in data conversions.
  • Maintaining consistency in the use of the new binary protocol configuration.
  • Improving test structure and correctness.

Overall, this is a solid enhancement to the project's performance and scalability.

Comment on lines +199 to +218
impl From<BroadcastMessage> for BinaryBroadcastMessage {
fn from(msg: BroadcastMessage) -> Self {
let node_id_bytes = uuid_to_bytes(&msg.node_id).unwrap_or([0u8; 16]);
let channel_hash = calculate_channel_hash(&msg.channel);

// The message field contains the JSON string that should be sent to clients
let raw_client_json = msg.message.into_bytes();

Self {
version: BINARY_PROTOCOL_VERSION,
channel_hash,
channel: msg.channel,
node_id_bytes,
app_id: msg.app_id,
raw_client_json,
except_socket_id: msg.except_socket_id,
timestamp_ms: msg.timestamp_ms,
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using unwrap_or here can silently hide errors. If uuid_to_bytes fails due to a malformed UUID string, the node_id will be replaced with a zero-UUID ([0u8; 16]). This could lead to hard-to-debug issues, such as messages being misattributed or lost. It's safer to propagate the error by using TryFrom instead of From. This will require updating the call sites from .into() to .try_into()?, which is a worthwhile trade-off for correctness.

impl TryFrom<BroadcastMessage> for BinaryBroadcastMessage {
    type Error = Error;

    fn try_from(msg: BroadcastMessage) -> Result<Self> {
        let node_id_bytes = uuid_to_bytes(&msg.node_id)?;
        let channel_hash = calculate_channel_hash(&msg.channel);

        // The message field contains the JSON string that should be sent to clients
        let raw_client_json = msg.message.into_bytes();

        Ok(Self {
            version: BINARY_PROTOCOL_VERSION,
            channel_hash,
            channel: msg.channel,
            node_id_bytes,
            app_id: msg.app_id,
            raw_client_json,
            except_socket_id: msg.except_socket_id,
            timestamp_ms: msg.timestamp_ms,
        })
    }
}

Comment on lines +412 to +428
#[test]
fn test_bincode_serialization_size() {
let msg = BroadcastMessage {
node_id: "550e8400-e29b-41d4-a716-446655440000".to_string(),
app_id: "test-app".to_string(),
channel: "test-channel".to_string(),
message: r#"{"event":"test","data":"payload"}"#.to_string(),
except_socket_id: None,
timestamp_ms: Some(1234567890.123),
};

let _json_size = serde_json::to_vec(&msg).unwrap().len();
let binary: BinaryBroadcastMessage = msg.into();
let _binary_size = bincode::encode_to_vec(&binary, bincode_config())
.unwrap()
.len();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This test function calculates serialization sizes but doesn't perform any assertions. The variables _json_size and _binary_size are unused, which will result in compiler warnings. A test without assertions doesn't verify any behavior and can be misleading. Consider adding a meaningful assertion or removing this test if it was intended for manual debugging.

    fn test_bincode_serialization_size() {
        let msg = BroadcastMessage {
            node_id: "550e8400-e29b-41d4-a716-446655440000".to_string(),
            app_id: "test-app".to_string(),
            channel: "test-channel".to_string(),
            message: r#"{"event":"test","data":"payload"}"#.to_string(),
            except_socket_id: None,
            timestamp_ms: Some(1234567890.123),
        };

        let json_size = serde_json::to_vec(&msg).unwrap().len();
        let binary: BinaryBroadcastMessage = msg.try_into().unwrap();
        let binary_size = bincode::encode_to_vec(&binary, bincode_config())
            .unwrap()
            .len();
        assert!(binary_size < json_size, "binary size ({}) should be less than json size ({})", binary_size, json_size);
    }

Comment on lines 90 to 91
let message_data = bincode::encode_to_vec(&binary_msg, bincode::config::standard())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency and to enforce the message size limit, it's better to use the shared bincode_config() function from the binary_protocol module instead of bincode::config::standard(). This ensures that all serialization and deserialization operations across transports follow the same rules, including the MAX_MESSAGE_SIZE limit for security. This applies to all bincode::encode_to_vec and bincode::decode_from_slice calls in this file.

Suggested change
let message_data = bincode::encode_to_vec(&binary_msg, bincode::config::standard())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;
let message_data = bincode::encode_to_vec(&binary_msg, crate::adapter::binary_protocol::bincode_config())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;

Comment on lines 80 to 81
let broadcast_bytes = bincode::encode_to_vec(&binary_msg, bincode::config::standard())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency and to enforce the message size limit, it's better to use the shared bincode_config() function from the binary_protocol module instead of bincode::config::standard(). This ensures that all serialization and deserialization operations across transports follow the same rules, including the MAX_MESSAGE_SIZE limit for security. This applies to all bincode::encode_to_vec and bincode::decode_from_slice calls in this file.

Suggested change
let broadcast_bytes = bincode::encode_to_vec(&binary_msg, bincode::config::standard())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;
let broadcast_bytes = bincode::encode_to_vec(&binary_msg, crate::adapter::binary_protocol::bincode_config())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;

Comment on lines 102 to 103
let broadcast_bytes = bincode::encode_to_vec(&binary_msg, bincode::config::standard())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency and to enforce the message size limit, it's better to use the shared bincode_config() function from the binary_protocol module instead of bincode::config::standard(). This ensures that all serialization and deserialization operations across transports follow the same rules, including the MAX_MESSAGE_SIZE limit for security. This applies to all bincode::encode_to_vec and bincode::decode_from_slice calls in this file.

Suggested change
let broadcast_bytes = bincode::encode_to_vec(&binary_msg, bincode::config::standard())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;
let broadcast_bytes = bincode::encode_to_vec(&binary_msg, crate::adapter::binary_protocol::bincode_config())
.map_err(|e| Error::Other(format!("Failed to serialize broadcast: {}", e)))?;

@@ -0,0 +1,230 @@
use sockudo::adapter::binary_protocol::*;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This new test file contains comprehensive tests for the binary protocol conversions. However, these appear to be unit tests for the binary_protocol module. To improve maintainability and keep tests co-located with the code they test, it's a Rust convention to place unit tests inside the module file itself, under a #[cfg(test)] mod tests { ... } block.

Consider moving the tests from this file into src/adapter/binary_protocol.rs and deleting this file. This will consolidate all binary_protocol unit tests in one place, making them easier to find and maintain. The existing tests in binary_protocol.rs can be merged with or replaced by these more comprehensive ones.

Additionally, the test_bincode_size_reduction test currently only prints to the console and has no assertions. Tests should be verifiable. Please add an assertion (e.g., assert!(binary_bytes.len() < json_bytes.len())) or remove it if it's for debugging purposes.

@countradooku countradooku marked this pull request as draft October 21, 2025 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants