Skip to content

docs: reflect active chat lane eviction fix - #410

Merged
jlucaso1 merged 4 commits into
mainfrom
claude/nifty-bohr-lxvyqb
Jul 16, 2026
Merged

jlucaso1 merged 4 commits into
mainfrom
claude/nifty-bohr-lxvyqb

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Summary

Updates concepts/architecture.mdx to reflect whatsapp-rust#1045, "fix(message): preserve active chat lanes."

  • Per-Chat Lanes: the queue element type changed from Arc<OwnedNodeRef> to QueuedChatMessage { node, lane_liveness }. Added a note explaining that each queued message now carries a clone of the lane's enqueue_lock, and the cache's evict_guard refuses to evict a lane while any message is still in flight — closing a race where a lane could be capacity-evicted right after its worker dequeued a message, letting a later stanza for the same chat spawn a second worker.
  • Sender-key chain lock (group receive): this section already described the exact double-worker race that PR #1045 fixes as the reason the chain lock exists. Added a note clarifying that the specific chat-lane-eviction trigger is now closed, and the chain lock remains as defense-in-depth for any other path.

No other docs changes — this PR fixes a correctness bug in internal message-dispatch state and doesn't change any public API or CHANGELOG content.

Test plan

  • Read the full merged diff of whatsapp-rust#1045 (src/client.rs, src/client/lifecycle.rs, src/handlers/message.rs, src/client/tests.rs)
  • Cross-checked against the existing docs section that already described this exact race condition
  • Docs build/preview (not run in this environment)

Generated by Claude Code


Summary by cubic

Updates concepts/architecture.mdx and api/bot.mdx to document the v0.6 eviction guard that preserves active per‑chat lanes while a message is in flight, and corrects that per‑chat queues use async_channel::unbounded.
Aligns both pages to state chat_lanes_capacity is a soft cap on the number of cached lanes (enqueue lock + unbounded queue), explains QueuedChatMessage { node, lane_liveness } powering the guard, and notes the sender‑key chain lock’s prior lane‑eviction trigger is now closed (lock remains defense‑in‑depth).

Written for commit b48d555. Summary will update on new commits.

Summary by CodeRabbit

  • Documentation
    • Updated the per-chat lane architecture documentation to describe unbounded lane queues and bounded lane-cache behavior.
    • Documented the default lane-cache capacity of 5,000 and safeguards that prevent active lanes from being evicted.
    • Clarified protections against duplicate workers and out-of-order processing.
    • Updated sender-key chain lock guidance to reflect the strengthened concurrency safeguards.

Document that per-chat lanes now survive capacity eviction while a
message is in flight (evict_guard + QueuedChatMessage.lane_liveness),
and note that this closes the specific chat-lane-eviction trigger
previously described for the sender-key chain lock section.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The architecture documentation now describes unbounded per-chat channels, bounded lane-cache backpressure with a 5,000-lane default, and active-lane eviction protection. It also documents the guard’s relationship to sender-key chain locking.

Changes

Per-Chat Lane Design

Layer / File(s) Summary
Lane backpressure and concurrency safeguards
concepts/architecture.mdx
The per-chat lane design uses unbounded channels with bounded cache capacity and an active-lane eviction guard; the sender-key section identifies the guard as preventing the documented race while retaining chain locking as defense-in-depth.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Possibly related issues

  • oxidezap/whatsapp-rust#1039 — The documentation describes the active-lane eviction guard proposed to prevent duplicate workers and preserve per-chat ordering.

Poem

A rabbit hops through lanes so wide,
With queued-up messages side by side.
Five thousand paths stay neatly spun,
Active workers guard each one.
Chain locks watch the moonlit night—
No duplicate worker takes flight.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main documentation change about the active chat lane eviction fix.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@mintlify

mintlify Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
whatsapp-rust 🟢 Ready View Preview Jul 16, 2026, 5:02 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@mintlify

mintlify Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated (UTC)
whatsapp-rust 🟡 Building Jul 16, 2026, 5:01 PM

