conditional Sync + Send if client supports it
This commit is contained in:
parent
da9c1b1563
commit
54345fef19
|
@ -1,2 +1,3 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = [ "macros", "torn-api", "torn-key-pool" ]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "torn-api"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
|
|
|
@ -11,7 +11,7 @@ use serde::de::{DeserializeOwned, Error as DeError};
|
|||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum Error {
|
||||
pub enum ClientError {
|
||||
#[error("api returned error '{reason}', code = '{code}'")]
|
||||
Api { code: u8, reason: String },
|
||||
|
||||
|
@ -36,7 +36,7 @@ pub struct ApiResponse {
|
|||
}
|
||||
|
||||
impl ApiResponse {
|
||||
fn from_value(mut value: serde_json::Value) -> Result<Self, Error> {
|
||||
fn from_value(mut value: serde_json::Value) -> Result<Self, ClientError> {
|
||||
#[derive(serde::Deserialize)]
|
||||
struct ApiErrorDto {
|
||||
code: u8,
|
||||
|
@ -46,7 +46,7 @@ impl ApiResponse {
|
|||
match value.get_mut("error") {
|
||||
Some(error) => {
|
||||
let dto: ApiErrorDto = serde_json::from_value(error.take())?;
|
||||
Err(Error::Api {
|
||||
Err(ClientError::Api {
|
||||
code: dto.code,
|
||||
reason: dto.reason,
|
||||
})
|
||||
|
@ -82,15 +82,22 @@ pub trait ApiSelection {
|
|||
fn category() -> &'static str;
|
||||
}
|
||||
|
||||
pub trait ApiCategoryResponse {
|
||||
pub trait ApiCategoryResponse: Send + Sync {
|
||||
type Selection: ApiSelection;
|
||||
|
||||
fn from_response(response: ApiResponse) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(feature = "awc")]
|
||||
#[async_trait(?Send)]
|
||||
pub trait ApiClient {
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, Error>;
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, ClientError>;
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "awc"))]
|
||||
#[async_trait]
|
||||
pub trait ApiClient: Send + Sync {
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, ClientError>;
|
||||
}
|
||||
|
||||
pub trait DirectApiClient: ApiClient {
|
||||
|
@ -105,32 +112,32 @@ pub trait DirectApiClient: ApiClient {
|
|||
pub trait BackedApiClient: ApiClient {}
|
||||
|
||||
#[cfg(feature = "reqwest")]
|
||||
#[async_trait(?Send)]
|
||||
#[cfg_attr(feature = "awc", async_trait(?Send))]
|
||||
#[cfg_attr(not(feature = "awc"), async_trait)]
|
||||
impl crate::ApiClient for reqwest::Client {
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, crate::Error> {
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, crate::ClientError> {
|
||||
let value: serde_json::Value = self.get(url).send().await?.json().await?;
|
||||
Ok(ApiResponse::from_value(value)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "reqwest")]
|
||||
#[async_trait(?Send)]
|
||||
impl crate::DirectApiClient for reqwest::Client {}
|
||||
|
||||
#[cfg(feature = "awc")]
|
||||
#[async_trait(?Send)]
|
||||
impl crate::ApiClient for awc::Client {
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, crate::Error> {
|
||||
async fn request(&self, url: String) -> Result<ApiResponse, crate::ClientError> {
|
||||
let value: serde_json::Value = self.get(url).send().await?.json().await?;
|
||||
Ok(ApiResponse::from_value(value)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "awc")]
|
||||
#[async_trait(?Send)]
|
||||
impl crate::DirectApiClient for awc::Client {}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[cfg_attr(feature = "awc", async_trait(?Send))]
|
||||
#[cfg_attr(not(feature = "awc"), async_trait)]
|
||||
pub trait ApiRequestExecutor<'client> {
|
||||
type Err: std::error::Error;
|
||||
|
||||
|
@ -171,12 +178,13 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[cfg_attr(feature = "awc", async_trait(?Send))]
|
||||
#[cfg_attr(not(feature = "awc"), async_trait)]
|
||||
impl<'client, C> ApiRequestExecutor<'client> for DirectExecutor<'client, C>
|
||||
where
|
||||
C: ApiClient,
|
||||
{
|
||||
type Err = Error;
|
||||
type Err = ClientError;
|
||||
|
||||
async fn excute<A>(&self, request: ApiRequest<A>) -> Result<A, Self::Err>
|
||||
where
|
||||
|
@ -315,7 +323,7 @@ where
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use torn_api::{prelude::*, Error};
|
||||
/// use torn_api::{prelude::*, ClientError};
|
||||
/// use reqwest::Client;
|
||||
/// # async {
|
||||
///
|
||||
|
@ -327,7 +335,7 @@ where
|
|||
/// .await;
|
||||
///
|
||||
/// // invalid key
|
||||
/// assert!(matches!(response, Err(Error::Api { code: 2, .. })));
|
||||
/// assert!(matches!(response, Err(ClientError::Api { code: 2, .. })));
|
||||
/// # };
|
||||
/// ```
|
||||
///
|
||||
|
@ -394,7 +402,7 @@ pub(crate) mod tests {
|
|||
|
||||
awc::Client::default()
|
||||
.torn_api(key)
|
||||
.user(None)
|
||||
.user()
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "torn-key-pool"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
|
|
@ -11,13 +11,13 @@ use torn_api::prelude::*;
|
|||
#[derive(Debug, Error)]
|
||||
pub enum KeyPoolError<S>
|
||||
where
|
||||
S: std::error::Error + std::fmt::Debug,
|
||||
S: Sync + Send + std::error::Error,
|
||||
{
|
||||
#[error("Key pool storage driver error: {0:?}")]
|
||||
Storage(#[source] S),
|
||||
|
||||
#[error(transparent)]
|
||||
Client(#[from] torn_api::Error),
|
||||
Client(#[from] torn_api::ClientError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -27,14 +27,14 @@ pub enum KeyDomain {
|
|||
Faction(i32),
|
||||
}
|
||||
|
||||
pub trait ApiKey {
|
||||
pub trait ApiKey: Sync + Send {
|
||||
fn value(&self) -> &str;
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[async_trait]
|
||||
pub trait KeyPoolStorage {
|
||||
type Key: ApiKey;
|
||||
type Err: std::error::Error;
|
||||
type Err: Sync + Send + std::error::Error;
|
||||
|
||||
async fn acquire_key(&self, domain: KeyDomain) -> Result<Self::Key, Self::Err>;
|
||||
|
||||
|
@ -66,11 +66,12 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[cfg_attr(feature = "awc", async_trait(?Send))]
|
||||
#[cfg_attr(not(feature = "awc"), async_trait)]
|
||||
impl<'client, C, S> ApiRequestExecutor<'client> for KeyPoolExecutor<'client, C, S>
|
||||
where
|
||||
C: ApiClient,
|
||||
S: KeyPoolStorage + 'static,
|
||||
S: KeyPoolStorage + Send + Sync + 'static,
|
||||
{
|
||||
type Err = KeyPoolError<S::Err>;
|
||||
|
||||
|
@ -88,7 +89,7 @@ where
|
|||
let res = self.client.request(url).await;
|
||||
|
||||
match res {
|
||||
Err(torn_api::Error::Api { code, .. }) => {
|
||||
Err(torn_api::ClientError::Api { code, .. }) => {
|
||||
if !self
|
||||
.storage
|
||||
.flag_key(key, code)
|
||||
|
|
|
@ -63,7 +63,7 @@ impl PgKeyPoolStorage {
|
|||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
#[async_trait]
|
||||
impl KeyPoolStorage for PgKeyPoolStorage {
|
||||
type Key = PgKey;
|
||||
|
||||
|
|
Loading…
Reference in a new issue