Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions advanced/signal-protocol.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -861,10 +861,10 @@ When sending group, status, or DM messages, the library validates the participan
**How it works:**

1. Before sending, the client obtains the locally computed `phash` — from the stanza `phash` attribute for group/status messages, or from `PreparedDmStanza.phash` for DMs
2. A oneshot ack waiter is registered for the message ID via `register_ack_waiter`
2. A `PhashWaiter` (expected hash, target JID, whether to also invalidate the group cache) is registered for the message ID via `register_phash_waiter` — a map entry, not a channel or a task
3. The message stanza is sent to the server
4. A background task (`spawn_phash_validation`) awaits the server's ack (with a 10-second timeout)
5. The server's ack includes its own `phash` — if it differs from the local value, the client invalidates caches
4. When the server's ack for that message ID arrives, the read loop compares its `phash` attribute against the expected value inline, with no task involved

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 Add the new implementation files to the location reference

This step now says the comparison runs in the read loop, but the section's unchanged Location line still names only src/send.rs and src/client.rs. The commit itself identifies src/client/node_io.rs and src/keepalive.rs as the files implementing the inline check and waiter sweep, so readers following the documented source locations will miss the behavior described here.

Useful? React with 👍 / 👎.

5. On a match the entry is just dropped; on a mismatch the client spawns a task to invalidate caches — so a send only pays for a task in the uncommon case, not on every send ([#1116](https://github.com/oxidezap/whatsapp-rust/pull/1116))

**On mismatch, the following caches are invalidated:**

Expand Down Expand Up @@ -895,7 +895,7 @@ if !jid.is_group() && !jid.is_status_broadcast() {
```

<Note>
The phash validation runs asynchronously in the background and does not block the send path. If the server ack times out (after 10 seconds) or the oneshot channel is dropped, the validation is silently skipped. This matches WhatsApp Web's approach of using phash as a best-effort staleness detector rather than a hard requirement.
The phash check never blocks the send path. If the server's ack never arrives, nothing polls the waiter directly — it is swept out on the keepalive tick, which drops any phash waiter that has lived through a full sweep since it registered (a window of one keepalive tick, 15–30 seconds, rather than the old fixed 10-second timeout). The sweep runs before keepalive's own idle early-return, so a connection with steady inbound traffic — which skips sending pings — still gets its stale waiters cleared; a stranded waiter would otherwise read as an outstanding IQ and suppress pings for the life of the connection. This matches WhatsApp Web's approach of using phash as a best-effort staleness detector rather than a hard requirement.
Comment thread
greptile-apps[bot] marked this conversation as resolved.
Outdated

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Split the keepalive note into concise sentences

The revised note combines waiter cleanup timing, sweep ordering, ping suppression, and WhatsApp Web parity into several long compound sentences. Split these concepts into shorter sentences so readers can distinguish the cleanup behavior from its rationale, as required by the repository's documentation style.

AGENTS.md reference: AGENTS.md:L24-L25

Useful? React with 👍 / 👎.

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 Correct the waiter lifetime range

A waiter can be registered at any point during an already-running 15–30-second keepalive interval, so the time until the next tick is not itself bounded to 15–30 seconds and may be nearly zero. If the waiter must survive one complete sweep interval before removal, cleanup instead occurs on a later tick and can span portions of two intervals. Replace the stated 15–30-second lifetime with the actual bounds or describe the sweep semantics without claiming this range.

Useful? React with 👍 / 👎.

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 Remove phash validation from the timeout usage list

This change says phash waiters are no longer polled through a fixed timeout, but api/wacore.mdx line 202 still lists phash validation as an internal user of the runtime-agnostic timeout helper. That cross-reference now documents the removed implementation and should be updated together with this section.

Useful? React with 👍 / 👎.

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 Add the waiter sweep to the keepalive ordering

The new text says the phash sweep runs before keepalive's idle early-return, while advanced/websocket-handling.mdx lines 1077–1082 still claim to list the loop's checks in order and put the recent-activity early-return first. Update that ordered description to include the sweep before step 1; otherwise the two pages give conflicting control-flow documentation.

Useful? React with 👍 / 👎.

</Note>

#### WA Web phash parity (v0.6)
Expand Down
2 changes: 2 additions & 0 deletions api/client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2029,6 +2029,8 @@ Entry counts plus estimated retained heap bytes for the client's internal collec
| `group_distribution_lock_evictions` | `u64` | Cumulative capacity evictions of cold (non-live) distribution lanes; poll successive reports to derive a rate |
| `group_distribution_lock_eviction_blocks` | `u64` | Cumulative attempts that kept a live lane and temporarily exceeded `group_distribution_locks_capacity` instead of evicting it |
| `resend_rate_limiter_chats` | `u64` | Chats tracked by the per-chat resend rate limiter (count only) |
| `transport_ack_queue` | `usize` | Deferred transport acks queued for the ack worker. Each entry retains the full inbound node plus a flush guard, so a stalled transport shows up here as a growing backlog ([#1116](https://github.com/oxidezap/whatsapp-rust/pull/1116)) |
| `delivery_receipt_queue` | `usize` | Delivery receipts queued for their worker, same shape as `transport_ack_queue` ([#1116](https://github.com/oxidezap/whatsapp-rust/pull/1116)) |
| `response_waiters` | `usize` | Active IQ response waiters |
| `node_waiters` | `usize` | Active node waiters |
| `pending_retries` | `usize` | Pending message retries |
Expand Down