Skip to content

Implement leak-proof SessionRegistry#153

Merged
leynos merged 5 commits intomainfrom
codex/implement-leak-proof-sessionregistry-with-dashmap
Jun 29, 2025
Merged

Implement leak-proof SessionRegistry#153
leynos merged 5 commits intomainfrom
codex/implement-leak-proof-sessionregistry-with-dashmap

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Jun 29, 2025

Summary

  • implement SessionRegistry backed by DashMap<ConnectionId, Weak<PushHandleInner>>
  • expose new ConnectionId type
  • add methods to manage and access handles without leaks
  • add comprehensive tests for registry functionality
  • document sessions in the README

Testing

  • make lint
  • make test

https://chatgpt.com/codex/tasks/task_e_686081a8382c832283b477b2cffa0269

Summary by Sourcery

Implement a leak-proof SessionRegistry that uses DashMap and Weak pointers to manage connection PushHandles without preventing their cleanup.

New Features:

  • Add SessionRegistry to track active PushHandles by ConnectionId using weak references
  • Introduce ConnectionId type and expose it in the public API

Enhancements:

  • Add PushHandle::downgrade and PushHandle::from_arc methods to support weak reference storage

Build:

  • Add dashmap dependency for concurrent session registry

Documentation:

  • Document the SessionRegistry in the README and mark it as completed in the asynchronous outbound messaging roadmap

Tests:

  • Add tests for SessionRegistry covering handle retrieval, cleanup after drop, and pruning dead entries

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Jun 29, 2025

Reviewer's Guide

Adds a leak-proof SessionRegistry backed by DashMap<ConnectionId, Weak> with insert/get/remove/prune methods, extends PushHandle with downgrade/from_arc, exports ConnectionId and SessionRegistry in the crate root, introduces dashmap dependency, includes comprehensive registry tests, and updates related documentation.

Class diagram for SessionRegistry and related types

classDiagram
    class ConnectionId {
        +u64 value
        +from(u64) ConnectionId
    }
    class PushHandleInner~F~ {
        +high_prio_tx: mpsc::Sender<F>
        +low_prio_tx: mpsc::Sender<F>
    }
    class PushHandle~F~ {
        +from_arc(arc: Arc<PushHandleInner<F>>) PushHandle<F>
        +downgrade() Weak<PushHandleInner<F>>
        +push(frame: F)
        +try_push(frame: F)
    }
    class SessionRegistry~F~ {
        +get(id: &ConnectionId) Option<PushHandle<F>>
        +insert(id: ConnectionId, handle: &PushHandle<F>)
        +remove(id: &ConnectionId)
        +prune()
    }
    SessionRegistry~F~ --> "*" ConnectionId : uses as key
    SessionRegistry~F~ --> "*" PushHandleInner~F~ : stores Weak refs
    PushHandle~F~ --> PushHandleInner~F~ : wraps Arc
    PushHandle~F~ ..> SessionRegistry~F~ : used in insert/get
Loading

File-Level Changes

Change Details Files
Implement SessionRegistry storing weak handles keyed by ConnectionId
  • Add session.rs module with ConnectionId and SessionRegistry
  • Implement get, insert, remove, and prune using DashMap and Weak
  • Derive Default and necessary traits for registry and identifier
src/session.rs
Extend PushHandle to support weak references
  • Make PushHandleInner pub(crate)
  • Add PushHandle::from_arc to build handle from Arc
  • Add PushHandle::downgrade to produce Weak reference
src/push.rs
Expose new session API and add DashMap dependency
  • Publish session module and ConnectionId, SessionRegistry in lib.rs
  • Add dashmap = "5" to Cargo.toml
src/lib.rs
Cargo.toml
Add tests for SessionRegistry functionality
  • Test retrieving a live handle
  • Test get returns None after handle drop
  • Test prune removes dead entries
tests/session_registry.rs
Update documentation with SessionRegistry details
  • Document registry usage in README.md
  • Mark leak-proof SessionRegistry complete in roadmap doc
README.md
docs/asynchronous-outbound-messaging-roadmap.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 29, 2025

