From 8d1212cbbadbd84efc35ed81c7a43c0b67640f14 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 11 Jun 2026 05:47:26 +0000 Subject: [PATCH] docs: PDO at-most-once placeholder-resend (whatsapp-rust#841) Changelog entry, CacheConfig table, and MemoryDiagnostics table for the pdo_requested memo cache added in #841. https://claude.ai/code/session_01WKYLKo6cHgMPzFrFekXheR --- api/bot.mdx | 1 + api/client.mdx | 1 + changelog/2026-06-11-pdo-once-per-message.mdx | 53 +++++++++++++++++++ docs.json | 1 + 4 files changed, 56 insertions(+) create mode 100644 changelog/2026-06-11-pdo-once-per-message.mdx diff --git a/api/bot.mdx b/api/bot.mdx index 3a26c3c9..a8b8119d 100644 --- a/api/bot.mdx +++ b/api/bot.mdx @@ -843,6 +843,7 @@ pub struct CacheEntryConfig { | `recent_messages` | 5 minutes | 0 (disabled) | Optional L1 in-memory cache for sent messages (retry support) | | `message_retry_counts` | 5 minutes | 1,000 | Retry count tracking | | `pdo_pending_requests` | 30 seconds | 500 | PDO pending requests | +| `pdo_requested` | 24 hours | 512 | PDO placeholder-resend memo — at-most-once per message | | `sender_key_devices_cache` | 1 hour (TTI) | 500 | Per-group SKDM distribution state | diff --git a/api/client.mdx b/api/client.mdx index f7581b17..a2699703 100644 --- a/api/client.mdx +++ b/api/client.mdx @@ -1821,6 +1821,7 @@ Returns a snapshot of all internal collection sizes for memory leak detection. M | `recent_messages` | `u64` | Recent message dedup cache | | `message_retry_counts` | `u64` | Message retry counter cache | | `pdo_pending_requests` | `u64` | PDO pending request cache | +| `pdo_requested` | `u64` | PDO once-per-message memo cache | | `sender_key_device_cache` | `u64` | Per-group sender key device tracking cache | | `session_locks` | `u64` | Per-device session locks | | `chat_lanes` | `u64` | Per-chat lanes (combined enqueue lock + message queue) | diff --git a/changelog/2026-06-11-pdo-once-per-message.mdx b/changelog/2026-06-11-pdo-once-per-message.mdx new file mode 100644 index 00000000..35fccb21 --- /dev/null +++ b/changelog/2026-06-11-pdo-once-per-message.mdx @@ -0,0 +1,53 @@ +--- +title: "June 11, 2026 — PDO placeholder-resend: at-most-once per message" +description: "Adds a pdo_requested memo cache that caps PDO placeholder-resend requests to one per message, skips a redundant migration retry decrypt when nothing moved, and adjusts noisy log levels." +--- + +## Bug Fix + +**PDO placeholder-resend: at-most-once per message ([#841](https://github.com/oxidezap/whatsapp-rust/pull/841))** + +A peer device with cloned Signal state could redeliver the same undecryptable message every ~11 seconds. Each copy triggered a PDO placeholder-resend request to our own phone — the `pdo_pending_requests` dedup only covered in-flight requests, so it emptied the moment the phone answered (~800 ms), and the next copy immediately opened a new one. In a three-hour storm this produced ~700 redundant requests with no benefit: the phone had already answered without content, so re-asking could not produce anything new. + +**One request per message.** A new `pdo_requested` memo cache (24h TTL, 512 entries) gates `send_pdo_placeholder_resend_request` — mirroring `WAWebNonMessageDataRequestPlaceholderMessageResendUtils`, which uses a session-lifetime set for the same purpose. The memo slot is released if the send itself fails, so a transient error does not permanently block recovery. A content-less phone response leaves the memo in place (the phone has nothing to share for this message; re-asking on the next redelivery cannot help). + +**Skip migration retry decrypt when nothing moved.** `migrate_signal_sessions_on_lid_discovery` now returns `bool` indicating whether any sessions moved into a LID slot. When it returns `false`, the subsequent retry decrypt in `try_pn_to_lid_migration_decrypt` is skipped: the Signal state is unchanged, so the retry would fail identically and only add a second decrypt error to the log for every redelivered copy. + +**Log-level adjustments.** Three lines that fired once per redelivered copy are brought in line with WA Web's telemetry handling: +- "Skipping skmsg decryption" → `debug` (WA Web's `canDecryptNext` skips silently after a retryable pkmsg failure) +- "missing message content" on a PDO response → `info` (WA Web counts this outcome in telemetry only, no warning) +- "Max retries reached" at the PDO fallback → `debug` (the high-retry `warn!` already fired on the way to the cap) + +With these changes, the same storm would produce 1 PDO request, 1 decrypt error per copy, and the existing retry receipt cap — instead of thousands of WARN/ERROR lines and hundreds of peer messages. + +## Breaking changes + +**`CacheConfig` gains a new field (`whatsapp-rust`)** + +`CacheConfig` now has a `pdo_requested` field (default: 24h TTL, 512 entries). Struct literals that spell out every field rather than using `..Default::default()` will fail to compile. + +```rust +// Update struct literals that do not use ..Default::default(): +let config = CacheConfig { + // your overrides ... + ..Default::default() // pdo_requested gets its default; no action required +}; +``` + +To tune the memo TTL or capacity: + +```rust +use std::time::Duration; +use whatsapp_rust::{CacheConfig, CacheEntryConfig}; + +let config = CacheConfig { + // Extend the TTL beyond the 24h default if you want the memo to survive + // across longer offline gaps without re-asking the phone. + pdo_requested: CacheEntryConfig::new(Some(Duration::from_secs(48 * 3600)), 512), + ..Default::default() +}; +``` + +**`MemoryDiagnostics` gains a new field (`whatsapp-rust`)** + +`MemoryDiagnostics` now has a `pdo_requested: u64` field. Code that exhaustively pattern-matches or constructs `MemoryDiagnostics` directly will need updating. diff --git a/docs.json b/docs.json index c47ca88e..4744bdea 100644 --- a/docs.json +++ b/docs.json @@ -138,6 +138,7 @@ "group": "Changelog", "pages": [ "changelog/overview", + "changelog/2026-06-11-pdo-once-per-message", "changelog/2026-06-11-history-sync-secret-prescan", "changelog/2026-06-10-jid-into-api-convention", "changelog/2026-06-10-prekey-unupload-watermark",