botx_api/api/utils/
auth_retry.rs

1use std::sync::Arc;
2
3use async_lock::RwLock;
4use log::{error, info};
5
6use crate::api::{
7    context::BotXApiContext,
8    result::{BotXApiError, BotXApiResult},
9    v2::token::api::token,
10};
11
12use std::future::Future;
13
14pub async fn retry_with_auth<Fut, TResponse, TError, TRequest: Fn() -> Fut>(
15    context: &Arc<RwLock<BotXApiContext>>,
16    request: TRequest,
17) -> Result<TResponse, BotXApiError<TError>>
18where
19    // for<'a> TResponse: Deserialize<'a> + Debug,
20    // for<'a> TError: Deserialize<'a> + Debug,
21    Fut: Future<Output = BotXApiResult<TResponse, TError>>,
22{
23    let response = (request)().await;
24
25    let Err(err) = response else {
26        return response
27    };
28
29    if !err.is_unauthorized() {
30        return Result::<TResponse, BotXApiError<TError>>::Err(err);
31    }
32
33    info!("Действие токена истекло, презапрашиваем");
34
35    let mut context_write_lock = context.write().await;
36    let token_response = token(&mut *context_write_lock).await;
37
38    let Ok(token_result) = token_response else {
39        error!("Не удалось повторить запрос с переавторизацией");
40        return Result::<TResponse, BotXApiError<TError>>::Err(err);
41    };
42
43    context_write_lock.auth_token = Some(token_result.token);
44
45    (request)().await
46}