Summary by CodeRabbit

  • New Features
    • Introduced a session registry for managing active connection handles, enabling asynchronous messaging and efficient broadcasting or diagnostics.
    • Added public types for session management and connection identification.
  • Documentation
    • Updated and expanded documentation to describe the new session registry, its usage, and lifecycle, including diagrams and usage examples.
  • Bug Fixes
    • Improved handling of stale session entries by ensuring expired handles are cleaned up automatically.
  • Tests
    • Added comprehensive tests covering session handle lifecycle, retrieval, pruning, and listing of active sessions.
  • Chores
    • Updated dependencies to include a new concurrency library.

Summary by CodeRabbit

  • New Features
    • Introduced a session registry for managing active connection handles, enabling asynchronous outbound messaging via weak references.
    • Added public types and methods for session management, including SessionRegistry and ConnectionId.
  • Documentation
    • Updated the README with a new section explaining the session registry and usage examples.
    • Marked the session registry implementation as complete in the asynchronous outbound messaging roadmap.
  • Tests
    • Added tests to verify correct lifecycle handling and pruning of session handles in the session registry.

Walkthrough

A new SessionRegistry module was introduced to manage weak references to active connection handles, enabling asynchronous frame sending without preventing connection cleanup. The push module was updated to support weak references. Documentation was updated to describe the new registry, and corresponding tests were added for session lifecycle management.

Changes

File(s) Change Summary
Cargo.toml Added dashmap v5 as a new dependency.
README.md Documented the new SessionRegistry type, usage, and example code.
docs/asynchronous-outbound-messaging-roadmap.md Marked the SessionRegistry with dashmap::DashMap and Weak pointers as complete in the checklist.
src/lib.rs Added new public session module; re-exported ConnectionId and SessionRegistry.
src/push.rs Made PushHandleInner public within the crate; added from_arc and downgrade methods to PushHandle.
src/session.rs Introduced SessionRegistry and ConnectionId types for managing weak references to connection handles.
tests/session_registry.rs Added async tests for insertion, retrieval, invalidation, and pruning in SessionRegistry.

Sequence Diagram(s)

sequenceDiagram
    participant Task as Background Task
    participant Registry as SessionRegistry
    participant Conn as Connection (PushHandle)
    participant Queue as Frame Queue

    Task->>Registry: get(ConnectionId)
    alt If handle exists and alive
        Registry-->>Task: PushHandle
        Task->>Conn: push(frame)
        Conn->>Queue: enqueue(frame)
    else If handle missing or dropped
        Registry-->>Task: None
    end
Loading

Possibly related PRs

Suggested reviewers

  • codescene-delta-analysis

Poem

A registry built with DashMap speed,
Keeps weak handles for every need.
Connections come, connections go,
Prune the dead, let live ones flow.
Now rabbits push frames with delight,
As sessions are managed just right!
🐇✨


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5aeebaa and 758048e.

