From 856aad12e5a85d83ce6d486c7cf06892ed313a60 Mon Sep 17 00:00:00 2001 From: "{ \"message\": \"Bad credentials\", \"documentation_url\": \"https://docs.github.com/rest\", \"status\": \"401\" }" <{ "message": "Bad credentials", "documentation_url": "https://docs.github.com/rest", "status": "401" }> Date: Thu, 9 Jul 2026 20:17:55 +0000 Subject: [PATCH] fix(xmtp_mls): stabilize flaky test_hmac_and_consent_preference_sync The second consent phase of this test did not wait for alix1 to publish the consent update (SyncMetric::ConsentSent) before alix2 performed its one-shot `sync_all_welcomes_and_groups`. Because `register_interest(ConsentReceived).wait()` only waits passively on the receiver metric and never drives a re-sync, that single sync was alix2's only chance to pull the second consent. When it ran before alix1's consent message landed on the server, `sync_all_welcomes_and_groups` filtered the device-sync group out as "no new activity", so ConsentReceived never reached 2 and the test timed out with Err(Expired). Add the same ConsentSent barrier (clear -> update -> wait) the first consent phase already uses, so the receiver sync is guaranteed to observe the message. Test-only change; verified 20/20 stress runs pass. Resolves #3749 Co-Authored-By: Claude Opus 4.8 --- crates/xmtp_mls/src/worker/device_sync/tests.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/crates/xmtp_mls/src/worker/device_sync/tests.rs b/crates/xmtp_mls/src/worker/device_sync/tests.rs index 790f4a7b59..b4b0f06f96 100644 --- a/crates/xmtp_mls/src/worker/device_sync/tests.rs +++ b/crates/xmtp_mls/src/worker/device_sync/tests.rs @@ -287,7 +287,22 @@ async fn test_hmac_and_consent_preference_sync() { alix1.sync_welcomes().await?; let alix1_group = alix1.group(&bo_group.group_id)?; assert_eq!(alix1_group.consent_state()?, ConsentState::Unknown); + + // Wait for alix1 to publish the consent update to the sync group before + // alix2 syncs. `register_interest(ConsentReceived).wait()` only waits + // passively on the metric — it does not drive a re-sync — so alix2's + // one-shot `sync_all_welcomes_and_groups` below is the only chance to pull + // this consent. Without this barrier that sync can run before the consent + // message lands on the server, in which case the sync group is filtered out + // as "no new activity" and ConsentReceived never reaches 2 (flaky timeout, + // see issue #3749). Mirrors the first consent barrier above. + alix1.worker().clear_metric(SyncMetric::ConsentSent); alix1_group.update_consent_state(ConsentState::Allowed)?; + alix1 + .worker() + .register_interest(SyncMetric::ConsentSent, 1) + .wait() + .await?; alix2.sync_all_welcomes_and_groups(None).await?;