pub struct ImmichApiClient {
pub client: Client,
settings: RwLock<ApiClientSettings>,
pub active_url: Mutex<Option<String>>,
last_issue: Mutex<Option<ApiIssue>>,
album_cache: Mutex<HashMap<String, String>>,
album_create_locks: Mutex<HashMap<String, Arc<Mutex<()>>>>,
album_fetch_lock: Mutex<()>,
connection_check_lock: Mutex<()>,
last_successful_check: Mutex<Option<Instant>>,
albums_fetched: Mutex<bool>,
thumbnail_semaphore: Arc<Semaphore>,
}Expand description
Asynchronous Immich API client with failover and request serialization.
Fields§
§client: ClientInternal HTTP client instance.
settings: RwLock<ApiClientSettings>Configuration settings wrapper.
active_url: Mutex<Option<String>>The currently active base URL, selected by the last successful connectivity check.
last_issue: Mutex<Option<ApiIssue>>Most recent actionable API/client problem, used for the dashboard and diagnostics.
album_cache: Mutex<HashMap<String, String>>Caches album names to album IDs to avoid repeated list/create API calls.
album_create_locks: Mutex<HashMap<String, Arc<Mutex<()>>>>Per-album-name async locks that serialize concurrent get-or-create calls for the same name, preventing duplicate-album creation under load.
album_fetch_lock: Mutex<()>Serializes fetch_all_albums so concurrent callers don’t all hit the
network and race writes into the cache.
connection_check_lock: Mutex<()>Serializes check_connection so concurrent callers collapse into one
connectivity probe instead of each issuing their own LAN+WAN pings.
last_successful_check: Mutex<Option<Instant>>Timestamp of the most recent successful connectivity probe. Used to coalesce concurrent burst callers without suppressing periodic re-checks.
albums_fetched: Mutex<bool>Flag indicating whether the album list has been successfully fetched in this session.
thumbnail_semaphore: Arc<Semaphore>Semaphore guarding maximum concurrent thumbnail downloads.
Implementations§
Source§impl ImmichApiClient
impl ImmichApiClient
Sourceasync fn fetch_all_albums(&self)
async fn fetch_all_albums(&self)
Retrieve all albums from the Immich server, populating the local in-memory cache.
Sourceasync fn fetch_all_albums_locked(&self)
async fn fetch_all_albums_locked(&self)
Inner fetch implementation. Assumes album_fetch_lock is held by the
caller and albums_fetched is already known to be false.
async fn handle_fetch_albums_response(&self, result: Result<Response, Error>)
fn process_album_summaries( albums: Vec<AlbumSummary>, ) -> (HashMap<String, String>, usize, usize)
pub async fn refresh_album_cache(&self)
Sourcepub async fn get_all_albums(&self) -> Result<Vec<(String, String)>, String>
pub async fn get_all_albums(&self) -> Result<Vec<(String, String)>, String>
Return a snapshot of all cached albums as a list of (albumName, id)
Sourcepub async fn create_album(
&self,
album_name: &str,
) -> Result<Option<String>, String>
pub async fn create_album( &self, album_name: &str, ) -> Result<Option<String>, String>
Create a new album. Returns the new album ID.
Sourcepub async fn get_or_create_album(
&self,
album_name: &str,
) -> Result<Option<String>, String>
pub async fn get_or_create_album( &self, album_name: &str, ) -> Result<Option<String>, String>
Return an existing album ID or create a new one.
Sourcepub async fn get_album_id_if_exists(
&self,
album_name: &str,
) -> Result<Option<String>, String>
pub async fn get_album_id_if_exists( &self, album_name: &str, ) -> Result<Option<String>, String>
Return an existing album ID without creating a new album as a side effect.
pub async fn resolve_album_by_name( &self, album_name: &str, force_refresh: bool, ) -> Result<Option<String>, String>
Sourcepub async fn bulk_existing_asset_ids(
&self,
checksums: &[String],
) -> HashMap<String, String>
pub async fn bulk_existing_asset_ids( &self, checksums: &[String], ) -> HashMap<String, String>
Check whether an asset already exists on the server by checksum and return its asset ID. Batch checksum existence check. Returns a map from checksum to asset id for every checksum the server already has. Missing checksums are absent from the result. The Immich endpoint accepts arbitrary batch sizes, but we chunk to keep request bodies modest.
pub async fn find_existing_asset_id(&self, checksum: &str) -> Option<String>
Sourcepub async fn add_assets_to_album(
&self,
album_id: &str,
asset_ids: &[String],
) -> bool
pub async fn add_assets_to_album( &self, album_id: &str, asset_ids: &[String], ) -> bool
Add a list of asset IDs to an album.
Sourcepub async fn count_albums_for_asset(&self, asset_id: &str) -> Option<usize>
pub async fn count_albums_for_asset(&self, asset_id: &str) -> Option<usize>
Count the albums that currently contain the given asset on the server. Drives the trash-vs-remove-from-album decision when mirroring a local deletion: an asset in multiple albums should only be unlinked from the linked album, never destroyed.
Sourcepub async fn remove_assets_from_album(
&self,
album_id: &str,
asset_ids: &[String],
) -> bool
pub async fn remove_assets_from_album( &self, album_id: &str, asset_ids: &[String], ) -> bool
Remove assets from an album without trashing them on the server. Used when an asset is referenced from more than one watch folder — we want to mirror the local deletion’s album side, not destroy the asset.
Source§impl ImmichApiClient
impl ImmichApiClient
Sourcepub async fn fetch_library_albums(&self) -> Result<Vec<LibraryAlbum>, String>
pub async fn fetch_library_albums(&self) -> Result<Vec<LibraryAlbum>, String>
Retrieve the complete list of albums from the Immich server for library display.
Sourcepub async fn fetch_album_assets(
&self,
album_id: &str,
page: u32,
size: u32,
order: Option<SortOrder>,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub async fn fetch_album_assets( &self, album_id: &str, page: u32, size: u32, order: Option<SortOrder>, ) -> Result<(Vec<LibraryAsset>, bool), String>
Retrieve paginated assets contained in a specific album.
Sourcepub async fn fetch_thumbnail(
&self,
asset_id: &str,
size: ThumbnailSize,
) -> Result<Vec<u8>, String>
pub async fn fetch_thumbnail( &self, asset_id: &str, size: ThumbnailSize, ) -> Result<Vec<u8>, String>
Retrieve raw thumbnail/preview image byte array for a given asset ID.
Sourceasync fn fetch_asset_generic<T: DeserializeOwned>(
&self,
asset_id: &str,
) -> Result<T, String>
async fn fetch_asset_generic<T: DeserializeOwned>( &self, asset_id: &str, ) -> Result<T, String>
Generic helper to fetch asset JSON details.
Sourcepub async fn fetch_asset_details(
&self,
asset_id: &str,
) -> Result<AssetDetails, String>
pub async fn fetch_asset_details( &self, asset_id: &str, ) -> Result<AssetDetails, String>
Retrieve full EXIF metadata and details for a given asset ID.
Sourcepub async fn fetch_asset_by_id(
&self,
asset_id: &str,
) -> Result<LibraryAsset, String>
pub async fn fetch_asset_by_id( &self, asset_id: &str, ) -> Result<LibraryAsset, String>
Fetch a single asset as a LibraryAsset by its ID.
Sourcepub async fn download_original_to_file(
&self,
asset_id: &str,
output_path: &Path,
progress: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>,
) -> Result<(), String>
pub async fn download_original_to_file( &self, asset_id: &str, output_path: &Path, progress: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>, ) -> Result<(), String>
Download original source file of a given asset ID and save it locally.
Sourcepub async fn fetch_current_user_id(&self) -> Result<String, String>
pub async fn fetch_current_user_id(&self) -> Result<String, String>
Fetch unique user ID of the logged-in API user.
Source§impl ImmichApiClient
impl ImmichApiClient
Sourcepub async fn fetch_people(
&self,
include_hidden: bool,
) -> Result<Vec<Person>, String>
pub async fn fetch_people( &self, include_hidden: bool, ) -> Result<Vec<Person>, String>
Fetch the list of recognized people faces from the server.
Sourcepub async fn fetch_explore(&self) -> Result<Vec<ExploreSection>, String>
pub async fn fetch_explore(&self) -> Result<Vec<ExploreSection>, String>
Sectioned tile data (places + things) for the Explore landing.
Sourcepub async fn fetch_all_places(&self) -> Result<Vec<PlaceItem>, String>
pub async fn fetch_all_places(&self) -> Result<Vec<PlaceItem>, String>
Fetch all unique cities that have at least one asset with EXIF city data.
Pages through /api/search/metadata collecting one representative asset
per city. Caps at 500 pages to bound runtime on very large libraries.
Sourcepub async fn fetch_person_thumbnail(
&self,
person_id: &str,
) -> Result<Vec<u8>, String>
pub async fn fetch_person_thumbnail( &self, person_id: &str, ) -> Result<Vec<u8>, String>
Per-person face thumbnail. Distinct from fetch_thumbnail (asset).
Sourcepub async fn search_smart(
&self,
query: &str,
page: u32,
size: u32,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub async fn search_smart( &self, query: &str, page: u32, size: u32, ) -> Result<(Vec<LibraryAsset>, bool), String>
Perform a CLIP embedding-based smart search for matching assets.
Sourcepub async fn search_smart_filtered(
&self,
query: &str,
filters: &MetadataSearchFilters,
page: u32,
size: u32,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub async fn search_smart_filtered( &self, query: &str, filters: &MetadataSearchFilters, page: u32, size: u32, ) -> Result<(Vec<LibraryAsset>, bool), String>
CLIP-based smart search combined with metadata filters.
The Immich SmartSearchDto supports the same filter dimensions as
MetadataSearchDto (location, date, type, etc.) alongside the CLIP
query field. This method serialises the filters and injects the
CLIP query on top.
Sourcepub async fn search_ocr(
&self,
query: &str,
page: u32,
size: u32,
order: Option<SortOrder>,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub async fn search_ocr( &self, query: &str, page: u32, size: u32, order: Option<SortOrder>, ) -> Result<(Vec<LibraryAsset>, bool), String>
Perform an OCR-based search to match recognized text inside library images.
Sourcepub async fn search_metadata(
&self,
query: &str,
page: u32,
size: u32,
order: Option<SortOrder>,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub async fn search_metadata( &self, query: &str, page: u32, size: u32, order: Option<SortOrder>, ) -> Result<(Vec<LibraryAsset>, bool), String>
Search library assets matching specific text within their original filenames.
Sourcepub async fn search_metadata_with_filters(
&self,
filters: &MetadataSearchFilters,
page: u32,
size: u32,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub async fn search_metadata_with_filters( &self, filters: &MetadataSearchFilters, page: u32, size: u32, ) -> Result<(Vec<LibraryAsset>, bool), String>
Perform a advanced search matching specific metadata filters.
Sourcepub async fn fetch_server_stats(&self) -> Result<ServerStats, String>
pub async fn fetch_server_stats(&self) -> Result<ServerStats, String>
Retrieve total images, videos, and overall asset count statistics from the server.
Sourcepub async fn fetch_server_statistics(&self) -> Result<ServerStatistics, String>
pub async fn fetch_server_statistics(&self) -> Result<ServerStatistics, String>
Fetch server-wide statistics including per-user usage breakdown.
Admin-only endpoint; non-admin sessions will receive an HTTP 403 and an
Err is returned. Caller should fall back to per-user asset counts.
Sourcepub async fn fetch_server_about(&self) -> Result<ServerAbout, String>
pub async fn fetch_server_about(&self) -> Result<ServerAbout, String>
Retrieve detailed Immich server system information (e.g. version).
Sourcepub(super) async fn fetch_search_assets(
&self,
endpoint: &str,
body: Value,
context: RequestContext,
subject: Option<&str>,
) -> Result<(Vec<LibraryAsset>, bool), String>
pub(super) async fn fetch_search_assets( &self, endpoint: &str, body: Value, context: RequestContext, subject: Option<&str>, ) -> Result<(Vec<LibraryAsset>, bool), String>
Shared internal helper executing paginated POST search queries against asset endpoints.
Source§impl ImmichApiClient
impl ImmichApiClient
Sourcepub async fn upload_asset(
&self,
file_path: &str,
checksum: &str,
sidecar_path: Option<&str>,
progress: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>,
) -> Option<String>
pub async fn upload_asset( &self, file_path: &str, checksum: &str, sidecar_path: Option<&str>, progress: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>, ) -> Option<String>
Upload a single local asset to the Immich server with progressive status tracking.
When sidecar_path points to an existing XMP file it is attached as the
sidecarData multipart field so Immich ingests it alongside the asset.
async fn handle_upload_response( &self, resp: Response, filename: &str, file_len: u64, desired_time_zone: &Option<String>, base_url: String, progress: Option<&Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>, ) -> Option<String>
async fn handle_upload_too_large(&self, filename: &str) -> Option<String>
async fn handle_upload_auth_error(&self) -> Option<String>
async fn handle_upload_server_error( &self, status: u16, filename: &str, ) -> Option<String>
async fn handle_upload_unknown_error( &self, resp: Response, status: u16, filename: &str, ) -> Option<String>
async fn set_upload_issue(&self, issue: ApiIssue)
Sourcefn schedule_asset_timezone_fixup(
&self,
base_url: String,
asset_id: String,
time_zone: Option<String>,
)
fn schedule_asset_timezone_fixup( &self, base_url: String, asset_id: String, time_zone: Option<String>, )
Schedule a background task to fix asset timezones after upload.
async fn handle_upload_success( &self, resp: Response, filename: &str, file_len: u64, desired_time_zone: &Option<String>, base_url: String, progress: Option<&Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>, ) -> Option<String>
async fn handle_upload_duplicate( &self, resp: Response, filename: &str, file_len: u64, progress: Option<&Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>, ) -> Option<String>
async fn attach_sidecar(form: Form, sidecar_path: Option<&str>) -> Form
async fn read_asset_metadata(&self, file_path: &str) -> Option<Metadata>
async fn open_asset_file(&self, path: &Path, file_path: &str) -> Option<File>
async fn check_active_url(&self, file_path: &str) -> Option<String>
async fn execute_upload_request( &self, form: Form, base_url: String, filename: String, file_len: u64, desired_time_zone: Option<String>, progress: Option<Arc<dyn Fn(u64, Option<u64>) + Send + Sync>>, ) -> Option<String>
Source§impl ImmichApiClient
impl ImmichApiClient
Sourcepub fn new(internal_url: String, external_url: String, api_key: String) -> Self
pub fn new(internal_url: String, external_url: String, api_key: String) -> Self
Initialize a new ImmichApiClient.
Sourcepub async fn active_route_label(&self) -> Option<String>
pub async fn active_route_label(&self) -> Option<String>
Retrieve the route label (LAN/WAN) for the currently active connection URL.
Sourcepub async fn latest_issue(&self) -> Option<ApiIssue>
pub async fn latest_issue(&self) -> Option<ApiIssue>
Retrieve the most recently recorded API issue.
Sourcepub async fn update_settings(
&self,
internal_url: String,
external_url: String,
api_key: String,
)
pub async fn update_settings( &self, internal_url: String, external_url: String, api_key: String, )
Update in-memory configuration settings and reset connection state.
Sourcepub(crate) async fn clear_issue(&self)
pub(crate) async fn clear_issue(&self)
Clear the active API issue.
Sourcepub(crate) fn settings_snapshot(&self) -> ApiClientSettings
pub(crate) fn settings_snapshot(&self) -> ApiClientSettings
Retrieve a snapshot copy of the current configuration settings.
Sourcepub(crate) fn route_label_for_url(&self, url: &str) -> String
pub(crate) fn route_label_for_url(&self, url: &str) -> String
Retrieve the LAN/WAN/Custom route label matching a specific URL.
Sourcepub async fn check_connection(&self) -> bool
pub async fn check_connection(&self) -> bool
Determine which base URL to use, preferring the internal address when reachable.
async fn try_activate_url(&self, url: &str, was_offline: bool) -> bool
Sourcepub async fn ping_url(&self, url: &str) -> bool
pub async fn ping_url(&self, url: &str) -> bool
Ping a specific Immich base URL and validate that it returns a real pong response.
Sourcepub(crate) async fn get_active_url(&self) -> Option<String>
pub(crate) async fn get_active_url(&self) -> Option<String>
Return the cached active base URL, resolving connectivity first if needed.
Auto Trait Implementations§
impl !Freeze for ImmichApiClient
impl !RefUnwindSafe for ImmichApiClient
impl !UnwindSafe for ImmichApiClient
impl Send for ImmichApiClient
impl Sync for ImmichApiClient
impl Unpin for ImmichApiClient
impl UnsafeUnpin for ImmichApiClient
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more