Skip to content

Add Fragmenter and transport-level fragmentation support#395

Merged
leynos merged 7 commits intomainfrom
terragon/implement-fragmentation-reassembly-fowx16
Nov 24, 2025
Merged

Add Fragmenter and transport-level fragmentation support#395
leynos merged 7 commits intomainfrom
terragon/implement-fragmentation-reassembly-fowx16

Conversation

@leynos
Copy link
Copy Markdown
Owner

@leynos leynos commented Nov 17, 2025

Summary

  • Introduces a Fragmenter helper to slice oversized outbound messages into fixed-size transport fragments, each annotated with FragmentHeader metadata (MessageId, FragmentIndex, is_last_fragment).
  • Adds FragmentFrame and FragmentBatch to represent transport-level fragments and batches, with ergonomic iteration and access.
  • Adds FragmentationError to surface encoding or index-overflow errors during fragmentation.
  • Updates public API surface to expose new fragmentation types and wiring for tests and behavioural scenarios.

Changes

Core functionality

  • New src/fragment/fragmenter.rs implementing Fragmenter with:
    • new(max_fragment_size) and with_starting_id(max_fragment_size, start_id)
    • max_fragment_size(), next_message_id()
    • fragment_message(&M) -> FragmentBatch, fragment_bytes(payload) -> FragmentBatch, fragment_with_id(message_id, payload) -> FragmentBatch
    • Internal fragment construction that respects max_fragment_size, assigns FragmentIndex, and marks is_last_fragment on the final piece
    • Overflow handling via FragmentationError::IndexOverflow
  • New FragmentFrame type for a single outbound fragment (header + payload) with header(), payload(), and into_parts()
  • New FragmentBatch type representing a collection of fragments for a single logical message with:
    • message_id(), fragments(), len(), is_empty(), is_fragmented(), into_fragments()
    • IntoIterator implementation for easy consumption
  • New FragmentationError enum (in fragment error module):
    • Encode(EncodeError) for serialization failures
    • IndexOverflow { last: FragmentIndex } for fragment index overflow

Public API surface

  • Expose FragmentBatch, FragmentFrame, Fragmenter, and FragmentationError from the fragment module
  • Re-export new items in src/lib.rs to form a cohesive fragmentation API surface
  • Tests and behavioural tests updated to exercise the new API surface

Tests

  • Expanded unit tests for fragmentation:
    • fragmenter_splits_payload_into_multiple_frames
    • fragmenter_handles_empty_payload
    • fragmenter_fragments_messages_and_increments_ids
    • fragment_batch_into_iterator_yields_all_fragments
  • Updated tests/worlds/fragment.rs with Fragmenter configuration, fragmentation requests, and assertions
  • Extended tests/features/fragment.feature with scenario: Fragmenter splits oversized payloads into sequential fragments
  • Extended tests/steps/fragment_steps.rs with Given/When/Then steps for fragmentation and assertions

Documentation & changelog

  • CHANGELOG.md: note added Fragmenter and transport-level fragmentation capability
  • Documentation updates across the docs folder to reflect fragmentation design, including a new Fragmenter section and updated roadmap notes
  • User guide (docs/users-guide.md) includes an example demonstrating Fragmenter usage

Backwards compatibility

  • Fragmentation is opt-in via the Fragmenter helper; existing code paths remain unaffected if fragmentation is not used.
  • Public API surface has new items but existing APIs remain stable; users may opt into fragmentation by using Fragmenter and FragmentBatch/FragmentFrame types

Example usage

use std::num::NonZeroUsize;
use wireframe::fragment::{Fragmenter, FragmentBatch};

let fragmenter = Fragmenter::new(NonZeroUsize::new(512).unwrap());
let batch: FragmentBatch = fragmenter
    .fragment_bytes(&vec![0u8; 1400])
    .expect("fragmentation should succeed");

assert_eq!(batch.len(), 3);
for (i, f) in batch.into_iter().enumerate() {
    println!("frag {}: {} bytes, last: {}", i, f.payload().len(), f.header().is_last_fragment());
}

Test plan

  • Run cargo test (unit tests for fragmentation)
  • Run cucumber-based behavioural tests for fragmentation scenarios
  • Validate edge cases: empty payload, multi-fragment payloads, and index overflow scenarios

🌿 Generated by Terry


ℹ️ Tag @terragon-labs to ask questions and address PR feedback

📎 Task: https://www.terragonlabs.com/task/b73c1632-521c-4ee5-9a0a-045c2128dbbf

Summary by Sourcery

Introduce an outbound fragmentation helper and wire it into the public fragment API, along with tests and documentation describing its behavior.

New Features:

  • Add a Fragmenter helper that splits outbound messages or raw payloads into fixed-size transport fragments with sequential MessageIds and fragment indices.
  • Introduce FragmentFrame and FragmentBatch types to represent individual fragments and batches for a single logical message, supporting ergonomic access and iteration.
  • Expose a FragmentationError type to surface encoding failures and fragment index overflows during fragmentation.

Enhancements:

  • Extend fragment-world test utilities and Cucumber steps to configure a Fragmenter, request fragmentation, and assert fragment counts, payload sizes, final flags, and message IDs.
  • Update documentation to describe the Fragmenter helper, its API, and how it fits into the broader fragmentation and outbound messaging designs, and mark the roadmap item for Fragmenter as completed.

Documentation:

  • Document the Fragmenter, FragmentBatch, and FragmentFrame types in the design docs and user guide, including example usage and updated design decisions.
  • Adjust markdown linting directives in several design documents to accommodate requirement tables without warnings.

Tests:

  • Add unit tests covering Fragmenter behavior for multi-fragment payloads, empty payloads, message ID sequencing, and FragmentBatch iteration.
  • Add a new behavioural scenario validating that the Fragmenter splits oversized payloads into sequential fragments with correct sizes, final flags, and message IDs.

Chores:

  • Update the changelog to note the new Fragmenter helper and transport-level fragmentation capability.

Introduced a new Fragmenter utility that serializes and splits oversized messages into multiple sequential fragments. Each fragment is tagged with a FragmentHeader containing MessageId, FragmentIndex, and an is_last_fragment flag to enable transparent transport-level reassembly. The API supports generating fresh message IDs automatically or accepting user-provided IDs. FragmentBatch and FragmentFrame types are provided to access and iterate fragments conveniently.

