0

値が有効である限りキャッシュし、無効になったときに更新しようとすると、問題が発生します。この問題は、非同期実行間で状態を共有しようとしたことが原因であると考えています。さらに、このコンポーネントはマルチスレッド/並行環境に存在します。

修正方法がわからないというエラーが表示されます

future is not `Send` as this value is used across an await

以下は、一般的に私のユースケースと私が見ている問題を捉えた、私が思いつくことができる最小限の例です (所有権の問題もいくつかあります)。 これがコードの遊び場です。

use async_trait::async_trait;
use chrono::{DateTime, Utc};
use std::sync::{Arc, Mutex};

struct Creds {
    expires_at: DateTime<Utc>,
}

impl Creds {
    fn is_expired(&self) -> bool {
        self.expires_at.le(&Utc::now())
    }
}

#[async_trait]
trait CredsProvider {
    async fn get_creds(&self) -> Creds;
}

struct MyCredsProvider {
    cached_creds: Arc<Mutex<Option<Creds>>>,
}

impl MyCredsProvider {
    fn new() -> Self {
        MyCredsProvider {
            cached_creds: Arc::new(Mutex::new(None)),
        }
    }
    async fn inner_get_creds(&self) -> Creds {
        todo!()
    }
}

#[async_trait]
impl CredsProvider for MyCredsProvider {
    async fn get_creds(&self) -> Creds {
        let mg = self
            .cached_creds
            .lock()
            .expect("Unable to get lock on creds mutex");
        if mg.is_some() && !mg.as_ref().unwrap().is_expired() {
            return mg.unwrap();
        }
        let new_creds = self.inner_get_creds().await;
        *mg = Some(new_creds);
        return new_creds;
    }
}

#[tokio::main]
async fn main() {
    MyCredsProvider::new();
    // Some multi-threaded / concurrent logic to periodically refresh creds
    todo!()
}

これを例に含める方法がわかりませんでしたが、main複数のワーカースレッドが同時に/並行して実行され、各呼び出しCredsProvider.get_credsが実行され、これらのクレデンシャルを使用していくつかの作業が実行されると想像してください(完全な動作例にそれを追加できる場合、それは私の啓蒙のために非常に感謝しています)。AssumeMyCredsProvider.inner_get_credsはコストが高く、キャッシュされた資格情報の有効期限が切れたときにのみ呼び出す必要があります。

これを解決するにはどうすればよいですか?で十分だと思いましたArc<Mutex<>>が、そうではないようです。ある時点で、Credsand trait を作成できるようにしようとArc<Mutex<Option<Box<dyn Creds + Send + Sync>>>>しましたが、それは間違った道のように感じられ、うまくいきませんでした。

ありがとう。

4

1 に答える 1