Skip to main content

Performance

Group send: session setup hoisted out of the sender-key chain lock (#807) Previously, prepare_group_stanza took the per-(group, sender) chain lock at the top and held it through the entire SKDM path — including cold-path device resolution and prekey fetch + X3DH session establishment. Any group send that needed to establish a new pairwise session held the chain lock across a server round-trip, so concurrent sends to the same group serialized behind that RTT. Two-phase split. encrypt_for_devices is now composed of two separately callable halves:
  • ensure_sessions_for_devices — network phase: LID-first session lookup, batch prekey fetch, parallel X3DH. Returns a SessionPlan (per-device LID overrides + 406 flag). Touches only session/identity state, never a sender-key chain. May span network I/O.
  • encrypt_for_devices_with_sessions — CPU phase: the bounded pairwise encrypt fan-out, consuming the SessionPlan. Safe to run under a lock that must not span I/O.
encrypt_for_devices remains as the composition of both, so the DM path is unchanged. The group path now runs ensure_sessions_for_devices before taking the chain lock; the chain lock covers only SKDM creation + pairwise fan-out + skmsg encrypt. This matches WA Web, where ensureE2ESessions is a separate step before GroupSkmsgJob’s encrypt. Session-setup lock. Hoisting session setup out of the chain lock would have let two concurrent cold sends to the same group race prekey fetch + X3DH writes to the same per-device sessions. A new SenderKeyStore::session_setup_lock (per-group, default-uncontended; backed by the same SignalStoreCache lock map under a ::setup key suffix) is held only during ensure_sessions_for_devices. Same-group cold sends serialize their setup exactly as before; warm sends (no SKDM needed) never take it, so the chain lock stays network-free. New public items:
  • wacore::send::encrypt::ensure_sessions_for_devices
  • wacore::send::encrypt::encrypt_for_devices_with_sessions
  • wacore::send::encrypt::SessionPlan
  • SenderKeyStore::session_setup_lock — defaulted trait method (returns a fresh uncontended mutex by default); production stores override via SignalStoreCache::session_setup_lock
Tracing. Both the DM and group paths now emit wa.send.ensure_sessions + wa.send.encrypt_fanout instead of a single combined wa.send.encrypt_fanout span. No breaking changesencrypt_for_devices and prepare_group_stanza keep their existing signatures.