This change includes comprehensive unit and behavioral tests, updates to documentation and design specs, and exposes the new types through the crate root. It facilitates transparent outbound message fragmentation, establishing the groundwork before integrating the full FragmentAdapter layer.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 17, 2025

Warning

Rate limit exceeded

@leynos has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 10 minutes and 29 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between fb9c39c and 97b5645.

📒 Files selected for processing (2)
  • docs/users-guide.md (1 hunks)
  • src/fragment/fragmenter.rs (1 hunks)

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Summary by CodeRabbit

  • New Features

    • Added Fragmenter utility to split oversized messages into sequential fragments with metadata for transparent transport-level reassembly.
    • Added FragmentationError for handling encoding failures and fragment index overflow scenarios.
  • Documentation

    • Updated user guide with Fragmenter usage examples and error handling guidance.
    • Marked Fragmenter capability as implemented in product roadmap.

✏️ Tip: You can customize this high-level summary in your review settings.

Walkthrough

Added an outbound Fragmenter utility that serialises and splits messages/byte payloads into transport fragments with sequential FragmentHeader metadata and monotonic MessageId generation. Introduced FragmentationError (Encode, IndexOverflow), public types Fragmenter, FragmentBatch, FragmentFrame, plus docs, roadmap and tests covering the new behaviour.

Changes

Cohort / File(s) Summary
Core fragmenter implementation
src/fragment/error.rs, src/fragment/fragmenter.rs, src/fragment/mod.rs
Add FragmentationError (variants: Encode, IndexOverflow). Implement Fragmenter (configurable max fragment size, MessageId allocation) and APIs: fragment_message, fragment_bytes, fragment_with_id. Add FragmentFrame (header + payload) and FragmentBatch (collection, iteration). Re-export new types.
Public API surface
src/lib.rs
Re-export Fragmenter, FragmentBatch, FragmentFrame, and FragmentationError at crate root.
Documentation
CHANGELOG.md, docs/generic-message-fragmentation-and-re-assembly-design.md, docs/multi-packet-and-streaming-responses-design.md, docs/users-guide.md, docs/roadmap.md, docs/asynchronous-outbound-messaging-design.md
Document new fragmentation helper, add examples and error notes, mark Fragmenter implemented in roadmap, and add markdownlint toggles around tables.
Tests & test DSL
src/fragment/tests.rs, tests/features/fragment.feature, tests/steps/fragment_steps.rs, tests/worlds/fragment.rs
Add unit tests and BDD scenarios for fragmentation (multi-fragment, empty payload, explicit IDs, ID progression). Extend test world with Fragmenter configuration, batching helpers and assertion helpers.

Sequence Diagram(s)

sequenceDiagram
    rect rgb(243,247,255)
    participant Caller
    participant Fragmenter
    participant Batch
    participant Frame
    end

    Caller->>Fragmenter: Fragmenter::new(max_size)
    Caller->>Fragmenter: fragment_bytes(payload)
    activate Fragmenter
    Fragmenter->>Fragmenter: allocate MessageId
    Fragmenter->>Fragmenter: compute fragment count (div_ceil)
    Fragmenter->>Frame: create Frame(header(index,...), chunk) x N
    Fragmenter->>Batch: assemble Batch(message_id, frames)
    deactivate Fragmenter
    Batch-->>Caller: return FragmentBatch
    Caller->>Batch: fragments() / into_fragments()
    Batch-->>Caller: &[FragmentFrame] / Vec<FragmentFrame>
    Caller->>Frame: header() / payload()
    Frame-->>Caller: metadata & bytes
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Inspect src/fragment/fragmenter.rs for correctness of chunking, div_ceil, padding behaviour, and IndexOverflow handling.
  • Verify FragmentationError conversions (bincode EncodeError) and test coverage in src/fragment/tests.rs.
  • Confirm public re-exports in src/fragment/mod.rs and src/lib.rs match intended API surface.
  • Validate BDD steps and FragmentWorld helpers for determinism and panic semantics.

Possibly related PRs

Suggested reviewers

  • codescene-delta-analysis

Poem

✂️ Messages too wide for one embrace,
Fragmenter slices with steady pace—
IDs climb, indexes line the trail,
Fragments march home to knit the tale.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title directly summarises the main change: adding a Fragmenter helper and transport-level fragmentation support to the codebase.
Description check ✅ Passed The description comprehensively covers the changeset, detailing the Fragmenter helper, new types (FragmentFrame, FragmentBatch), FragmentationError, API surface changes, tests, and documentation updates.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai
Copy link
Copy Markdown
Contributor

sourcery-ai Bot commented Nov 17, 2025

Reviewer's Guide

Implements a new outbound Fragmenter helper that slices messages into capped transport fragments, introduces FragmentFrame/FragmentBatch containers and FragmentationError, wires them into the public fragment API, and extends tests and docs to cover transport-level fragmentation behaviour.

Sequence diagram for fragmenting a message with Fragmenter

sequenceDiagram
    actor "Caller" as Caller
    participant "Fragmenter" as Fragmenter
    participant "Message" as Message
    participant "FragmentBatch" as FragmentBatch
    participant "FragmentFrame" as FragmentFrame
    participant "FragmentIndex" as FragmentIndex

    "Caller" ->> "Fragmenter" : "fragment_message(&message)"
    activate "Fragmenter"

    "Fragmenter" ->> "Message" : "to_bytes()"
    activate "Message"
    "Message" -->> "Fragmenter" : "Result<Vec<u8>, EncodeError>"
    deactivate "Message"

    alt "encode fails"
        "Fragmenter" -->> "Caller" : "Err(FragmentationError::Encode(EncodeError))"
    else "encode succeeds"
        "Fragmenter" ->> "Fragmenter" : "fragment_bytes(payload)"
        "Fragmenter" ->> "Fragmenter" : "next_message_id() -> MessageId"
        "Fragmenter" ->> "Fragmenter" : "fragment_with_id(message_id, payload)"
        "Fragmenter" ->> "Fragmenter" : "build_fragments(message_id, payload)"

        loop "for each fragment slice"
            "Fragmenter" ->> "Fragmenter" : "construct FragmentHeader(message_id, index, is_last)"
            "Fragmenter" ->> "FragmentFrame" : "new(header, payload_chunk.to_vec())"
            activate "FragmentFrame"
            "FragmentFrame" -->> "Fragmenter" : "FragmentFrame"
            deactivate "FragmentFrame"
            alt "need more fragments"
                "Fragmenter" ->> "FragmentIndex" : "checked_increment(index)"
                "FragmentIndex" -->> "Fragmenter" : "Option<FragmentIndex>"
            else "last fragment"
                "Fragmenter" ->> "Fragmenter" : "stop loop"
            end
        end

        alt "index overflow"
            "Fragmenter" -->> "Caller" : "Err(FragmentationError::IndexOverflow { last })"
        else "no overflow"
            "Fragmenter" ->> "FragmentBatch" : "new(message_id, fragments)"
            activate "FragmentBatch"
            "FragmentBatch" -->> "Fragmenter" : "FragmentBatch"
            deactivate "FragmentBatch"
            "Fragmenter" -->> "Caller" : "Ok(FragmentBatch)"
        end
    end
    deactivate "Fragmenter"
