Wrap Client internals in Arc for cheap cloning
This commit is contained in:
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use crate::apis::{AlbumsApi, AssetsApi, ServerApi, TimelineApi};
|
use crate::apis::{AlbumsApi, AssetsApi, ServerApi, TimelineApi};
|
||||||
use crate::error::{ImmichError, Result};
|
use crate::error::{ImmichError, Result};
|
||||||
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
/// Configuration for the Immich client
|
/// Configuration for the Immich client
|
||||||
@@ -56,13 +57,22 @@ impl Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Client for making requests to the Immich API
|
/// Internal client data wrapped in Arc for cheap cloning
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug)]
|
||||||
pub struct Client {
|
struct ClientInner {
|
||||||
config: Config,
|
config: Config,
|
||||||
http: reqwest::Client,
|
http: reqwest::Client,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Client for making requests to the Immich API
|
||||||
|
///
|
||||||
|
/// This struct is cheap to clone - it uses an internal Arc to share the underlying
|
||||||
|
/// HTTP client and configuration.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Client {
|
||||||
|
inner: Arc<ClientInner>,
|
||||||
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
/// Create a new client with the given configuration
|
/// Create a new client with the given configuration
|
||||||
pub fn new(config: Config) -> Result<Self> {
|
pub fn new(config: Config) -> Result<Self> {
|
||||||
@@ -86,8 +96,10 @@ impl Client {
|
|||||||
.build()?;
|
.build()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
config: Config { base_url, ..config },
|
inner: Arc::new(ClientInner {
|
||||||
http,
|
config: Config { base_url, ..config },
|
||||||
|
http,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,38 +109,46 @@ impl Client {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the API key
|
/// Set the API key
|
||||||
pub fn with_api_key(mut self, api_key: impl Into<String>) -> Self {
|
pub fn with_api_key(self, api_key: impl Into<String>) -> Self {
|
||||||
self.config.api_key = Some(api_key.into());
|
// We need to create a new ClientInner since we can't modify Arc contents
|
||||||
self
|
let mut config = self.inner.config.clone();
|
||||||
|
config.api_key = Some(api_key.into());
|
||||||
|
|
||||||
|
Self {
|
||||||
|
inner: Arc::new(ClientInner {
|
||||||
|
config,
|
||||||
|
http: self.inner.http.clone(),
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the configuration
|
/// Get the configuration
|
||||||
pub fn config(&self) -> &Config {
|
pub fn config(&self) -> &Config {
|
||||||
&self.config
|
&self.inner.config
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the base URL
|
/// Get the base URL
|
||||||
pub fn base_url(&self) -> &str {
|
pub fn base_url(&self) -> &str {
|
||||||
&self.config.base_url
|
&self.inner.config.base_url
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if the client has an API key configured
|
/// Check if the client has an API key configured
|
||||||
pub fn has_api_key(&self) -> bool {
|
pub fn has_api_key(&self) -> bool {
|
||||||
self.config.api_key.is_some()
|
self.inner.config.api_key.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the underlying HTTP client
|
/// Get the underlying HTTP client
|
||||||
pub fn http(&self) -> &reqwest::Client {
|
pub fn http(&self) -> &reqwest::Client {
|
||||||
&self.http
|
&self.inner.http
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an authenticated request builder
|
/// Create an authenticated request builder
|
||||||
pub fn request(&self, method: reqwest::Method, path: &str) -> reqwest::RequestBuilder {
|
pub fn request(&self, method: reqwest::Method, path: &str) -> reqwest::RequestBuilder {
|
||||||
let url = format!("{}/api{}", self.config.base_url, path);
|
let url = format!("{}/api{}", self.inner.config.base_url, path);
|
||||||
let mut builder = self.http.request(method, &url);
|
let mut builder = self.inner.http.request(method, &url);
|
||||||
|
|
||||||
// Add API key authentication
|
// Add API key authentication
|
||||||
if let Some(ref api_key) = self.config.api_key {
|
if let Some(ref api_key) = self.inner.config.api_key {
|
||||||
builder = builder.header("x-api-key", api_key);
|
builder = builder.header("x-api-key", api_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,7 +157,7 @@ impl Client {
|
|||||||
|
|
||||||
/// Execute a request and handle common error cases
|
/// Execute a request and handle common error cases
|
||||||
pub async fn execute(&self, request: reqwest::Request) -> Result<reqwest::Response> {
|
pub async fn execute(&self, request: reqwest::Request) -> Result<reqwest::Response> {
|
||||||
let response = self.http.execute(request).await?;
|
let response = self.inner.http.execute(request).await?;
|
||||||
|
|
||||||
if response.status().is_success() {
|
if response.status().is_success() {
|
||||||
Ok(response)
|
Ok(response)
|
||||||
|
|||||||
Reference in New Issue
Block a user