Skip to content

feat: add test-utils feature to allow connections to be force closed from the server side #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ThetaSinner
Copy link
Member

@ThetaSinner ThetaSinner commented Aug 6, 2025

Summary by CodeRabbit

  • New Features
    • Added a new optional feature to enable test utilities.
    • Introduced a method to drop all active connections for testing scenarios (available when test utilities are enabled).
    • Enhanced logging for new websocket connections.

Copy link

cocogitto-bot bot commented Aug 6, 2025

✔️ 09cb1bb - Conventional commits check succeeded.

@ThetaSinner ThetaSinner marked this pull request as draft August 6, 2025 13:44
Copy link

coderabbitai bot commented Aug 6, 2025

Walkthrough

A new feature flag named test-utils was introduced in the sbd-server Rust package. Under this flag, new asynchronous methods for dropping all active connections were added to the CSlot and SbdServer structs to facilitate testing scenarios. A logging statement was also added to the connection insertion method.

Changes

Cohort / File(s) Change Summary
Cargo Feature Addition
rust/sbd-server/Cargo.toml
Added an empty test-utils feature to the [features] section.
CSlot Enhancements
rust/sbd-server/src/cslot.rs
Added a logging statement to the insert method and introduced an async drop_all_connections method under the test-utils feature.
SbdServer Enhancements
rust/sbd-server/src/lib.rs
Added a public async drop_all_connections method to SbdServer, gated by the test-utils feature, delegating to CSlot.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Code
    participant SbdServer
    participant CSlot

    Test->>SbdServer: drop_all_connections()
    activate SbdServer
    SbdServer->>CSlot: drop_all_connections()
    activate CSlot
    CSlot->>CSlot: Remove all active connections
    deactivate CSlot
    SbdServer-->>Test: (async complete)
    deactivate SbdServer
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~7 minutes

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test-utils-shutdown-connections

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9658faf and 09cb1bb.

📒 Files selected for processing (3)
  • rust/sbd-server/Cargo.toml (1 hunks)
  • rust/sbd-server/src/cslot.rs (2 hunks)
  • rust/sbd-server/src/lib.rs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
rust/sbd-server/src/lib.rs (1)
rust/sbd-server/src/cslot.rs (1)
  • drop_all_connections (296-323)
rust/sbd-server/src/cslot.rs (1)
rust/sbd-server/src/lib.rs (1)
  • drop_all_connections (644-646)
🔇 Additional comments (3)
rust/sbd-server/Cargo.toml (1)

60-60: LGTM! Clean feature flag addition.

The test-utils feature flag is properly positioned and follows Rust conventions for test-only functionality.

rust/sbd-server/src/lib.rs (1)

640-646: LGTM! Well-designed test utility method.

The drop_all_connections method is properly implemented with:

  • Appropriate feature gating with test-utils
  • Clear documentation explaining its fault simulation purpose
  • Clean delegation to the underlying CSlot implementation
rust/sbd-server/src/cslot.rs (1)

208-208: LGTM! Useful logging addition.

The logging statement provides helpful debugging information for connection management.

Comment on lines +295 to +323
#[cfg(feature = "test-utils")]
pub(crate) async fn drop_all_connections(&self) {
let keys = {
let guard = self.0.lock().expect("poisoned");
guard.pk_to_index.keys().cloned().collect::<Vec<_>>()
};

for pk in keys {
if let Ok((uniq, index, _ws)) = self.get_sender(&pk) {
let mut lock = self.0.lock().unwrap();

match lock.slab.get(index) {
None => return,
Some(s) => {
if s.uniq != uniq {
return;
}
}
}

lock.slab.remove(index);
lock.pk_to_index.retain(|_, i| *i != index);
lock.ip_to_index.retain(|_, v| {
v.retain(|i| *i != index);
!v.is_empty()
});
}
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix early returns that prevent processing all connections.

The method has logic issues that cause it to exit early instead of processing all connections:

Apply this diff to fix the early returns:

                match lock.slab.get(index) {
-                    None => return,
+                    None => continue,
                    Some(s) => {
                        if s.uniq != uniq {
-                            return;
+                            continue;
                        }
                    }
                }

The current implementation stops processing remaining connections if any single connection is not found or has a mismatched unique identifier, which defeats the purpose of dropping all connections.

Additionally, consider adding documentation about the intentional lack of close messages:

    #[cfg(feature = "test-utils")]
+    /// Drop all connections without sending close messages.
+    /// This simulates a fault scenario for testing purposes.
    pub(crate) async fn drop_all_connections(&self) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#[cfg(feature = "test-utils")]
pub(crate) async fn drop_all_connections(&self) {
let keys = {
let guard = self.0.lock().expect("poisoned");
guard.pk_to_index.keys().cloned().collect::<Vec<_>>()
};
for pk in keys {
if let Ok((uniq, index, _ws)) = self.get_sender(&pk) {
let mut lock = self.0.lock().unwrap();
match lock.slab.get(index) {
None => return,
Some(s) => {
if s.uniq != uniq {
return;
}
}
}
lock.slab.remove(index);
lock.pk_to_index.retain(|_, i| *i != index);
lock.ip_to_index.retain(|_, v| {
v.retain(|i| *i != index);
!v.is_empty()
});
}
}
}
#[cfg(feature = "test-utils")]
/// Drop all connections without sending close messages.
/// This simulates a fault scenario for testing purposes.
pub(crate) async fn drop_all_connections(&self) {
let keys = {
let guard = self.0.lock().expect("poisoned");
guard.pk_to_index.keys().cloned().collect::<Vec<_>>()
};
for pk in keys {
if let Ok((uniq, index, _ws)) = self.get_sender(&pk) {
let mut lock = self.0.lock().unwrap();
match lock.slab.get(index) {
None => continue,
Some(s) => {
if s.uniq != uniq {
continue;
}
}
}
lock.slab.remove(index);
lock.pk_to_index.retain(|_, i| *i != index);
lock.ip_to_index.retain(|_, v| {
v.retain(|i| *i != index);
!v.is_empty()
});
}
}
}
🤖 Prompt for AI Agents
In rust/sbd-server/src/cslot.rs between lines 295 and 323, the
drop_all_connections function uses early returns inside the loop that cause it
to stop processing all connections prematurely. To fix this, replace the return
statements with continue statements so the loop skips the current connection on
errors or mismatches but continues processing the rest. Also, add a comment
explaining that no close messages are sent intentionally when dropping
connections.

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.

1 participant