📒 Files selected for processing (2)
  • README.md (1 hunks)
  • docs/asynchronous-outbound-messaging-design.md (6 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
`**/*.md`: Validate Markdown files using `markdownlint *.md **/*.md`. Run `mdfor...

**/*.md: Validate Markdown files using markdownlint *.md **/*.md.
Run mdformat-all after any documentation changes to format all Markdown files and fix table markup.
Validate Markdown Mermaid diagrams using the nixie CLI by running nixie *.md **/*.md.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks in Markdown files must be wrapped at 120 columns.
Tables and headings in Markdown files must not be wrapped.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • README.md
  • docs/asynchronous-outbound-messaging-design.md
`**/*.md`: * Avoid 2nd person or 1st person pronouns ("I", "you", "we") * Use en...

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-oxendic spelling and grammar.
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • README.md
  • docs/asynchronous-outbound-messaging-design.md
`docs/**/*.md`: Use the markdown files within the `docs/` directory as a knowled...

docs/**/*.md: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Proactively update the relevant file(s) in the docs/ directory to reflect the latest state when new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve.
Documentation in the docs/ directory must use en-GB-oxendict spelling and grammar, except for the word 'license'.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-design.md
`docs/*`: Each file in the docs/ directory provides design, roadmap, testing, op...

docs/*: Each file in the docs/ directory provides design, roadmap, testing, operations, or reference documentation for the project. Use these files as a reference for understanding the project's architecture, development plans, testing strategies, operational guidelines, and documentation conventions.

📄 Source: CodeRabbit Inference Engine (docs/contents.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-design.md
`docs/**/*.md`: Use British English spelling based on the Oxford English Diction...

docs/**/*.md: Use British English spelling based on the Oxford English Dictionary, except retain US spelling in API names (e.g., 'color').
Use the Oxford comma in lists.
Write headings in sentence case and use Markdown heading levels in order without skipping.
Follow markdownlint recommendations for Markdown formatting.
Always use fenced code blocks with a language identifier; use 'plaintext' for non-code text.
Use '-' as the first level bullet and renumber lists when items change.
Prefer inline links using 'text' or angle brackets around the URL.
Expand any uncommon acronym on first use, e.g., Continuous Integration (CI).
Wrap paragraphs at 80 columns, code at 120 columns, and do not wrap tables.
Use footnotes referenced with '[^label]'.
When embedding figures, use 'alt text' and provide concise alt text describing the content.
Add a short description before each Mermaid diagram for screen readers.

📄 Source: CodeRabbit Inference Engine (docs/documentation-style-guide.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-design.md
`docs/**/*`: Write official documentation for new features, including separate g...

docs/**/*: Write official documentation for new features, including separate guides for 'Duplex Messaging & Pushes', 'Streaming Responses', and 'Message Fragmentation', each with runnable examples and explanations of relevant concepts and APIs.

📄 Source: CodeRabbit Inference Engine (docs/wireframe-1-0-detailed-development-roadmap.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-design.md
🪛 LanguageTool
docs/asynchronous-outbound-messaging-design.md

[uncategorized] ~73-~73: Loose punctuation mark.
Context: ...low_priority_push_rx: mpsc::Receiver`: For standard, non-urgent background ...

(UNLIKELY_OPENING_PUNCTUATION)


[style] ~448-~448: Would you like to use the Oxford spelling “summarizes”? The spelling ‘summarises’ is also correct.
Context: ...ollect() } } ``` The diagram below summarises the data structures and how they intera...

(OXFORD_SPELLING_Z_NOT_S)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-test
🔇 Additional comments (2)
docs/asynchronous-outbound-messaging-design.md (2)

436-444: LGTM – clear and idiomatic iterator chain

The active_handles() implementation is compact, avoids double look-ups, and
returns ownership cleanly. Nice work.


413-421: Minor style tidy-up: the explicit drop(guard) is unnecessary

guard goes out of scope at the end of the function, so the explicit
drop(guard); call adds no functional value and slightly obscures the flow.
Removing it keeps the example concise without altering semantics.

-    let handle = guard.as_ref().and_then(|w| w.upgrade());
-    drop(guard);
+    let handle = guard.as_ref().and_then(|w| w.upgrade());

Likely an incorrect or invalid review comment.

✨ Finishing Touches
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch codex/implement-leak-proof-sessionregistry-with-dashmap

🪧 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.
    • @coderabbitai modularize this function.
  • 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.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

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

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

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 auto-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
Copy Markdown
Contributor

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey @leynos - I've reviewed your changes - here's some feedback:

  • Consider having get remove expired entries (e.g. prune when upgrade returns None) so that dead sessions don’t accumulate in the registry.
  • You might want to add an iterator or listing method for active ConnectionIds/PushHandles to support broadcast or diagnostics without reaching into the DashMap directly.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider having `get` remove expired entries (e.g. prune when `upgrade` returns `None`) so that dead sessions don’t accumulate in the registry.
- You might want to add an iterator or listing method for active `ConnectionId`s/`PushHandle`s to support broadcast or diagnostics without reaching into the `DashMap` directly.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Copy link
Copy Markdown
Contributor

@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: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between af47ccc and b2ca1c7.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (7)
  • Cargo.toml (1 hunks)
  • README.md (1 hunks)
  • docs/asynchronous-outbound-messaging-roadmap.md (1 hunks)
  • src/lib.rs (1 hunks)
  • src/push.rs (4 hunks)
  • src/session.rs (1 hunks)
  • tests/session_registry.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (9)
`Cargo.toml`: Use explicit version ranges in `Cargo.toml` and keep dependencies up-to-date.

Cargo.toml: Use explicit version ranges in Cargo.toml and keep dependencies up-to-date.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • Cargo.toml
`docs/**/*.md`: Use the markdown files within the `docs/` directory as a knowled...

docs/**/*.md: Use the markdown files within the docs/ directory as a knowledge base and source of truth for project requirements, dependency choices, and architectural decisions.
Proactively update the relevant file(s) in the docs/ directory to reflect the latest state when new decisions are made, requirements change, libraries are added/removed, or architectural patterns evolve.
Documentation in the docs/ directory must use en-GB-oxendict spelling and grammar, except for the word 'license'.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-roadmap.md
`**/*.md`: Validate Markdown files using `markdownlint *.md **/*.md`. Run `mdfor...

