headless_lms_server/controllers/tmc_server/
mod.rs1pub mod users;
8pub mod users_by_upstream_id;
9
10use crate::prelude::*;
11use headless_lms_utils::tmc::TmcClient;
12
13pub fn _add_routes(cfg: &mut ServiceConfig) {
15 cfg.service(web::scope("/users-by-upstream-id").configure(users_by_upstream_id::_add_routes))
16 .service(web::scope("/users").configure(users::_add_routes));
17}
18
19pub async fn notify_password_managed_with_retry(
27 tmc_client: &TmcClient,
28 upstream_id: String,
29 user_id: Uuid,
30) {
31 const MAX_ATTEMPTS_INLINE: u32 = 3;
32 const MAX_DELAY_MS_INLINE: u64 = 2_000;
33 for attempt in 1..=MAX_ATTEMPTS_INLINE {
34 match tmc_client
35 .set_user_password_managed_by_courses_mooc_fi(upstream_id.clone(), user_id)
36 .await
37 {
38 Ok(_) => return,
39 Err(e) if attempt < MAX_ATTEMPTS_INLINE => {
40 let delay = std::time::Duration::from_millis(
41 200u64
42 .saturating_mul(2u64.pow(attempt - 1))
43 .min(MAX_DELAY_MS_INLINE),
44 );
45 warn!(
46 "Failed to notify TMC that user's password is saved in courses.mooc.fi (inline attempt {}/{}), retrying in {:?}: upstream_id={}, user_id={}, error={}",
47 attempt, MAX_ATTEMPTS_INLINE, delay, upstream_id, user_id, e
48 );
49 tokio::time::sleep(delay).await;
50 }
51 Err(e) => {
52 warn!(
53 "Inline TMC notification attempts exhausted, handing off to background task: upstream_id={}, user_id={}, error={}",
54 upstream_id, user_id, e
55 );
56 }
57 }
58 }
59
60 let tmc_client = tmc_client.clone();
61 tokio::spawn(async move {
62 const MAX_ATTEMPTS_BG: u32 = 10;
63 const MAX_DELAY_MS_BG: u64 = 30_000;
64 for attempt in 1..=MAX_ATTEMPTS_BG {
65 match tmc_client
66 .set_user_password_managed_by_courses_mooc_fi(upstream_id.clone(), user_id)
67 .await
68 {
69 Ok(_) => {
70 info!(
71 "Background TMC notification succeeded on attempt {}: upstream_id={}, user_id={}",
72 attempt, upstream_id, user_id
73 );
74 return;
75 }
76 Err(e) if attempt < MAX_ATTEMPTS_BG => {
77 let delay = std::time::Duration::from_millis(
78 200u64
79 .saturating_mul(2u64.pow(attempt - 1))
80 .min(MAX_DELAY_MS_BG),
81 );
82 warn!(
83 "Background TMC notification failed (attempt {}/{}), retrying in {:?}: upstream_id={}, user_id={}, error={}",
84 attempt, MAX_ATTEMPTS_BG, delay, upstream_id, user_id, e
85 );
86 tokio::time::sleep(delay).await;
87 }
88 Err(e) => {
89 error!(
90 "Background TMC notification exhausted all {} retries: upstream_id={}, user_id={}, error={}",
91 MAX_ATTEMPTS_BG, upstream_id, user_id, e
92 );
93 }
94 }
95 }
96 });
97}