Loading

File-Level Changes

Change Details Files
Introduce Fragmenter helper and outbound fragmentation primitives.
  • Add Fragmenter struct that tracks a max fragment size and monotonically increasing MessageId using an AtomicU64.
  • Implement fragment_message, fragment_bytes, and fragment_with_id to serialize or chunk payloads into fixed-size fragments, delegating to an internal build_fragments routine.
  • Handle empty payloads by emitting a single zero-length final fragment, and enforce FragmentIndex overflow protection with FragmentationError::IndexOverflow.
  • Add FragmentFrame type (header + Vec) with accessors and into_parts, and FragmentBatch container with metadata, convenience methods, and IntoIterator support for fragments.
src/fragment/fragmenter.rs
Add FragmentationError and expose new fragmentation API types publicly.
  • Define FragmentationError enum with Encode and IndexOverflow variants to represent outbound fragmentation failures.
  • Export FragmentationError, Fragmenter, FragmentBatch, and FragmentFrame from the fragment module.
  • Re-export new fragmentation types from the crate root to form a cohesive public API surface.
src/fragment/error.rs
src/fragment/mod.rs
src/lib.rs
Extend unit tests and Cucumber worlds/steps to cover Fragmenter behaviour.
  • Add unit tests validating multi-fragment splitting, empty payload handling, MessageId incrementation across calls, and FragmentBatch iterator behaviour.
  • Augment FragmentWorld with Fragmenter configuration, payload fragmentation helpers, and assertion helpers for fragment counts, payload lengths, final flags, and message IDs.
  • Add new step definitions and a feature scenario asserting that an oversized payload is split into sequential fragments with correct sizes, flags, and message ID.
src/fragment/tests.rs
tests/worlds/fragment.rs
tests/steps/fragment_steps.rs
tests/features/fragment.feature
Update documentation, changelog, and roadmap to describe the new fragmentation helper.
  • Document the Fragmenter, FragmentBatch, and FragmentFrame in the generic fragmentation design doc and note their role as outbound helpers.
  • Extend the user guide with a concrete Fragmenter usage example that logs fragment metadata.
  • Relax markdownlint rules where needed and update the roadmap and changelog to mark Fragmenter as implemented and describe the new capability.
docs/generic-message-fragmentation-and-re-assembly-design.md
docs/users-guide.md
docs/asynchronous-outbound-messaging-design.md
docs/multi-packet-and-streaming-responses-design.md
docs/roadmap.md
CHANGELOG.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

codescene-delta-analysis[bot]

This comment was marked as outdated.

@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Nov 18, 2025

@coderabbitai Please suggest a fix for this issue and supply a prompt for an AI coding agent to enable it to apply the fix:

tests/worlds/fragment.rs

Comment on lines +200 to +210

    pub fn assert_fragment_payload_len(&self, index: usize, expected: usize) {
        let fragments = self.batch().fragments();
        let fragment = fragments
            .get(index)
            .unwrap_or_else(|| panic!("fragment {index} missing"));
        assert_eq!(
            fragment.payload().len(),
            expected,
            "payload length mismatch"
        );
    }

❌ New issue: Code Duplication
The module contains 2 functions with similar structure: FragmentWorld.assert_fragment_final_flag,FragmentWorld.assert_fragment_payload_len

@coderabbitai

This comment was marked as resolved.

…ication

Refactor FragmentWorld test code by introducing a get_fragment_at helper method. This method retrieves a fragment at a given index or panics if missing, replacing repeated code within assert_fragment_payload_len and assert_fragment_final_flag. This improves code clarity and reduces duplication in test assertions.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
Added FragmentFrame to imports in tests/worlds/fragment.rs to support upcoming tests or code changes requiring this struct.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
@leynos leynos marked this pull request as ready for review November 21, 2025 18:24
sourcery-ai[bot]

This comment was marked as resolved.

@coderabbitai coderabbitai Bot added the codex label Nov 21, 2025
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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/worlds/fragment.rs (1)

1-5: Update module‑level docs to mention outbound fragmentation

Extend the module‑level //! comment to mention that FragmentWorld now also drives outbound fragmentation scenarios (via the fragmenter and fragment batch assertions), not only re‑assembly. Keep the current description of ordering, completion detection, and error handling, but add a short sentence about exercising fragment production as well.

Also applies to: 37-59, 197-241

📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 97ed69c and 56de7ee.

📒 Files selected for processing (14)
  • CHANGELOG.md (1 hunks)
  • docs/asynchronous-outbound-messaging-design.md (1 hunks)
  • docs/generic-message-fragmentation-and-re-assembly-design.md (4 hunks)
  • docs/multi-packet-and-streaming-responses-design.md (1 hunks)
  • docs/roadmap.md (1 hunks)
  • docs/users-guide.md (1 hunks)
  • src/fragment/error.rs (2 hunks)
  • src/fragment/fragmenter.rs (1 hunks)
  • src/fragment/mod.rs (1 hunks)
  • src/fragment/tests.rs (2 hunks)
  • src/lib.rs (1 hunks)
  • tests/features/fragment.feature (1 hunks)
  • tests/steps/fragment_steps.rs (1 hunks)
  • tests/worlds/fragment.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