**/*.md: Validate Markdown files using markdownlint *.md **/*.md.
Run mdformat-all after any documentation changes to format all Markdown files and fix table markup.
Validate Markdown Mermaid diagrams using the nixie CLI by running nixie *.md **/*.md.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks in Markdown files must be wrapped at 120 columns.
Tables and headings in Markdown files must not be wrapped.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-roadmap.md
  • README.md
`docs/*`: Each file in the docs/ directory provides design, roadmap, testing, op...

docs/*: Each file in the docs/ directory provides design, roadmap, testing, operations, or reference documentation for the project. Use these files as a reference for understanding the project's architecture, development plans, testing strategies, operational guidelines, and documentation conventions.

📄 Source: CodeRabbit Inference Engine (docs/contents.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-roadmap.md
`docs/**/*.md`: Use British English spelling based on the Oxford English Diction...

docs/**/*.md: Use British English spelling based on the Oxford English Dictionary, except retain US spelling in API names (e.g., 'color').
Use the Oxford comma in lists.
Write headings in sentence case and use Markdown heading levels in order without skipping.
Follow markdownlint recommendations for Markdown formatting.
Always use fenced code blocks with a language identifier; use 'plaintext' for non-code text.
Use '-' as the first level bullet and renumber lists when items change.
Prefer inline links using 'text' or angle brackets around the URL.
Expand any uncommon acronym on first use, e.g., Continuous Integration (CI).
Wrap paragraphs at 80 columns, code at 120 columns, and do not wrap tables.
Use footnotes referenced with '[^label]'.
When embedding figures, use 'alt text' and provide concise alt text describing the content.
Add a short description before each Mermaid diagram for screen readers.

📄 Source: CodeRabbit Inference Engine (docs/documentation-style-guide.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-roadmap.md
`docs/**/*`: Write official documentation for new features, including separate g...

docs/**/*: Write official documentation for new features, including separate guides for 'Duplex Messaging & Pushes', 'Streaming Responses', and 'Message Fragmentation', each with runnable examples and explanations of relevant concepts and APIs.

📄 Source: CodeRabbit Inference Engine (docs/wireframe-1-0-detailed-development-roadmap.md)

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-roadmap.md
`**/*.md`: * Avoid 2nd person or 1st person pronouns ("I", "you", "we") * Use en...

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-oxendic spelling and grammar.
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • docs/asynchronous-outbound-messaging-roadmap.md
  • README.md
`**/*.rs`: Every Rust module must begin with a module level (`//!`) comment expl...

