Skip to main content

matrix_bot_sdk/
strategies.rs

1use std::time::Duration;
2
3use async_trait::async_trait;
4
5use crate::client::MatrixClient;
6
7#[async_trait]
8pub trait JoinRoomStrategy: Send + Sync {
9    async fn join_room(&self, client: &MatrixClient, room_id: &str) -> anyhow::Result<String>;
10}
11
12#[derive(Debug, Default)]
13pub struct AppserviceJoinRoomStrategy;
14
15impl AppserviceJoinRoomStrategy {
16    pub fn new() -> Self {
17        Self
18    }
19}
20
21#[async_trait]
22impl JoinRoomStrategy for AppserviceJoinRoomStrategy {
23    async fn join_room(&self, client: &MatrixClient, room_id: &str) -> anyhow::Result<String> {
24        client.join_room(room_id).await
25    }
26}
27
28#[derive(Debug, Clone)]
29pub struct SimpleRetryJoinStrategy {
30    pub schedule: Vec<Duration>,
31}
32
33impl Default for SimpleRetryJoinStrategy {
34    fn default() -> Self {
35        Self {
36            schedule: vec![
37                Duration::from_secs(0),
38                Duration::from_secs(2),
39                Duration::from_secs(5),
40                Duration::from_secs(10),
41            ],
42        }
43    }
44}
45
46impl SimpleRetryJoinStrategy {
47    pub fn new() -> Self {
48        Self::default()
49    }
50
51    pub fn with_schedule(schedule: Vec<Duration>) -> Self {
52        Self { schedule }
53    }
54
55    pub async fn retry<F, Fut>(&self, mut api_call: F) -> anyhow::Result<String>
56    where
57        F: FnMut() -> Fut,
58        Fut: std::future::Future<Output = anyhow::Result<String>>,
59    {
60        let mut last_error = None;
61
62        for delay in &self.schedule {
63            if !delay.is_zero() {
64                tokio::time::sleep(*delay).await;
65            }
66
67            match api_call().await {
68                Ok(result) => return Ok(result),
69                Err(e) => {
70                    last_error = Some(e);
71                }
72            }
73        }
74
75        Err(last_error.unwrap_or_else(|| anyhow::anyhow!("All retry attempts failed")))
76    }
77}
78
79#[async_trait]
80impl JoinRoomStrategy for SimpleRetryJoinStrategy {
81    async fn join_room(&self, client: &MatrixClient, room_id: &str) -> anyhow::Result<String> {
82        self.retry(|| client.join_room(room_id)).await
83    }
84}