From 5f7679043833e8f541fb8284f7ca6bdfe14aff75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Lucas?= <55464917+jlucaso1@users.noreply.github.com> Date: Mon, 10 Aug 2026 20:56:37 -0300 Subject: [PATCH 1/2] docs(client): document new MemoryReport fields from PR #1273 Adds inbound_commit_batch, msg_secret_buffer, pending_device_sync, and app_state_key_cache to the memory_report() field table, and notes the new Transient retention section in the Display output. Ref: oxidezap/whatsapp-rust#1273 --- api/client.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/client.mdx b/api/client.mdx index 3bd9b8e..5687ca1 100644 --- a/api/client.mdx +++ b/api/client.mdx @@ -2445,6 +2445,7 @@ Entry counts plus estimated retained heap bytes for the client's internal collec | `pending_retries` | `usize` | Pending message retries | | `presence_subscriptions` | `usize` | Active presence subscriptions | | `app_state_key_requests` | `usize` | Pending app state key requests | +| `app_state_key_cache` | `usize` | Expanded app-state keys the app-state processor holds in memory. No capacity cap and no TTL — one entry per distinct key id the server's patches reference, emptied only on reconnect. Zero until the first app-state sync builds the processor ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | | `app_state_syncing` | `usize` | Active app state sync operations | | `signal_sessions` | `CollectionStats` | Cached Signal sessions | | `signal_identities` | `CollectionStats` | Cached Signal identities | @@ -2452,12 +2453,15 @@ Entry counts plus estimated retained heap bytes for the client's internal collec | `history_sync_tasks` | `CollectionStats` | Queued/running history-sync tasks and their logical compressed-payload byte sum. A shared `Bytes` slice may retain a larger backing allocation, whose capacity isn't exposed by the type | | `history_sync_tasks_peak` | `u64` | Lifetime high-water mark of queued/running history-sync tasks | | `history_sync_payload_bytes_peak` | `u64` | Lifetime high-water mark of logical compressed-payload bytes | +| `inbound_commit_batch` | `CollectionStats` | Inbound messages accumulated for the next per-batch commit (400 messages / 4 MiB flush threshold), plus their encoded-byte sum — the largest per-client allocation this report names, by two orders of magnitude. "Accumulated", not "resident": a batch already handed to its commit is still in memory but no longer counted here. Live traffic commits immediately, so outside an offline drain this is normally zero ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | +| `msg_secret_buffer` | `usize` | `messageSecret` captures buffered for write-behind persistence, from live receives and sends as well as an offline drain — a slow backend can saturate this with no drain in progress. The 4096-entry limit isn't a hard ceiling: a queueing future cancelled while backpressured force-buffers what it still holds, so this can read above the limit during teardown ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | +| `pending_device_sync` | `usize` | Users awaiting a device-list refresh, deduped so one outstanding refresh suppresses a second request for the same user. Offline entries are drained at the end of the backlog; entries added by the *online* path are removed only by that same drain or by teardown, so on a connection with no offline drain this grows with the distinct users seen with an unknown device ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | | `chatstate_handlers` | `usize` | Registered chat state handlers | | `custom_enc_handlers` | `usize` | Registered custom encryption handlers | | `stanza_interceptors` | `usize` | Registered stanza interceptors ([`add_stanza_interceptor`](#add_stanza_interceptor)). A handle that outlives its interest leaves one registered, and a leak here costs a walk on every stanza — which this count is what makes visible ([#1239](https://github.com/oxidezap/whatsapp-rust/pull/1239)) | | `plugin_stanza_interceptors` | `u64` | Behind the `plugins` feature: sum of every installed plugin's active [stanza interceptors](/advanced/plugins#stanza-interception) ([#1241](https://github.com/oxidezap/whatsapp-rust/pull/1241)) | -`CollectionStats` carries both `entries: u64` and `bytes: u64`. `MemoryReport::total_estimated_bytes(&self) -> u64` sums `.bytes` across every byte-carrying field. `MemoryReport` implements `Display` for a pretty-printed, human-readable breakdown. This output includes an `--- In-flight history sync ---` section with the two peak fields above. +`CollectionStats` carries both `entries: u64` and `bytes: u64`. `MemoryReport::total_estimated_bytes(&self) -> u64` sums `.bytes` across every byte-carrying field. `MemoryReport` implements `Display` for a pretty-printed, human-readable breakdown. This output includes an `--- In-flight history sync ---` section with the two peak fields above, followed by a `--- Transient retention ---` section for `inbound_commit_batch`, `msg_secret_buffer`, and `pending_device_sync` ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)). **Example:** From fce8a059baa16da60526423d43bb22fba2a39981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Lucas?= <55464917+jlucaso1@users.noreply.github.com> Date: Mon, 10 Aug 2026 21:09:00 -0300 Subject: [PATCH 2/2] docs(client): qualify memory_report field claims per review Inbound_commit_batch's "largest allocation" claim now notes it holds only under default cache sizing (enlarged history_sync_tasks or other cache capacity can exceed it). pending_device_sync's description now makes clear a nonzero count is dedup-set membership, not necessarily a refresh still queued -- an online-path entry outlives its own refresh until the next offline drain or teardown removes it. Addresses review feedback from oxidezap/whatsapp-rust-docs#511. --- api/client.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/client.mdx b/api/client.mdx index 5687ca1..9b6de5c 100644 --- a/api/client.mdx +++ b/api/client.mdx @@ -2453,9 +2453,9 @@ Entry counts plus estimated retained heap bytes for the client's internal collec | `history_sync_tasks` | `CollectionStats` | Queued/running history-sync tasks and their logical compressed-payload byte sum. A shared `Bytes` slice may retain a larger backing allocation, whose capacity isn't exposed by the type | | `history_sync_tasks_peak` | `u64` | Lifetime high-water mark of queued/running history-sync tasks | | `history_sync_payload_bytes_peak` | `u64` | Lifetime high-water mark of logical compressed-payload bytes | -| `inbound_commit_batch` | `CollectionStats` | Inbound messages accumulated for the next per-batch commit (400 messages / 4 MiB flush threshold), plus their encoded-byte sum — the largest per-client allocation this report names, by two orders of magnitude. "Accumulated", not "resident": a batch already handed to its commit is still in memory but no longer counted here. Live traffic commits immediately, so outside an offline drain this is normally zero ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | +| `inbound_commit_batch` | `CollectionStats` | Inbound messages accumulated for the next per-batch commit (400 messages / 4 MiB flush threshold), plus their encoded-byte sum. Under default cache configuration this is the largest per-client allocation this report names, by roughly two orders of magnitude — but a deployment running enlarged cache capacities (e.g. a larger `history_sync_tasks` payload) can push another field's bytes past it. "Accumulated", not "resident": a batch already handed to its commit is still in memory but no longer counted here. Live traffic commits immediately, so outside an offline drain this is normally zero ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | | `msg_secret_buffer` | `usize` | `messageSecret` captures buffered for write-behind persistence, from live receives and sends as well as an offline drain — a slow backend can saturate this with no drain in progress. The 4096-entry limit isn't a hard ceiling: a queueing future cancelled while backpressured force-buffers what it still holds, so this can read above the limit during teardown ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | -| `pending_device_sync` | `usize` | Users awaiting a device-list refresh, deduped so one outstanding refresh suppresses a second request for the same user. Offline entries are drained at the end of the backlog; entries added by the *online* path are removed only by that same drain or by teardown, so on a connection with no offline drain this grows with the distinct users seen with an unknown device ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | +| `pending_device_sync` | `usize` | Distinct users in the unknown-device refresh dedup set, added when a refresh is requested and suppressing a repeat request for the same user. A nonzero count doesn't mean a refresh is still queued: an online-path entry outlives its own refresh, staying until the next offline backlog drain or teardown removes it — so this counts dedup entries, not pending work. On a connection with no offline drain this grows with the distinct users seen with an unknown device ([#1273](https://github.com/oxidezap/whatsapp-rust/pull/1273)) | | `chatstate_handlers` | `usize` | Registered chat state handlers | | `custom_enc_handlers` | `usize` | Registered custom encryption handlers | | `stanza_interceptors` | `usize` | Registered stanza interceptors ([`add_stanza_interceptor`](#add_stanza_interceptor)). A handle that outlives its interest leaves one registered, and a leak here costs a walk on every stanza — which this count is what makes visible ([#1239](https://github.com/oxidezap/whatsapp-rust/pull/1239)) |