**/*.rs: Every Rust module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public Rust APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • src/lib.rs
  • tests/session_registry.rs
  • src/push.rs
  • src/session.rs
`**/*.rs`: * Seek to keep the cyclomatic complexity of functions no more than 12...

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments must use en-GB-oxendict spelling and grammar.

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • src/lib.rs
  • tests/session_registry.rs
  • src/push.rs
  • src/session.rs
🧬 Code Graph Analysis (1)
src/session.rs (1)
src/push.rs (1)
  • from_arc (58-58)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-test
🔇 Additional comments (15)
Cargo.toml (1)

15-15: Good addition for SessionRegistry support.

The dashmap dependency correctly supports the concurrent SessionRegistry implementation. The major version constraint is appropriate for this concurrent data structure library.

docs/asynchronous-outbound-messaging-roadmap.md (1)

29-31: Accurate completion tracking.

The roadmap correctly marks the SessionRegistry implementation as complete, with proper references to the design documentation.

src/lib.rs (2)

21-21: Proper module addition for session functionality.

The new session module correctly exposes the SessionRegistry functionality.


26-26: Appropriate public re-exports.

The re-exports of ConnectionId and SessionRegistry follow the established pattern and make the new types accessible to library users.

README.md (1)

148-169: Clear and helpful documentation addition.

The Session Registry section effectively explains the purpose and usage of the new functionality. The code example demonstrates practical integration within a WireframeProtocol implementation.

Minor style note: Consider using British English spelling throughout for consistency with coding guidelines (though this may be acceptable as technical documentation).

src/push.rs (4)

9-9: Necessary import for weak reference support.

The Weak import is required for the new downgrade functionality supporting the SessionRegistry.


48-48: Appropriate visibility change for crate-internal access.

Making PushHandleInner pub(crate) allows the session module to access it while maintaining encapsulation from external users.


58-58: Useful constructor for Arc-based creation.

The from_arc method provides a clean way to create PushHandle instances from existing Arc<PushHandleInner<F>>, supporting the SessionRegistry's internal operations.


121-122: Essential method for SessionRegistry integration.

The downgrade method enables creating weak references for storage in the SessionRegistry, preventing memory leaks whilst allowing frame delivery to active connections.

tests/session_registry.rs (1)

1-1: LGTM: Proper module documentation.

The module-level doc comment correctly explains the module's purpose as required by the coding guidelines.

src/session.rs (5)

1-6: LGTM: Excellent module documentation.

The module-level doc comment properly explains the module's purpose and utility, meeting the coding guidelines requirements.


25-32: LGTM: Correct weak reference upgrade pattern.

The implementation correctly upgrades the weak reference and uses the from_arc method to reconstruct the PushHandle. This properly handles the case where the connection may have been dropped.


39-40: LGTM: Simple and correct removal implementation.

The remove method correctly removes entries from the DashMap.


42-43: LGTM: Proper weak reference pruning logic.

The pruning implementation correctly uses strong_count() > 0 to identify live weak references and removes dead entries. This prevents the registry from accumulating dead entries over time.


34-37: Verified: PushHandle::downgrade() exists and returns the expected Weak<PushHandleInner<F>>

  • Defined in src/push.rs at line 122:
    pub(crate) fn downgrade(&self) -> Weak<PushHandleInner<F>> {
        Arc::downgrade(&self.0)
    }

No changes are required here.

Comment thread tests/session_registry.rs
Comment thread src/session.rs
Copy link
Copy Markdown
Contributor

@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: 2

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between b2ca1c7 and 27b6c00.

📒 Files selected for processing (3)
  • README.md (1 hunks)
  • src/session.rs (1 hunks)
  • tests/session_registry.rs (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
`**/*.md`: Validate Markdown files using `markdownlint *.md **/*.md`. Run `mdfor...

**/*.md: Validate Markdown files using markdownlint *.md **/*.md.
Run mdformat-all after any documentation changes to format all Markdown files and fix table markup.
Validate Markdown Mermaid diagrams using the nixie CLI by running nixie *.md **/*.md.
Markdown paragraphs and bullet points must be wrapped at 80 columns.
Code blocks in Markdown files must be wrapped at 120 columns.
Tables and headings in Markdown files must not be wrapped.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • README.md
`**/*.md`: * Avoid 2nd person or 1st person pronouns ("I", "you", "we") * Use en...

**/*.md: * Avoid 2nd person or 1st person pronouns ("I", "you", "we")

  • Use en-oxendic spelling and grammar.
  • Paragraphs and bullets must be wrapped to 80 columns, except where a long URL would prevent this (in which case, silence MD013 for that line)
  • Code blocks should be wrapped to 120 columns.
  • Headings must not be wrapped.

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • README.md
`**/*.rs`: Every Rust module must begin with a module level (`//!`) comment expl...

**/*.rs: Every Rust module must begin with a module level (//!) comment explaining the module's purpose and utility.
Document public Rust APIs using Rustdoc comments (///) so documentation can be generated with cargo doc.
Place function attributes after doc comments.

📄 Source: CodeRabbit Inference Engine (AGENTS.md)

List of files the instruction was applied to:

  • tests/session_registry.rs
  • src/session.rs
`**/*.rs`: * Seek to keep the cyclomatic complexity of functions no more than 12...

**/*.rs: * Seek to keep the cyclomatic complexity of functions no more than 12.

  • Adhere to single responsibility and CQRS

  • Place function attributes after doc comments.

  • Do not use return in single-line functions.

  • Move conditionals with >2 branches into a predicate function.

  • Avoid unsafe unless absolutely necessary.

  • Every module must begin with a //! doc comment that explains the module's purpose and utility.

  • Comments must use en-GB-oxendict spelling and grammar.

  • Lints must not be silenced except as a last resort.

    • #[allow] is forbidden.
    • Only narrowly scoped #[expect(lint, reason = "...")] is allowed.
    • No lint groups, no blanket or file-wide suppression.
    • Include FIXME: with link if a fix is expected.
  • Use rstest fixtures for shared setup and to avoid repetition between tests.

  • Replace duplicated tests with #[rstest(...)] parameterised cases.

  • Prefer mockall for mocks/stubs.

  • Prefer .expect() over .unwrap()

  • Ensure that any API or behavioural changes are reflected in the documentation in docs/

  • Ensure that any completed roadmap steps are recorded in the appropriate roadmap in docs/

⚙️ Source: CodeRabbit Configuration File

List of files the instruction was applied to:

  • tests/session_registry.rs
  • src/session.rs
🧬 Code Graph Analysis (2)
tests/session_registry.rs (3)
src/push.rs (1)
  • bounded (135-149)
src/session.rs (3)
  • from (18-18)
  • new (24-24)
  • get (43-48)
tests/connection_actor.rs (1)
  • queues (18-18)
src/session.rs (1)
src/push.rs (1)
  • from_arc (58-58)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build-test
🔇 Additional comments (4)
tests/session_registry.rs (1)

1-62: Excellent test coverage using rstest fixtures.

The tests effectively cover the SessionRegistry lifecycle management with proper use of rstest fixtures to reduce duplication, comprehensive doc comments, and clear test scenarios. This addresses the requirements from the coding guidelines perfectly.

src/session.rs (3)

1-11: Excellent module documentation and imports.

The module doc comment clearly explains the purpose and design rationale for using weak references. The imports are well-organised and appropriate.


13-35: Well-designed ConnectionId type with comprehensive API.

The ConnectionId implementation follows Rust best practices with appropriate derives, conversion traits, utility methods with #[must_use] attributes, and a helpful Display implementation. This addresses the previous feedback about adding utility methods.


37-60: Robust SessionRegistry implementation with proper lifecycle management.

The SessionRegistry correctly uses weak references to prevent memory leaks whilst enabling asynchronous frame sending. The implementation is thread-safe with DashMap and provides comprehensive lifecycle management through get, insert, remove, and prune methods.

The prune method correctly removes dead entries by checking strong_count() > 0, and the get method safely upgrades weak references with proper fallback to None when handles are dropped.

Comment thread README.md Outdated
Comment thread tests/session_registry.rs
@leynos leynos merged commit 77fcbe9 into main Jun 29, 2025
5 checks passed
@leynos leynos deleted the codex/implement-leak-proof-sessionregistry-with-dashmap branch June 29, 2025 14:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant