Skip to main content

AirLibrary/Client/AirServiceProvider/
mod.rs

1//! # Air::Client::AirServiceProvider
2//!
3//! High-level façade over [`crate::Client::AirClient::AirClient`]. Each
4//! method generates a request id via [`crate::Utility::GenerateRequestId`],
5//! issues the gRPC call, and returns [`crate::AirError`] on failure.
6//! Compared with the raw `AirClient` surface, this layer:
7//!
8//! - hides request-id plumbing from callers,
9//! - returns ergonomic shapes (`CheckForUpdates` collapses `update_available ==
10//!   false` into `Ok(None)`),
11//! - keeps a shared `Arc<AirClient>` so all callers reuse the same gRPC
12//!   channel.
13//!
14//! ## Layout
15//!
16//! Per-domain methods live one-per-file under this module; each declares
17//! a single `impl AirServiceProvider { … }` block:
18//!
19//! - Authentication: [`Authenticate`]
20//! - Updates: [`CheckForUpdates`], [`DownloadUpdate`], [`ApplyUpdate`]
21//! - Downloads: [`DownloadFile`], [`DownloadStream`]
22//! - Indexing: [`IndexFiles`], [`SearchFiles`], [`GetFileInfo`]
23//! - Status / monitoring: [`GetStatus`], [`GetMetrics`]
24//! - Resources: [`GetResourceUsage`], [`SetResourceLimits`]
25//! - Configuration: [`GetConfiguration`], [`UpdateConfiguration`]
26//!
27//! ## Threading model
28//!
29//! Cheap to clone (Arc ref-count bump). The interior `tokio::sync::Mutex`
30//! on the underlying `AirClient` serialises concurrent RPCs on a single
31//! channel.
32
33// --- Authentication ---
34
35pub mod Authenticate;
36
37pub mod CheckForUpdates;
38
39pub mod DownloadUpdate;
40
41// --- Downloads ---
42
43pub mod DownloadFile;
44
45pub mod DownloadStream;
46
47// --- Indexing ---
48
49pub mod GetFileInfo;
50
51pub mod IndexFiles;
52
53pub mod SearchFiles;
54
55// --- Status + monitoring ---
56
57pub mod GetMetrics;
58
59pub mod GetStatus;
60
61// --- Resource management ---
62
63pub mod GetResourceUsage;
64
65pub mod SetResourceLimits;
66
67// --- Configuration ---
68
69pub mod GetConfiguration;
70
71pub mod UpdateConfiguration;
72
73// --- ApplyUpdate ---
74
75pub mod ApplyUpdate;
76
77// --- Provider core ---
78
79use std::sync::Arc;
80
81use crate::{
82	AirError,
83	Client::AirClient::{AirClient, DEFAULT_AIR_SERVER_ADDRESS},
84	dev_log,
85};
86
87/// High-level provider over [`AirClient`]. Holds the client in an
88/// `Arc` so consumers can share one channel across the application.
89#[derive(Debug, Clone)]
90pub struct AirServiceProvider {
91	/// Shared underlying gRPC client.
92	client:Arc<AirClient>,
93}
94
95impl AirServiceProvider {
96	/// Connects to the Air daemon at `address` and returns a ready-to-use
97	/// provider.
98	///
99	/// # Errors
100	///
101	/// Forwards any error from [`AirClient::new`].
102	pub async fn new(address:String) -> Result<Self, AirError> {
103		dev_log!("grpc", "[AirServiceProvider] Creating AirServiceProvider at: {}", address);
104
105		let Client = AirClient::new(&address).await?;
106
107		dev_log!("grpc", "[AirServiceProvider] AirServiceProvider created successfully");
108
109		Ok(Self { client:Arc::new(Client) })
110	}
111
112	/// Connects using [`DEFAULT_AIR_SERVER_ADDRESS`].
113	pub async fn NewDefault() -> Result<Self, AirError> { Self::new(DEFAULT_AIR_SERVER_ADDRESS.to_string()).await }
114
115	/// Wraps an existing [`AirClient`] handle. Useful when the gRPC
116	/// channel is created elsewhere or shared with a non-provider call
117	/// site.
118	pub fn FromClient(Client:Arc<AirClient>) -> Self {
119		dev_log!("grpc", "[AirServiceProvider] Creating AirServiceProvider from existing client");
120
121		Self { client:Client }
122	}
123
124	/// Shared reference to the underlying client.
125	pub fn Client(&self) -> &Arc<AirClient> { &self.client }
126
127	/// Whether the underlying client is connected.
128	pub fn IsConnected(&self) -> bool { self.client.is_connected() }
129
130	/// Address of the Air daemon.
131	pub fn Address(&self) -> &str { self.client.address() }
132}