**/*.md: Validate Markdown with make markdownlint
Run make fmt after documentation changes to format Markdown and fix table markup
Validate Mermaid diagrams in Markdown using make nixie
Wrap Markdown paragraphs and bullet points at 80 columns
Wrap code blocks in Markdown at 120 columns
Do not wrap tables and headings in Markdown
Use dashes (-) for list bullets in Markdown
Use GitHub-flavoured Markdown footnotes ([^1]) for references and footnotes

Files:

  • CHANGELOG.md
  • docs/roadmap.md
  • docs/users-guide.md
  • docs/multi-packet-and-streaming-responses-design.md
  • docs/generic-message-fragmentation-and-re-assembly-design.md
  • docs/asynchronous-outbound-messaging-design.md

⚙️ CodeRabbit configuration file

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

  • Use en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • CHANGELOG.md
  • docs/roadmap.md
  • docs/users-guide.md
  • docs/multi-packet-and-streaming-responses-design.md
  • docs/generic-message-fragmentation-and-re-assembly-design.md
  • docs/asynchronous-outbound-messaging-design.md
docs/**/*.md

📄 CodeRabbit inference engine (docs/message-versioning.md)

Document examples showing how to deprecate old message versions gracefully

When long lines are warranted in documentation, disable markdownlint rule MD013 inline using the comment:

docs/**/*.md: Use docs/ as the knowledge base and source of truth for requirements, dependencies, and architectural decisions
Proactively update docs/ when decisions, requirements, libraries, or architecture change to keep documentation accurate
Documentation must use en-GB-oxendict spelling and grammar (LICENSE name unchanged)

Follow markdownlint recommendations

Files:

  • docs/roadmap.md
  • docs/users-guide.md
  • docs/multi-packet-and-streaming-responses-design.md
  • docs/generic-message-fragmentation-and-re-assembly-design.md
  • docs/asynchronous-outbound-messaging-design.md
docs/**

📄 CodeRabbit inference engine (docs/wireframe-1-0-detailed-development-roadmap.md)

docs/**: Document async-stream as the canonical way to create streams imperatively
Write comprehensive user guides for Duplex Messaging & Pushes, Streaming Responses, and Message Fragmentation with runnable examples

Files:

  • docs/roadmap.md
  • docs/users-guide.md
  • docs/multi-packet-and-streaming-responses-design.md
  • docs/generic-message-fragmentation-and-re-assembly-design.md
  • docs/asynchronous-outbound-messaging-design.md
docs/**/*.{md,rs}

📄 CodeRabbit inference engine (docs/documentation-style-guide.md)