💡 Tip: Enable Workflows to automatically generate PRs for you.

@greptile-apps

greptile-apps Bot commented Jul 16, 2026

Copy link
Copy Markdown

Greptile Summary

This PR updates documentation in concepts/architecture.mdx and api/bot.mdx to reflect the merged fix in whatsapp-rust#1045 that prevents active per-chat lanes from being capacity-evicted while a message is still in flight.

  • Per-Chat Lanes (concepts/architecture.mdx): replaces the bounded-channel (500-message cap) description with unbounded queues, adds a <Note> explaining the QueuedChatMessage { node, lane_liveness } eviction guard and the Arc::strong_count check that keeps active lanes in the cache.
  • Sender-key chain lock (concepts/architecture.mdx): adds a <Note> clarifying that the specific double-worker trigger (lane evicted mid-drain) is now closed by the eviction guard, and that the chain lock stays as defense-in-depth.
  • chat_lanes_capacity setting (api/bot.mdx): expands the description to convey the soft-cap semantics and the cross-link to the architecture section.

Confidence Score: 5/5

Pure documentation update with no code changes; all technical claims are internally consistent and cross-references resolve correctly.

Both files only update prose and MDX notes to describe an already-merged fix. The eviction-guard mechanism documented (Arc::strong_count check, QueuedChatMessage { node, lane_liveness }) is internally consistent across the two files, the bounded→unbounded queue change is accurately reflected in both the code comment block and the settings table, and the anchor links (#per-chat-lanes) match the section headings present in the file.

No files require special attention.

Important Files Changed

Filename Overview
concepts/architecture.mdx Accurately updates Per-Chat Lanes and Sender-key chain lock sections to reflect the v0.6 eviction guard; new Notes are technically coherent and cross-references resolve to valid anchors.
api/bot.mdx Expands chat_lanes_capacity table description with soft-cap semantics and a cross-link to the architecture page; consistent with the architecture.mdx changes.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant S as Stanza (inbound)
    participant C as Client / chat_lanes cache
    participant W as Lane Worker
    participant EG as evict_guard

    Note over C: chat_lanes cache (soft cap 5,000)

    S->>C: look up ChatLane for chat JID
    alt Lane exists
        C-->>S: return cached ChatLane
    else Lane missing (capacity eviction candidate)
        C->>EG: attempt eviction of idle lane
        EG-->>C: "allowed (Arc::strong_count == 1)"
        C->>C: create new ChatLane
        C-->>S: return new ChatLane
    end

    S->>C: "enqueue QueuedChatMessage {node, lane_liveness}"
    Note over S,C: lane_liveness = clone of enqueue_lock (strong_count 2+)

    W->>C: dequeue message
    Note over W: worker holds lane_liveness clone

    C->>EG: attempt capacity eviction of active lane
    EG->>C: "Arc::strong_count(&enqueue_lock) > 1?"
    C-->>EG: YES — in-flight message holds clone
    EG-->>C: BLOCKED — lane survives eviction

    W->>W: process message
    W->>W: drop lane_liveness (strong_count back to 1)
    Note over W: lane now idle, evictable as before
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant S as Stanza (inbound)
    participant C as Client / chat_lanes cache
    participant W as Lane Worker
    participant EG as evict_guard

    Note over C: chat_lanes cache (soft cap 5,000)

    S->>C: look up ChatLane for chat JID
    alt Lane exists
        C-->>S: return cached ChatLane
    else Lane missing (capacity eviction candidate)
        C->>EG: attempt eviction of idle lane
        EG-->>C: "allowed (Arc::strong_count == 1)"
        C->>C: create new ChatLane
        C-->>S: return new ChatLane
    end

    S->>C: "enqueue QueuedChatMessage {node, lane_liveness}"
    Note over S,C: lane_liveness = clone of enqueue_lock (strong_count 2+)

    W->>C: dequeue message
    Note over W: worker holds lane_liveness clone

    C->>EG: attempt capacity eviction of active lane
    EG->>C: "Arc::strong_count(&enqueue_lock) > 1?"
    C-->>EG: YES — in-flight message holds clone
    EG-->>C: BLOCKED — lane survives eviction

    W->>W: process message
    W->>W: drop lane_liveness (strong_count back to 1)
    Note over W: lane now idle, evictable as before
Loading

Reviews (4): Last reviewed commit: "docs: clarify chat_lanes_capacity is a s..." | Re-trigger Greptile

greptile-apps[bot]
greptile-apps Bot previously approved these changes Jul 16, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a5b3c8263e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread concepts/architecture.mdx Outdated
pub(crate) chat_lanes: Cache<Jid, ChatLane>,
// ChatLane { enqueue_lock, queue_tx }
// Each queue: async_channel::bounded::<Arc<OwnedNodeRef>>(500)
// Each queue: async_channel::bounded::<QueuedChatMessage>(500)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Document the chat lane queue as unbounded

In the referenced #1045 diff, create_chat_lane constructs this channel with async_channel::unbounded::<QueuedChatMessage>(), so the updated snippet still advertises a 500-message bounded queue and per-chat backpressure that do not exist. In backlog-heavy chats this misleads readers into expecting TrySendError::Full/cancelled acks and a per-lane memory cap, while the actual capacity limit only applies to the lane cache; please align this snippet and the surrounding capacity sentence with the Rust code.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch — confirmed against handlers/message.rs in whatsapp-rust: the channel is async_channel::unbounded, and the real capacity limit (chat_lanes_capacity, default 5,000 per cache_config.rs) bounds the number of cached lanes, not messages per lane. Fixed in 4e6c7df.


Generated by Claude Code

The queue element type comment was updated in the previous commit but
still claimed a bounded(500) channel with per-lane backpressure. The
actual code (handlers/message.rs in whatsapp-rust) uses
async_channel::unbounded. The real capacity limit is on the number of
cached lanes (chat_lanes_capacity, default 5,000 per cache_config.rs),
not on messages per lane.

Addresses review feedback from @chatgpt-codex-connector on #410.
@greptile-apps
greptile-apps Bot dismissed their stale review July 16, 2026 17:15

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

greptile-apps[bot]
greptile-apps Bot previously approved these changes Jul 16, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@concepts/architecture.mdx`:
- Line 536: Update the chat_lanes capacity explanation in the architecture
documentation to state that protected active lanes may temporarily exceed
chat_lanes_capacity, while only evictable idle lanes are removed. Also revise
the corresponding api/bot.mdx configuration description to define
chat_lanes_capacity as the cached-lane capacity, not combined
enqueue-lock/message-queue capacity.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 02a488bf-8fcb-4402-9d91-9ffb01b5d58c

📥 Commits

Reviewing files that changed from the base of the PR and between fa255ce and 4e6c7df.

📒 Files selected for processing (1)
  • concepts/architecture.mdx

Comment thread concepts/architecture.mdx Outdated
Addresses CodeRabbit review feedback on #410: this file's description of
chat_lanes_capacity conflicted with concepts/architecture.mdx's updated
wording. Aligns both to describe it as the number of cached per-chat
lanes (each pairing an enqueue lock with an unbounded queue), and notes
it's a soft cap like the other coordination caches — an active lane is
never evicted, so the map can briefly exceed capacity when every cached
lane is in use.
@greptile-apps
greptile-apps Bot dismissed their stale review July 16, 2026 17:24

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

greptile-apps[bot]
greptile-apps Bot previously approved these changes Jul 16, 2026
Addresses CodeRabbit review feedback on #410: a lane with an in-flight
message is protected from eviction, so the chat_lanes cache can briefly
exceed chat_lanes_capacity when every cached lane happens to be active
at once, rather than evicting a live lane. Mirrors the phrasing already
used for session_locks_capacity/group_distribution_locks_capacity.
@greptile-apps
greptile-apps Bot dismissed their stale review July 16, 2026 17:27

Dismissed because a newer commit was pushed; Greptile will re-review the current head.

@jlucaso1
jlucaso1 merged commit 1d5322b into main Jul 16, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant