столкнулся с проблемой, как показано ниже, нужно ли мне использовать &'static self
или self
вместо &self
? Есть ли другое решение? Благодарен за любую помощь
struct AuthToken {
token: String,
expires_at: i64,
}
pub(crate) struct Notifier {
credential: Credential,
auth_token: Arc<RwLock<AuthToken>>,
http_client: reqwest::Client,
}
pub(crate) async fn push_notification<D>(&self, notification: PushNotificationBody<D>) -> Result<(), Error>
where
D: Serialize,
{
{
// error occurs here
let mut auth_token = self
.auth_token
.write()
.map_err(|e| Error::wrap(e, "获取读写锁失败(fcm notifier)", 500u16))?;
let timestamp = chrono::Utc::now().timestamp();
if auth_token.expires_at <= timestamp - 300 {
let token = Self::generate_jwt_token(&self.credential, timestamp)?;
auth_token.token = token;
auth_token.expires_at = timestamp + 3600;
}
}
...
}
@kmdreko ок, я отредактировал
И ошибку, пожалуйста. И можете ли вы уточнить, какой тип Error
вы возвращаете?
Хотя об этом сложно судить на основании предоставленной информации (определение Error
было бы полезно, в частности Error::wrap()
), проблема, скорее всего, будет заключаться в обработке ошибок в случае, если RwLock
не удается заблокировать:
Помните, что RwLock::write()
возвращает LockResult<RwLockWriteGuard<'_, T>>
. В случае сбоя блокировки LockResult
сопровождается PoisonError<RwLockWriteGuard<'_, T>>
. У этого PoisonError
есть into_inner()
-метод, который позволяет получить доступ к базовым данным независимо от того, что блокировка считается отравленной (если это необходимо). Это также требует, чтобы PoisonError
имел тот же срок жизни, что и RwLockWriteGuard
, поскольку нам нужно иметь возможность разблокировать замок, пока внутренний RwLockWriteGuard
отбрасывается. Другими словами, значение блокировки Mutex
или RwLock
, указывающее на ошибку, заблокировало базовый объект и содержит ссылку на эту блокировку, чтобы разблокировать ее. Это распространенный источник путаницы в Rust.
В вашей конкретной ситуации кажется, что ваш Error
-тип может содержать значение ошибки e
. Для этого потребуется, чтобы ссылка на lock
имела всю жизнь 'static
, чтобы вернуть эту ошибку из метода. Но RwLockWriteGuard
, содержащийся в PoisonError
, заимствован из self.auth_token
, поэтому он существует ровно столько, сколько self
. Это ошибка, которую вы получаете.
Решение состоит в том, чтобы удалить PoisonError
(следовательно, разблокировать блокировку и удалить заимствование на &self
) в map_err()
-вызове.
Я провел рефакторинг своего кода и поднял Arc и Mutex до их родительской структуры, похоже, это помогло обойти проблему. Но я согласен с вами, причиной может быть LockResult. Позже я попробую ваше решение, чтобы убедиться, что вызвало проблему, и большое спасибо за ваш ответ.