docs/**/*.{md,rs}: Use British English (en-GB-oxendict) spelling in documentation prose
Keep US spelling when it appears in API identifiers (e.g., color)
The word “outwith” is acceptable in documentation
Use the Oxford comma where it aids comprehension
Treat company names as collective nouns (e.g., “Lille Industries are…”)
Write headings in sentence case
Use Markdown headings (#, ##, ###, …) in order without skipping levels
Use standard Markdown syntax for code blocks and lists
Always provide a language identifier for fenced code blocks; use plaintext for non-code text
Use - as the first-level bullet; renumber ordered lists when items change
Prefer inline links [text](url) or angle-bracket autolinks <url>
Ensure blank lines before and after bulleted lists and fenced code blocks
Ensure Markdown tables include a delimiter line below the header row
Expand uncommon acronyms on first use (e.g., Continuous Integration (CI))
Wrap paragraphs at 80 columns
Wrap code at 120 columns
Do not wrap tables
Use footnotes referenced with [^label]
Include Mermaid diagrams where they add clarity
When embedding images, use Markdown ![alt text](path/to/image) with brief, descriptive alt text
Add a short descriptive sentence before each Mermaid diagram for screen readers

Files:

  • docs/roadmap.md
  • docs/users-guide.md
  • docs/multi-packet-and-streaming-responses-design.md
  • docs/generic-message-fragmentation-and-re-assembly-design.md
  • docs/asynchronous-outbound-messaging-design.md
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Name things precisely; use clear, descriptive names; booleans should use is/has/should prefixes
Use consistent en-GB-oxendict spelling and grammar in comments (except external API references)
Disallow Clippy warnings; fix warnings in code rather than silencing
Extract helpers when functions are too long; maintain separation of concerns and CQRS
Group many parameters into meaningful structs when a function has too many parameters
When returning a large error, consider using Arc to reduce data returned
Every Rust module must begin with a module-level (//! ) comment explaining its purpose and utility
Document public APIs with Rustdoc comments (///) to enable cargo doc generation
Prefer immutable data; avoid unnecessary mut bindings
Use Result for error handling instead of panicking where feasible
Avoid unsafe code unless absolutely necessary and document any usage clearly
Place function attributes after doc comments
Do not use return in single-line functions
Use predicate functions for conditional criteria with more than two branches
Do not silence lints except as a last resort; suppressions must be tightly scoped and include a clear reason
Prefer #[expect] over #[allow] for lints
Prefer .expect() over .unwrap()
Use concat!() to combine long string literals rather than escaping newlines with a backslash
Prefer single-line versions of trivial functions when appropriate (e.g., pub fn new(id: u64) -> Self { Self(id) })
Use NewTypes to model domain values; consider newt-hype, tuple structs, and the-newtype as appropriate; add shims like From<&str>/AsRef; implement AsRef for path wrappers and provide into_inner()/to_path_buf()
Keep file size manageable: no single code file longer than 400 lines; split long switches/dispatch tables by feature; move large test data to external files

Files:

  • src/fragment/tests.rs
  • src/fragment/mod.rs
  • src/fragment/error.rs
  • tests/steps/fragment_steps.rs
  • tests/worlds/fragment.rs
  • src/fragment/fragmenter.rs
  • src/lib.rs

⚙️ CodeRabbit configuration file

**/*.rs: * Seek to keep the cognitive complexity of functions no more than 9.

  • 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 and docs must follow en-GB-oxendict (-ize / -yse / -our) 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.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
  • 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() in tests.
  • .expect() and .unwrap() are forbidden outside of tests. Errors must be propagated.
  • 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/
  • Files must not exceed 400 lines in length
    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
    • For testing of functionality depending upon environment variables, dependency injection and...

Files:

  • src/fragment/tests.rs
  • src/fragment/mod.rs
  • src/fragment/error.rs
  • tests/steps/fragment_steps.rs
  • tests/worlds/fragment.rs
  • src/fragment/fragmenter.rs
  • src/lib.rs
tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.rs: Use rstest fixtures for shared setup in tests
Replace duplicated tests with #[rstest(...)] parameterised cases
Prefer mockall for mocks/stubs in tests

Files:

  • tests/steps/fragment_steps.rs
  • tests/worlds/fragment.rs
🧬 Code graph analysis (5)
src/fragment/tests.rs (4)
src/fragment/fragmenter.rs (10)
  • new (26-28)
  • new (138-138)
  • new (161-167)
  • payload (146-146)
  • len (179-179)
  • is_fragmented (187-187)
  • message_id (171-171)
  • fragments (175-175)
  • header (142-142)
  • with_starting_id (32-37)
src/fragment/id.rs (1)
  • new (25-25)
src/fragment/header.rs (4)
  • new (35-45)
  • message_id (49-49)
  • is_last_fragment (57-57)
  • fragment_index (53-53)
src/fragment/index.rs (2)
  • new (30-30)
  • zero (34-34)
src/fragment/mod.rs (1)
src/fragment/fragmenter.rs (1)
  • header (142-142)
tests/steps/fragment_steps.rs (3)
src/fragment/fragmenter.rs (2)
  • len (179-179)
  • message_id (171-171)
src/fragment/header.rs (1)
  • message_id (49-49)
src/fragment/series.rs (1)
  • message_id (33-33)
tests/worlds/fragment.rs (3)
src/fragment/fragmenter.rs (7)
  • new (26-28)
  • new (138-138)
  • new (161-167)
  • len (179-179)
  • payload (146-146)
  • header (142-142)
  • message_id (171-171)
src/fragment/id.rs (1)
  • new (25-25)
src/fragment/header.rs (3)
  • new (35-45)
  • is_last_fragment (57-57)
  • message_id (49-49)
src/fragment/fragmenter.rs (1)
src/fragment/index.rs (1)
  • zero (34-34)
🪛 LanguageTool
docs/generic-message-fragmentation-and-re-assembly-design.md

[style] ~132-~132: Would you like to use the Oxford spelling “serializes”? The spelling ‘serialises’ is also correct.
Context: ...ree entry points: - fragment_message serialises any type implementing the Message tra...

(OXFORD_SPELLING_Z_NOT_S)


[uncategorized] ~143-~143: Use a comma before ‘so’ if it connects two independent clauses (unless they are closely connected and short).
Context: ...` overflow and returns an explicit error so protocols can downgrade to streaming or...

(COMMA_COMPOUND_SENTENCE_2)

🔍 Remote MCP Deepwiki

Additional Context for PR #395 Review

I've gathered relevant design and architectural context to supplement the PR review. Here's the key information:

Fragmentation Architecture Context

Design Goals and Requirements
The core requirements for message fragmentation include transparent inbound reassembly (router/handlers receive complete logical frames), transparent outbound fragmentation (payloads exceeding protocol-specific sizes are automatically fragmented), pluggable strategy for protocol-agnostic implementation, DoS protection with resource and time limits, and zero friction for non-fragmented messages

Core Architecture
The FragmentAdapter is implemented as a FrameProcessor middleware between raw I/O and the main router, handling splitting of large outbound frames and reassembling inbound fragments. State management for multiplexing uses a dashmap::DashMap for concurrent reassembly of multiple logical messages on the same connection, keyed by msg_id, providing lock-free reads and sharded writes

How Fragmenter Relates to the System

The Fragmenter acts as a FrameProcessor middleware sitting between raw I/O (transport layer) and message handling logic (router/handlers), transparently splitting large outbound logical messages into smaller physical frames and reassembling inbound fragments into complete logical messages. For outbound messages, when a handler returns a Response::Stream or asynchronous push is made, the FragmentAdapter automatically fragments large logical frames into smaller physical frames before writing to the socket, with application code remaining unaware

Related PR #393 Context

PR #393 introduced the FragmentMeta struct carrying decoded fragment header metadata (payload_len, total_message_len, is_final, msg_id, seq) and the FragmentStrategy trait defining protocol-specific rules for fragmentation, including max_fragment_payload, decode_header, and encode_header methods

FragmentStrategy Integration

The FragmentStrategy trait provides methods for determining maximum payload sizes, parsing fragment headers, and emitting fragment headers, while the FragmentAdapter is instantiated with a protocol-specific FragmentStrategy and uses decode_header for inbound reassembly and encode_header for outbound fragmentation

Key Review Points

  1. Scope Alignment: The PR introduces utility types (Fragmenter, FragmentBatch, FragmentFrame) for explicit message fragmentation, complementing the middleware FragmentAdapter that was introduced in PR #393 for transparent fragmentation/reassembly at the FrameProcessor layer.

  2. Code Duplication Issue: As noted in the PR comments, tests/worlds/fragment.rs contains duplicated fragment retrieval logic in assert_fragment_payload_len and assert_fragment_final_flag that should be extracted into a shared get_fragment_at helper.

  3. Backwards Compatibility: The Fragmenter API is opt-in and does not modify existing fragmentation logic, keeping existing code paths unaffected.

⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sourcery review
  • GitHub Check: Sourcery review
🔇 Additional comments (17)
docs/roadmap.md (1)

261-262: Fragmenter completion marker is accurate and correctly positioned.

The checkbox update to [x] appropriately reflects the completion of the Fragmenter implementation introduced in PR #395, including the public API (Fragmenter, FragmentBatch, FragmentFrame), unit tests, and documentation. The roadmap structure remains logically ordered, with Reassembler and full F&R integration tasks correctly left unchecked as future work.

tests/features/fragment.feature (1)

37-47: LGTM: Comprehensive Fragmenter scenario added.

The new scenario thoroughly exercises the Fragmenter API, validating fragment counts, payload sizes, final/non-final flags, and message ID assignment. The test steps are specific and align with the PR objectives.

CHANGELOG.md (1)

12-14: LGTM: Changelog entry is clear and accurate.

The entry accurately describes the new Fragmenter helper and its purpose for transport-level reassembly.

src/fragment/tests.rs (5)

1-3: LGTM: Imports added for new test functionality.

The imports for NonZeroUsize and bincode traits are necessary for the new Fragmenter tests.


84-103: LGTM: Comprehensive test for multi-fragment splitting.

The test validates fragment counts, payload correctness, and final/non-final flags across all fragments.


105-116: LGTM: Empty payload edge case covered.

The test correctly validates that an empty payload produces a single fragment marked as final.


118-140: LGTM: Message ID increment and dual API tested.

The test validates that the Fragmenter correctly increments message IDs across calls and exercises both fragment_message and fragment_bytes APIs.


142-155: LGTM: IntoIterator implementation tested.

The test validates that FragmentBatch correctly implements IntoIterator and yields all fragments in order.

src/lib.rs (1)

34-45: LGTM: Public API expanded with new fragmentation types.

The re-exports for FragmentBatch, FragmentFrame, FragmentationError, and Fragmenter correctly expose the new fragmentation utilities at the crate root, consistent with the PR objectives.

src/fragment/mod.rs (2)

9-9: LGTM: Fragmenter module added.

The new fragmenter module is correctly declared and integrated into the fragment module structure.


15-20: LGTM: Public re-exports extended for new fragmentation types.

The re-exports for FragmentationError, FragmentBatch, FragmentFrame, Fragmenter, and FragmentSeries correctly expose the new fragmentation utilities at the fragment module level.

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

41-49: Suppression is justified; no changes required.

The table uses aligned style (column separators padded to match content width), which is a specific formatting choice that may conflict with other table styles in the documentation. The MD060 suppression is correctly applied and warrants retention.

Run make markdownlint locally to confirm no other MD060 violations exist in the file.

docs/multi-packet-and-streaming-responses-design.md (1)

88-96: Clarify which rule violation requires suppression.

The table structure appears consistently formatted. However, the coding guidelines specify disabling MD013 for long lines in documentation, yet this suppression targets MD060 (table column style). The second column contains text exceeding 120 characters—triggering MD013, not necessarily MD060.

Verify with make markdownlint whether both rules are violated or only one. If line length is the concern, align the suppression with the documented guidance:

<!-- markdownlint-disable-next-line MD013 -->

rather than MD060. If both rules require suppression, document why.

src/fragment/error.rs (1)

7-8: Define dedicated outbound FragmentationError

Keep this separation between inbound FragmentError and outbound FragmentationError. The two explicit variants (Encode and IndexOverflow) are narrowly scoped, error messages match the inbound overflow wording, and the From mapping keeps call‑sites clean. No changes required.

Also applies to: 44-52

tests/steps/fragment_steps.rs (1)

44-75: Wire fragmenter steps cleanly through FragmentWorld

Keep these steps as thin delegates to FragmentWorld. Parameter types match the underlying helpers, the final/non‑final steps correctly re‑use the same assertion with a boolean flag, and the message‑id check uses the explicit world assertion. No changes required.

tests/worlds/fragment.rs (1)

7-8: Centralise fragment assertions via get_fragment_at

Keep configure_fragmenter, fragment_payload, batch, and get_fragment_at structured as they are. The world now initialises a fragmenter with a non‑zero cap, records the last batch, and uses a single lookup helper for both payload‑length and final‑flag assertions. This removes the duplication highlighted in the PR notes while preserving clear panic messages in test‑only code.

Also applies to: 22-28, 37-59, 98-109, 197-241

src/fragment/fragmenter.rs (1)

16-89: Keep Fragmenter/FragmentFrame/FragmentBatch API and invariants as-is

Retain the current API surface:

  • Use NonZeroUsize for max_fragment_size and panic‑free handling of empty payloads via a single zero‑length fragment.
  • Generate message identifiers atomically and expose next_message_id for callers that need to inspect IDs.
  • Enforce FragmentIndex overflow via checked_increment, mapping directly to FragmentationError::IndexOverflow.
  • Keep FragmentFrame and FragmentBatch as lightweight wrappers with #[must_use] accessors and IntoIterator for ergonomic consumption.

The design matches the documented behaviour, keeps invariants explicit, and introduces no unnecessary allocations or panics in library code.

Also applies to: 128-199

Comment thread docs/generic-message-fragmentation-and-re-assembly-design.md
Comment thread docs/users-guide.md
Comment thread src/fragment/fragmenter.rs
Comment thread src/fragment/fragmenter.rs
Refactor fragment_bytes method to accept any type implementing AsRef<[u8]> instead of a byte slice. This enables greater flexibility in the payload argument without changing internal logic.

Additional enhancements:
- Refined next_message_id to safely handle overflow with fetch_update and documented its panic behavior.
- Updated documentation in users-guide.md to warn users about error handling when fragmenting.
- Removed is_empty method from FragmentBatch as batches are guaranteed non-empty.
- Added tests to validate explicit message IDs and changed tests and examples to leverage payload argument flexibility.

These changes improve API robustness, clarity, and usability.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
@leynos
Copy link
Copy Markdown
Owner Author

leynos commented Nov 23, 2025

@coderabbitai Have the following now been resolved?

  • Fragmenter::next_message_id() blindly increments an AtomicU64 without handling wrap‑around; consider either checking for and surfacing overflow or explicitly documenting that MessageId rollover is unsupported/undefined once u64::MAX is reached.
  • Given the invariant enforced in FragmentBatch::new that fragments is never empty, FragmentBatch::is_empty() is effectively unreachable; you might either remove this method or tighten the invariant (e.g., make the field NonEmpty) to reflect that callers can always assume at least one fragment.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Nov 23, 2025

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Read the fragmenter.rs file to check the implementation
cat src/fragment/fragmenter.rs

Length of output: 7007


@leynos: Yes, both issues have been resolved:

Issue 1: next_message_id() overflow handling
Resolved. The method now uses checked_add(1) within fetch_update, which returns None on overflow. When overflow occurs, the method panics with the message "message id counter exhausted". This behaviour is explicitly documented in the doc comment:

/// # Panics
///
/// Panics if the identifier counter reaches `u64::MAX` and overflows. Callers
/// should provisionally treat `MessageId` values as unique for the lifetime of
/// the fragmenter.

Issue 2: FragmentBatch::is_empty() unreachability
Resolved. The is_empty() method has been removed entirely. The len() method now includes an explicit clippy allow that acknowledges the invariant:

#[allow(
    clippy::len_without_is_empty,
    reason = "batches are guaranteed non-empty"
)]

The non-empty invariant is enforced via debug_assert!(!fragments.is_empty(), ...) in the private new() constructor.

Replaced inline vector in fragment_bytes call with a named variable `payload` to improve code clarity in the users guide example.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
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: 1

♻️ Duplicate comments (4)
src/fragment/tests.rs (1)

118-170: Retain ID-progression, iterator, and explicit-ID coverage

Keep DummyMessage and the tests fragmenter_fragments_messages_and_increments_ids, fragment_batch_into_iterator_yields_all_fragments, and fragmenter_respects_explicit_message_ids. Together they validate:

  • Shared ID progression across fragment_message and fragment_bytes from a known starting MessageId.
  • FragmentBatch’s IntoIterator implementation yielding all fragments in order.
  • fragment_with_id honouring the caller-supplied MessageId without advancing the internal counter, then resuming from the configured starting id on the next auto-assigned batch.

This set resolves the earlier request for a focused fragment_with_id test while tightening overall Fragmenter behaviour coverage.

tests/worlds/fragment.rs (1)

37-58: Keep centralised batch/fragment helpers and new assertions

Keep configure_fragmenter, fragment_payload, batch, and get_fragment_at; they provide a clear Fragmenter workflow in the world state, enforce non-zero caps, and centralise both “no payload fragmented yet” and “fragment {index} missing” failure modes. The new assertions (assert_fragment_count, assert_fragment_payload_len, assert_fragment_final_flag, assert_message_id) build on these helpers to produce precise diagnostics while eliminating the earlier duplicated fragment-access logic.

Also applies to: 98-109, 197-241

src/fragment/fragmenter.rs (2)

43-59: Keep the documented, non-wrapping MessageId generation

Keep this next_message_id implementation and documentation. The fetch_update + checked_add logic prevents silent wraparound, panics with a clear “message id counter exhausted” message on u64::MAX, and matches both the documented behaviour and the tests that rely on with_starting_id yielding the starting MessageId on the first allocation.


105-139: Eliminate potential usize overflow in fragment boundary calculation

Replace the plain offset + max addition with a saturating addition before clamping to total. With an unconstrained NonZeroUsize max_fragment_size, extreme configurations (large max and large payload) can cause offset + max to overflow usize, which either wraps or panics depending on build configuration.

Apply this change in build_fragments:

-        while offset < total {
-            let end = (offset + max).min(total);
+        while offset < total {
+            let end = offset.saturating_add(max).min(total);
             let is_last = end == total;
             fragments.push(FragmentFrame::new(
                 FragmentHeader::new(message_id, index, is_last),
                 payload[offset..end].to_vec(),
             ));

This preserves the intended behaviour for normal sizes while removing the overflow risk.

#!/bin/bash
# Verify that fragment boundary computation uses saturating_add after patching.
rg -n 'offset\.saturating_add\(max\)\.min\(total\)' src/fragment/fragmenter.rs
📜 Review details

Configuration used: CodeRabbit UI

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56de7ee and 71862b5.

📒 Files selected for processing (4)
  • docs/users-guide.md (1 hunks)
  • src/fragment/fragmenter.rs (1 hunks)
  • src/fragment/tests.rs (2 hunks)
  • tests/worlds/fragment.rs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
docs/**/*.md

📄 CodeRabbit inference engine (docs/message-versioning.md)

Document examples showing how to deprecate old message versions gracefully

When long lines are warranted in documentation, disable markdownlint rule MD013 inline using the comment:

docs/**/*.md: Use docs/ as the knowledge base and source of truth for requirements, dependencies, and architectural decisions
Proactively update docs/ when decisions, requirements, libraries, or architecture change to keep documentation accurate
Documentation must use en-GB-oxendict spelling and grammar (LICENSE name unchanged)

Follow markdownlint recommendations

Files:

  • docs/users-guide.md
docs/**

📄 CodeRabbit inference engine (docs/wireframe-1-0-detailed-development-roadmap.md)

docs/**: Document async-stream as the canonical way to create streams imperatively
Write comprehensive user guides for Duplex Messaging & Pushes, Streaming Responses, and Message Fragmentation with runnable examples

Files:

  • docs/users-guide.md
**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

**/*.md: Validate Markdown with make markdownlint
Run make fmt after documentation changes to format Markdown and fix table markup
Validate Mermaid diagrams in Markdown using make nixie
Wrap Markdown paragraphs and bullet points at 80 columns
Wrap code blocks in Markdown at 120 columns
Do not wrap tables and headings in Markdown
Use dashes (-) for list bullets in Markdown
Use GitHub-flavoured Markdown footnotes ([^1]) for references and footnotes

Files:

  • docs/users-guide.md

⚙️ CodeRabbit configuration file

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

  • Use en-GB-oxendict (-ize / -yse / -our) spelling and grammar
  • Headings must not be wrapped.
  • Documents must start with a level 1 heading
  • Headings must correctly increase or decrease by no more than one level at a time
  • Use GitHub-flavoured Markdown style for footnotes and endnotes.
  • Numbered footnotes must be numbered by order of appearance in the document.

Files:

  • docs/users-guide.md
docs/**/*.{md,rs}

📄 CodeRabbit inference engine (docs/documentation-style-guide.md)

docs/**/*.{md,rs}: Use British English (en-GB-oxendict) spelling in documentation prose
Keep US spelling when it appears in API identifiers (e.g., color)
The word “outwith” is acceptable in documentation
Use the Oxford comma where it aids comprehension
Treat company names as collective nouns (e.g., “Lille Industries are…”)
Write headings in sentence case
Use Markdown headings (#, ##, ###, …) in order without skipping levels
Use standard Markdown syntax for code blocks and lists
Always provide a language identifier for fenced code blocks; use plaintext for non-code text
Use - as the first-level bullet; renumber ordered lists when items change
Prefer inline links [text](url) or angle-bracket autolinks <url>
Ensure blank lines before and after bulleted lists and fenced code blocks
Ensure Markdown tables include a delimiter line below the header row
Expand uncommon acronyms on first use (e.g., Continuous Integration (CI))
Wrap paragraphs at 80 columns
Wrap code at 120 columns
Do not wrap tables
Use footnotes referenced with [^label]
Include Mermaid diagrams where they add clarity
When embedding images, use Markdown ![alt text](path/to/image) with brief, descriptive alt text
Add a short descriptive sentence before each Mermaid diagram for screen readers

Files:

  • docs/users-guide.md
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Name things precisely; use clear, descriptive names; booleans should use is/has/should prefixes
Use consistent en-GB-oxendict spelling and grammar in comments (except external API references)
Disallow Clippy warnings; fix warnings in code rather than silencing
Extract helpers when functions are too long; maintain separation of concerns and CQRS
Group many parameters into meaningful structs when a function has too many parameters
When returning a large error, consider using Arc to reduce data returned
Every Rust module must begin with a module-level (//! ) comment explaining its purpose and utility
Document public APIs with Rustdoc comments (///) to enable cargo doc generation
Prefer immutable data; avoid unnecessary mut bindings
Use Result for error handling instead of panicking where feasible
Avoid unsafe code unless absolutely necessary and document any usage clearly
Place function attributes after doc comments
Do not use return in single-line functions
Use predicate functions for conditional criteria with more than two branches
Do not silence lints except as a last resort; suppressions must be tightly scoped and include a clear reason
Prefer #[expect] over #[allow] for lints
Prefer .expect() over .unwrap()
Use concat!() to combine long string literals rather than escaping newlines with a backslash
Prefer single-line versions of trivial functions when appropriate (e.g., pub fn new(id: u64) -> Self { Self(id) })
Use NewTypes to model domain values; consider newt-hype, tuple structs, and the-newtype as appropriate; add shims like From<&str>/AsRef; implement AsRef for path wrappers and provide into_inner()/to_path_buf()
Keep file size manageable: no single code file longer than 400 lines; split long switches/dispatch tables by feature; move large test data to external files

Files:

  • src/fragment/tests.rs
  • tests/worlds/fragment.rs
  • src/fragment/fragmenter.rs

⚙️ CodeRabbit configuration file

**/*.rs: * Seek to keep the cognitive complexity of functions no more than 9.

  • 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 and docs must follow en-GB-oxendict (-ize / -yse / -our) 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.
  • Where code is only used by specific features, it must be conditionally compiled or a conditional expectation for unused_code applied.
  • 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() in tests.
  • .expect() and .unwrap() are forbidden outside of tests. Errors must be propagated.
  • 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/
  • Files must not exceed 400 lines in length
    • Large modules must be decomposed
    • Long match statements or dispatch tables should be decomposed by domain and collocated with targets
    • Large blocks of inline data (e.g., test fixtures, constants or templates) must be moved to external files and inlined at compile-time or loaded at run-time.
  • Environment access (env::set_var and env::remove_var) are always unsafe in Rust 2024 and MUST be marked as such
    • For testing of functionality depending upon environment variables, dependency injection and...

Files:

  • src/fragment/tests.rs
  • tests/worlds/fragment.rs
  • src/fragment/fragmenter.rs
tests/**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

tests/**/*.rs: Use rstest fixtures for shared setup in tests
Replace duplicated tests with #[rstest(...)] parameterised cases
Prefer mockall for mocks/stubs in tests

Files:

  • tests/worlds/fragment.rs
🧬 Code graph analysis (2)
tests/worlds/fragment.rs (5)
src/fragment/fragmenter.rs (7)
  • new (26-28)
  • new (153-153)
  • new (176-182)
  • len (198-198)
  • payload (161-161)
  • header (157-157)
  • message_id (186-186)
src/fragment/id.rs (1)
  • new (25-25)
src/fragment/header.rs (3)
  • new (35-45)
  • is_last_fragment (57-57)
  • message_id (49-49)
src/fragment/index.rs (1)
  • new (30-30)
src/fragment/series.rs (2)
  • new (23-29)
  • message_id (33-33)
src/fragment/fragmenter.rs (1)
src/fragment/index.rs (1)
  • zero (34-34)
⏰ Context from checks skipped due to timeout of 120000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Sourcery review
  • GitHub Check: build-test
🔇 Additional comments (2)
docs/users-guide.md (1)

151-177: Align Fragmenter docs and example with the public API

Keep this block: it now names FragmentBatch and FragmentFrame, explains that FragmentationError reports encode failures and index overflows, and illustrates correct usage of Fragmenter::new and fragment_bytes with a payload slice and realistic tracing fields. This aligns the user guide with the current API and resolves the earlier fallibility and signature concerns.

src/fragment/tests.rs (1)

84-116: Keep these Fragmenter edge-case tests for payload splitting

Keep fragmenter_splits_payload_into_multiple_frames and fragmenter_handles_empty_payload; they exercise core invariants: correct chunking at the configured cap, is_fragmented semantics, MessageId::new(0) from Fragmenter::new, and the empty-payload case producing a single final fragment at index zero.

Comment thread src/fragment/fragmenter.rs Outdated
…ation

Add outbound fragmentation scenarios by chunking payloads using the Fragmenter helper and inspecting FragmentBatch states. Enhance documentation and assertions to verify ordering, completion detection, and error handling for both inbound and outbound fragmentation in FragmentWorld behavioural tests.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
…lice instead of vec

In docs/users-guide.md, replaced `vec![0_u8; 1400]` with fixed-size array `[0_u8; 1400]` for slice compatibility.

In src/fragment/fragmenter.rs, changed Clippy lint attribute from `#[allow(clippy::len_without_is_empty)]` to `#[expect(clippy::len_without_is_empty)]` to better express intent about non-empty batches.

Co-authored-by: terragon-labs[bot] <terragon-labs[bot]@users.noreply.github.com>
@leynos leynos merged commit 450c0df into main Nov 24, 2025
6 checks passed
@leynos leynos deleted the terragon/implement-fragmentation-reassembly-fowx16 branch November 24, 2025 12:18
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