fix(media)!: schedule distinct reuploads and preserve phased failures
A pending first reupload previously prevented another operation from starting even after the other 31 finished. Duplicate subscribers also consumed concurrency slots. Reserve every input first, group subscriptions by shared operation, and poll up to 32 distinct operations with unordered completion. Fan results back to their original slots, retaining order, cardinality, conflict errors, and cancellation cleanup.
Both deterministic progress regressions failed on bd1f3069 and pass with the scheduler change. The standalone native consumer also requires the batch future to be Send. Collecting operation futures before constructing the buffered stream makes that contract compile on Rust 1.94.1.
The error contract now identifies the failed phase and preserves server rejections. Migrate callers as follows:
AckTimeoutbecomesTimeout { phase: MediaReuploadPhase::SendAndAck }.- The former unit
TimeoutbecomesTimeout { phase: MediaReuploadPhase::Notification }. - Closed waiter channels become
Cancelled { phase }. Dropping a subscriber future still returns no error and uses the existing cleanup guards. Rejected(String)becomesRejected { code: Option<u16>, response: RejectionStanza }. Absent, nonnumeric, or out-of-range codes produce None; the full original response retains raw and unknown fields.- Client/Internal causes remain shared and accessible through Error::source and downcast. Debug redacts opaque causes and retained stanza contents.
MediaReuploadPhase is available through both the crate root and features reexports. The first 30-second budget still includes send_node and ACK waiting. Notification waiting receives its own 30-second budget. Filters, identity handling, wire shape, and subscriber ownership are unchanged.
Validation: 2,518 SDK library tests passed, 3 skipped; default SDK all-target clippy passed with warnings denied; 50 SDK doctests passed, 15 ignored; 28 native consumer tests and 63 doctests passed; Rust 1.94.1 and WASM standalone consumer checks passed. Formatting checks passed. A read-only implementation review found no correctness issues. The first parallel native link attempt exhausted temporary disk space; rerunning with one build job completed successfully.
These local checks exercised the combined implementation and both exports in an isolated checkout. The PR's integrated files differ only by rustfmt line wrapping. Exact-head remote verification is complete: all 36 functional checks passed, including full builds/tests, all-feature build/lint/tests, all 11 crate feature matrices, native/MSRV consumers, WASM, Miri, E2E, Rustdoc, formatting, generated artifacts, supply-chain checks, and binary size. Greptile passed with 5/5 confidence and no review findings. No CI checks were weakened.
CI evidence on f1b22a160f27394e1e4a5bdb5c8c8eebe47ac878: the binary-size gate passed with zero change in stripped bytes, .text, and allocated sections. Its test-merge tree matches the PR head. The informational semver job fails on unchanged wacore/wacore-binary/waproto APIs against published 0.7.0 and also fails on base bd1f3069; the existing advisory policy is unchanged.
CodSpeed's exact-head comparison flags two libsignal session simulations, both explicitly listed under a linked-library environment difference. No libsignal, protobuf, dependency, or benchmark configuration files changed. These measurements do not establish a reupload regression; no performance override or unrelated optimization was applied.
Integration with main b4e349989cc980ec7c9de6f35d95a3f5017b3914 (#1652) was verified in an isolated automatic-merge tree, ff8ffaa3e8fe922fe0159e5337a42903aa80afff. The merge is conflict-free, preserves removal of the free message_key export from both public paths, and retains MediaReuploadPhase in both paths. Formatting, 26 native consumer library tests, all 20 removed-action API compile-fail tests, Rust 1.94.1 consumer check, and WASM consumer check passed on that exact combined tree. The PR head remains unchanged; no branch rewrite was needed.
Review follow-up: CodeRabbit approved f1b22a1 and withdrew its sole cosmetic finding, explicitly confirming no code change was needed. No review was dismissed. Codex code review completed on f1b22a1 with no posted finding. Its separate security review was blocked by account usage limits; security-review completion or approval is not claimed.