Skip to main content

xmtp_mls/groups/
welcome_pointer.rs

1use super::GroupError;
2use xmtp_common::{Retry, retry_async};
3use xmtp_proto::types::{DecryptedWelcomePointer, WelcomeMessageType, WelcomeMessageV1};
4
5/// Returns none if the welcome pointer is not found
6pub async fn resolve_welcome_pointer<Context: crate::context::XmtpSharedContext>(
7    decrypted_welcome_pointer: &DecryptedWelcomePointer,
8    context: &Context,
9) -> Result<Option<WelcomeMessageV1>, GroupError> {
10    let retry = Retry::default();
11    let mut retries = 0;
12    let time_spent = xmtp_common::time::Instant::now();
13
14    let decrypted_v1 = decrypted_welcome_pointer;
15
16    tracing::debug!(
17        "Resolving welcome pointer for destination {}",
18        decrypted_v1.destination
19    );
20
21    // Can't use retry_async! because we want to return Ok(None) if it isn't resolved.
22    let welcome = loop {
23        let welcome = retry_async!(
24            Retry::default(),
25            (context
26                .api()
27                // TODO: limit this to a single message somehow (maybe an earliest_welcome_message fn)
28                .query_welcome_messages(decrypted_v1.destination.as_slice()))
29        );
30        if let Some(first) = welcome?.into_iter().next() {
31            break first;
32        }
33        retries += 1;
34        if retries <= retry.retries()
35            && let Some(d) = retry.backoff(retries, time_spent)
36        {
37            tracing::info!(
38                "Welcome pointee not found, backing off for {d:?}... (attempt {})",
39                retries
40            );
41            xmtp_common::time::sleep(d).await;
42        } else {
43            return Ok(None);
44        }
45    };
46    // These failure modes are non-retryable and will end up incrementing
47    // the cursor and will prevent the welcome message from being retried.
48    match welcome.variant {
49        WelcomeMessageType::V1(v1) => Ok(Some(v1)),
50        WelcomeMessageType::WelcomePointer(_) => {
51            tracing::warn!("Got Another welcome pointer from a welcome pointer. Ignoring.");
52            Err(xmtp_proto::ConversionError::InvalidValue {
53                item: "WelcomeMessage.version",
54                expected: "V1",
55                got: "WelcomePointer".into(),
56            }
57            .into())
58        }
59    }
60}