matrix_bot_sdk/
strategies.rs1use 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}