Skip to content

perf(recv): hold the per-sender session lock only around Signal decrypt - #983

Merged
jlucaso1 merged 6 commits into
mainfrom
claude/perf-audit-parallelization-v42g7v
Jul 5, 2026
Merged

perf(recv): hold the per-sender session lock only around Signal decrypt#983
jlucaso1 merged 6 commits into
mainfrom
claude/perf-audit-parallelization-v42g7v

Conversation

@jlucaso1

@jlucaso1 jlucaso1 commented Jul 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Second of the recv post-decrypt dispatch series (follow-up to #981). This one narrows the per-sender session lock so it covers only the Signal ratchet crypto, not the downstream plaintext handling and app dispatch.

process_session_enc_batch held the per-sender ratchet guard (session_lock_for(signal_address)) across the entire batch — including handle_decrypted_plaintext, which does protobuf decode, SKDM / app-state-key / LID-migration / PDO / history-sync handling, and the app dispatch. None of that touches the Signal session ratchet — only message_decrypt does — so the lock only needs to cover the crypto.

Change

  • Buffer each decrypted plaintext into a DeferredPlaintext during the locked decrypt loop, release the guard, then run handle_decrypted_plaintext over the drained buffer, unlocked.
  • The rare PN→LID migration retry helper buffers its plaintext into the same queue and returns a small MigrationDecryptResult enum, so multi-payload dispatch order stays uniform. This also collapses four verbose outcome-merge call sites into a match.

A concurrent stanza from the same sender device — e.g. the same participant across two group chats, or the detached LID-migration task, both of which contend on session_lock_for(signal_address) — can now start decrypting while this one dispatches.

Motivation

This matches whatsmeow, which holds the per-sender session lock only around the libsignal decrypt call and handles the decrypted message unlocked. Holding it across dispatch serializes same-sender cross-chat work behind unrelated downstream I/O.

Correctness

  • Delivery order is unchanged. Per-chat in-order delivery is owned by the serial chat-lane worker (handlers/message.rs), which processes one stanza at a time through full dispatch — not by this guard. Releasing the guard earlier cannot reorder delivery.
  • SKDM still precedes group decrypt. The buffer drains before the function returns, so a pkmsg's sender-key distribution is applied before PASS 2's skmsg decrypt reads that sender key.
  • Ratchet stays serialized. message_decrypt (the only session-ratchet mutation) still runs under the guard; handle_decrypted_plaintext only touches sender-key / app-state stores + dispatch, and is already invoked lock-free on the group, newsletter, and PDO paths today.
  • Outcome flags (decrypted / duplicate / dispatched / skdm_only / plaintext_failed / had_failure) are all finalized before the function returns, so the PASS 2 gate and the ack fallbacks are unaffected.

Testing

  • cargo test -p whatsapp-rust --lib — 933 passed, 0 failed (incl. the message::tests decrypt-path suite), deterministic across runs.
  • cargo clippy -p whatsapp-rust --tests — clean.
  • CI green: E2E Tests, wasm32 release, Build & Test, Build & Lint (all features), Test Stable (no-simd), Clippy, Format, Binary Size (−1.5 KiB), and the CodSpeed benchmarks. No new dependencies.

Notes

  • A reviewer raised a durability concern: dropping the guard lets a same-sender/different-chat stanza reach the stanza-end whole-cache flush before this message commits its pending-inbound row, so a crash in that window could persist the ratchet advance without a durable row. This is a pre-existing property, not introduced here — the live-path flush already persists any uncommitted stanza's ratchet via cross-sender concurrency (permit=N, no cross-sender lock), so this change only marginally widens the racing set, and on the session path it touches that is almost entirely SKDM-only decrypts (no durable row, acked by design) or already-serialized 1:1 chats (chat == sender). A proper fix — a live-path row-before-flush barrier, like the offline drain's commit-batcher — is a separate follow-up.

Generated by Claude Code

process_session_enc_batch held the per-sender ratchet lock across the whole
batch, including handle_decrypted_plaintext (protobuf decode, SKDM/app-state/
LID/PDO/history handling, and app dispatch). None of that touches the Signal
session ratchet — only message_decrypt does — so the lock only needs to cover
the crypto.

Buffer each decrypted plaintext during the locked decrypt loop, release the
guard, then run handle_decrypted_plaintext unlocked. A concurrent stanza from
the same sender (e.g. the same device across two group chats, or the detached
LID-migration task) can now start decrypting while this one dispatches.

This matches whatsmeow, which holds the per-sender lock only around the
libsignal decrypt. Correctness is preserved:
- Per-chat delivery order is owned by the serial chat-lane worker, not this
  guard, so releasing it early cannot reorder delivery.
- The buffer drains before the function returns, so a pkmsg's SKDM is still
  applied before PASS 2's group (skmsg) decrypt reads the sender key.
- The PN->LID migration retry helper now buffers its plaintext too and returns
  a small result enum, keeping multi-payload dispatch order uniform and
  collapsing the four verbose outcome-merge call sites into a match.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116cfRpumbEv3H4qUNmtNk4
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

PN→LID migration decrypt handling now returns a three-state result, buffers decrypted plaintext during batch processing, and processes deferred plaintext after releasing the session lock.

Changes

Migration decrypt result and deferred dispatch

Layer / File(s) Summary
Result and deferred payload types
src/message.rs
Replaced MigrationDecryptOutcome with MigrationDecryptResult and added DeferredPlaintext for buffered decrypted data.
Deferred buffering in session batch processing
src/message/receive.rs
process_session_enc_batch now buffers successful decrypts, and the UntrustedIdentity, SessionNotFound, BadMac/InvalidMessage, and InvalidPreKeyId retry branches match on MigrationDecryptResult.
Post-lock plaintext handling
src/message/receive.rs
Deferred plaintext is drained after session_guard is dropped, and plaintext handling or failure handling runs outside the lock.
Migration helper contract
src/message/receive.rs
try_pn_to_lid_migration_decrypt now accepts a deferred buffer, returns disposition-only results, and buffers plaintext on successful migration decrypt.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested labels: performance

Suggested reviewers: cubic-dev-ai

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: narrowing the per-sender session lock around Signal decrypt.
Description check ✅ Passed The description is directly related to the code changes and explains the lock-scope refactor and migration retry updates.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/perf-audit-parallelization-v42g7v

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.

@greptile-apps

greptile-apps Bot commented Jul 4, 2026

Copy link
Copy Markdown

Greptile Summary

This PR narrows the per-sender session lock (session_lock_for) to cover only the Signal ratchet decryption, releasing it before the downstream plaintext handling (handle_decrypted_plaintext). A DeferredPlaintext buffer collects successful decrypts during the locked loop; the buffer is drained unlocked immediately after, preserving SKDM-before-PASS-2 ordering and per-chat delivery order (which is owned by the serial chat-lane worker, not this guard).

  • Lock narrowing: DeferredPlaintext buffers successful decrypts during the locked loop; drop(session_guard) precedes the drain, letting a concurrent same-sender stanza start decrypting while this one dispatches.
  • MigrationDecryptResult enum: replaces the five-field MigrationDecryptOutcome struct, collapsing four verbose flag-merge call sites into match arms and pushing migration-path plaintexts into the shared deferred buffer.
  • handle_decrypted_plaintext signature: changed from self: Arc<Self> (consuming a clone) to self: &Arc<Self>, eliminating unnecessary Arc clones at all four call sites.
  • Benchmark: adds an ignored bench_session_decrypt_throughput test to measure steady-state msg-type decrypt throughput with optional valgrind support.

Confidence Score: 5/5

Safe to merge — the change correctly narrows a mutex scope without altering delivery ordering, flag semantics, or the SKDM-before-PASS-2 invariant, and 933 tests confirm this.

The deferred buffer pattern is mechanically straightforward: all outcome.* flags are finalized before the function returns, the drain happens before return outcome (so SKDM precedes PASS 2 group decrypt), and per-chat ordering is owned by the chat-lane worker rather than this guard. The MigrationDecryptResult enum maps cleanly to the old MigrationDecryptOutcome flag combinations, and the four call-site match blocks cover every old code path with no gaps. The handle_decrypted_plaintext receiver change from Arc<Self> to &Arc<Self> is a straight cleanup. All 933 existing tests pass, and CI is green across the board.

No files require special attention.

Important Files Changed

Filename Overview
src/message/receive.rs Core change: decrypt loop now pushes to deferred instead of immediately calling handle_decrypted_plaintext; drop(session_guard) precedes the drain; try_pn_to_lid_migration_decrypt now takes &mut Vec<DeferredPlaintext> and returns MigrationDecryptResult; handle_decrypted_plaintext receiver changed to &Arc<Self>. All flag-merge call sites simplified to match. Logic is correct and flag semantics preserved.
src/message.rs Replaces five-field MigrationDecryptOutcome struct with focused MigrationDecryptResult enum; adds DeferredPlaintext struct. Both types are clearly documented and tightly scoped to their purpose.
src/message/tests.rs Removes .clone() calls on handle_decrypted_plaintext call sites (matching new &Arc<Self> receiver); adds an ignored bench_session_decrypt_throughput benchmark with warmup phase, steady-state timing, and Linux-specific memory stats via /proc/self/status.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant Caller
    participant process_session_enc_batch
    participant session_guard as session_guard (ratchet lock)
    participant message_decrypt
    participant deferred as deferred buffer
    participant handle_decrypted_plaintext

    Caller->>process_session_enc_batch: payloads, info, sender_jid
    process_session_enc_batch->>session_guard: lock_arc() — acquire
    loop for each payload
        process_session_enc_batch->>message_decrypt: decrypt (ratchet advances)
        message_decrypt-->>process_session_enc_batch: Ok(plaintext)
        process_session_enc_batch->>deferred: push(DeferredPlaintext)
        Note over process_session_enc_batch: outcome.decrypted = true
    end
    process_session_enc_batch->>session_guard: drop() — RELEASE LOCK
    Note over session_guard: concurrent same-sender stanza can now acquire and decrypt
    loop drain deferred
        process_session_enc_batch->>handle_decrypted_plaintext: enc_type, plaintext, padding_version
        handle_decrypted_plaintext-->>process_session_enc_batch: PlaintextHandleOutcome
        Note over process_session_enc_batch: update dispatched / skdm_only flags
    end
    process_session_enc_batch-->>Caller: SessionBatchOutcome
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 Caller
    participant process_session_enc_batch
    participant session_guard as session_guard (ratchet lock)
    participant message_decrypt
    participant deferred as deferred buffer
    participant handle_decrypted_plaintext

    Caller->>process_session_enc_batch: payloads, info, sender_jid
    process_session_enc_batch->>session_guard: lock_arc() — acquire
    loop for each payload
        process_session_enc_batch->>message_decrypt: decrypt (ratchet advances)
        message_decrypt-->>process_session_enc_batch: Ok(plaintext)
        process_session_enc_batch->>deferred: push(DeferredPlaintext)
        Note over process_session_enc_batch: outcome.decrypted = true
    end
    process_session_enc_batch->>session_guard: drop() — RELEASE LOCK
    Note over session_guard: concurrent same-sender stanza can now acquire and decrypt
    loop drain deferred
        process_session_enc_batch->>handle_decrypted_plaintext: enc_type, plaintext, padding_version
        handle_decrypted_plaintext-->>process_session_enc_batch: PlaintextHandleOutcome
        Note over process_session_enc_batch: update dispatched / skdm_only flags
    end
    process_session_enc_batch-->>Caller: SessionBatchOutcome
Loading

Reviews (6): Last reviewed commit: "perf(recv): drop the per-payload clone i..." | Re-trigger Greptile

Comment thread src/message/receive.rs Outdated

@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 `@src/message/receive.rs`:
- Around line 741-744: Preserve the observable order for mixed success/failure
payload batches in receive_message handling. In src/message/receive.rs, update
the receive/decrypt loop around the logic that sets outcome.decrypted and pushes
into deferred so that not only plaintext successes but also undecryptable
events, retries, and nack side effects are queued in order. Then, after
drop(session_guard), drain that ordered action queue so later failures do not
run inline before earlier successful payloads are processed.
🪄 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: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e0c61009-73d9-4a51-ad01-e0d6e86c3047

📥 Commits

Reviewing files that changed from the base of the PR and between 882d1f8 and 6377263.

📒 Files selected for processing (2)
  • src/message.rs
  • src/message/receive.rs

Comment thread src/message/receive.rs Outdated

@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: 6377263ad9

ℹ️ 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 src/message/receive.rs

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 2 files

Confidence score: 3/5

  • In src/message/receive.rs, the batch loop now defers successful plaintext handling but still runs failure handling inline, so a later decrypt/parse failure in a mixed batch can fire undecryptable/retry side effects before earlier successful messages are applied, creating ordering/regression risk if merged as-is. De-risk by making success/failure effects use the same phase (or explicitly preserving original ordering) and add a mixed-batch test before merging.

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/message/receive.rs Outdated
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

📦 Binary size report

Metric main PR Δ
bin size (stripped) 10.77 MiB 10.77 MiB -1.72 KiB (-0.02%) 🔽
bin .text 8.78 MiB 8.78 MiB -1.56 KiB (-0.02%) 🔽
bin allocated (text+data+bss) 10.77 MiB 10.77 MiB -3.93 KiB (-0.04%) 🔽
llvm-lines wacore 504,289 504,289 0
llvm-lines wacore copies 17,275 17,275 0
llvm-lines whatsapp-rust lib 749,290 748,702 -588 (-0.08%) 🔽
llvm-lines whatsapp-rust lib copies 24,387 24,405 +18 (+0.07%) 🔺
deps crates (Cargo.lock) 466 466 0
.text per crate
Crate main PR Δ
.text whatsapp_rust 1.60 MiB 1.60 MiB -1.44 KiB (-0.09%) 🔽
.text wacore 530.38 KiB 530.38 KiB 0
.text wacore_binary 157.49 KiB 157.49 KiB 0
.text wacore_libsignal 178.73 KiB 178.73 KiB 0
.text wacore_appstate 156.42 KiB 156.42 KiB 0
.text wacore_noise 26.05 KiB 26.05 KiB 0
.text waproto 1.60 MiB 1.60 MiB 0
.text whatsapp_rust_sqlite_storage 512.98 KiB 512.98 KiB 0
.text whatsapp_rust_tokio_transport 43.61 KiB 43.61 KiB 0
.text whatsapp_rust_ureq_http_client 10.47 KiB 10.47 KiB 0
.text std 1021.77 KiB 1021.63 KiB -142 B (-0.01%) 🔽
.text other deps 2.95 MiB 2.95 MiB 0
Top movers (cargo-bloat attribution)
Crate main PR Δ
whatsapp_rust 1.60 MiB 1.60 MiB -1.44 KiB (-0.09%)

Baseline: 882d1f873 (latest main run) · Head: 8b6a21ca6 · Graphs

Self-review cleanup: replace the positional (&'static str, Vec<u8>, u8)
buffer tuple with a named DeferredPlaintext struct so the migration helper
signature and each push/drain site read for themselves, and trim the two
verbose block comments to their load-bearing invariant. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116cfRpumbEv3H4qUNmtNk4
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

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

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 2 files (changes from recent commits).

Requires human review: Auto-approval blocked by 1 unresolved issue from previous reviews.

Re-trigger cubic

Self-review follow-up: the comment said the guard is held "across the entire
batch", but the lock-scope change releases it before the plaintext drain. Say
"across the decrypt loop" and note the early release. Comment only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116cfRpumbEv3H4qUNmtNk4
@greptile-apps
greptile-apps Bot dismissed their stale review July 4, 2026 23:36

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

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

greptile-apps[bot]
greptile-apps Bot previously approved these changes Jul 4, 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.

Caution

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

⚠️ Outside diff range comments (1)
src/message/receive.rs (1)

1542-1570: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Guard hand-back contract holds — good, keep it that way.

Every exit path leaves session_guard in the state the caller expects: the early NotDecrypted returns (Lines 1543, 1547) never touch the guard, and once it's cleared at Line 1552 it's re-acquired at Line 1558 before any subsequent return. That invariant is load-bearing for the next payload in the batch, so it's worth a short comment or debug-assert that the guard is Some on return to stop a future edit from silently dropping serialization.

🤖 Prompt for 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.

In `@src/message/receive.rs` around lines 1542 - 1570, The guard hand-back
invariant in the migration retry path of receive.rs should be made explicit so
future edits do not accidentally drop serialization. In the function handling
migration decrypt results, around the session_guard release/reacquire flow and
the NotDecrypted early exits, add a short comment or debug_assert near the
return path that makes it clear session_guard must be Some whenever control
leaves this block after it has been cleared, and verify the hand-back happens in
the migrate_signal_sessions_on_lid_discovery path before returning.
🤖 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.

Outside diff comments:
In `@src/message/receive.rs`:
- Around line 1542-1570: The guard hand-back invariant in the migration retry
path of receive.rs should be made explicit so future edits do not accidentally
drop serialization. In the function handling migration decrypt results, around
the session_guard release/reacquire flow and the NotDecrypted early exits, add a
short comment or debug_assert near the return path that makes it clear
session_guard must be Some whenever control leaves this block after it has been
cleared, and verify the hand-back happens in the
migrate_signal_sessions_on_lid_discovery path before returning.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: caa8547f-a762-4513-a3ae-79b5dbcc337e

📥 Commits

Reviewing files that changed from the base of the PR and between 61ba043 and 83d0432.

📒 Files selected for processing (1)
  • src/message/receive.rs

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 1 file (changes from recent commits).

Requires human review: AI found no issues, but this optimization touches critical decryption and session lock logic in the message path. It could introduce subtle concurrency bugs that require human validation.

Re-trigger cubic

try_pn_to_lid_migration_decrypt drops and re-acquires the per-sender session
guard around the migration loop; every return after the re-acquire must leave
the guard Some or the caller silently loses same-sender serialization for the
next batch payload. Make that load-bearing invariant explicit with a
debug_assert at the re-acquire boundary.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116cfRpumbEv3H4qUNmtNk4
@greptile-apps
greptile-apps Bot dismissed their stale review July 4, 2026 23:46

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

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@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 `@src/message/receive.rs`:
- Around line 1560-1564: The debug_assert in receive-related session migration
is tautological because it checks session_guard.is_some() immediately after
assigning Some(...), so it cannot catch invariant violations. In the receive.rs
logic around the PN→LID migration path, either remove the assert and leave a
plain comment documenting the handoff, or move the check to a later point in the
same control flow where it can verify that every return path still leaves
session_guard as Some before exiting.
🪄 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: Repository UI (base), Organization UI (inherited)

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b1ed2797-0ac7-4aaf-98a2-14a667eb6d79

📥 Commits

Reviewing files that changed from the base of the PR and between 83d0432 and 119292b.

📒 Files selected for processing (1)
  • src/message/receive.rs

Comment thread src/message/receive.rs Outdated

@cubic-dev-ai cubic-dev-ai 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.

1 issue found across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/message/receive.rs Outdated
…ng it

The debug_assert added in the previous commit sat immediately after
`*session_guard = Some(...)`, so it was tautological — it could never observe a
missing hand-back on a later return path. Drop it and keep the invariant as a
comment at the reacquire boundary (flagged by cubic and CodeRabbit).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116cfRpumbEv3H4qUNmtNk4
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 1 file (changes from recent commits).

Requires human review: Modifies per-sender session lock scope in message receive path; high-risk concurrency change requires human review.

Re-trigger cubic

greptile-apps[bot]
greptile-apps Bot previously approved these changes Jul 4, 2026
…ypt bench

handle_decrypted_plaintext never moves self — every callee takes &self /
&Arc<Self> — so take self: &Arc<Self> and drop the per-payload Arc clone at the
session-drain and group-path call sites.

Also add an ignored steady-state session-decrypt benchmark
(bench_session_decrypt_throughput) that drives the real process_session_enc_batch
against established Signal sessions; deterministic CPU/allocation profiles come
from running the same binary under valgrind (callgrind/dhat).

Profiling shows the decrypt path is crypto-bound (~93% message_decrypt: SHA-256 +
curve25519); the batch orchestration this touches is ~0.06% of instructions, so
the clone removal is a hygiene win, not a throughput change. 933 lib tests pass,
clippy clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0116cfRpumbEv3H4qUNmtNk4
@greptile-apps
greptile-apps Bot dismissed their stale review July 5, 2026 04:02

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

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 2 files (changes from recent commits).

Not reviewed (too large): src/message/tests.rs (~155 lines) - if these are generated or fixture files, add them to ignored paths to exclude them from future reviews.

Requires human review: This is a non-trivial refactor of the signal session decryption locking logic that touches core crypto paths and data integrity boundaries. Even though the AI review found no issues, changes of this nature involving lock scope, deferred processing, and concurrency risk require human review.

Re-trigger cubic

@jlucaso1
jlucaso1 merged commit bda9bb8 into main Jul 5, 2026
18 checks passed
@jlucaso1
jlucaso1 deleted the claude/perf-audit-parallelization-v42g7v branch July 5, 2026 04:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants