Skip to main content

AirLibrary/Client/AirClient/
IndexFiles.rs

1//! `AirClient::IndexFiles` - drives the Air daemon's `IndexingService`
2//! over a directory tree. Filters by include / exclude glob patterns and
3//! bounds recursion depth so a stray request can't walk the entire
4//! filesystem.
5
6use tonic::Request;
7
8use crate::{
9	AirError,
10	Client::AirClient::{AirClient, IndexInfo},
11	Vine::Generated::air::IndexRequest,
12	dev_log,
13};
14
15impl AirClient {
16	/// Indexes files in a directory.
17	///
18	/// # Arguments
19	///
20	/// - `request_id` - opaque correlation id.
21	/// - `path` - root directory.
22	/// - `patterns` - glob include list (empty = include all).
23	/// - `exclude_patterns` - glob exclude list.
24	/// - `max_depth` - recursion bound; `0` indexes only `path` itself.
25	pub async fn IndexFiles(
26		&self,
27
28		request_id:String,
29
30		path:String,
31
32		patterns:Vec<String>,
33
34		exclude_patterns:Vec<String>,
35
36		max_depth:u32,
37	) -> Result<IndexInfo::Struct, AirError> {
38		dev_log!("grpc", "[AirClient] Indexing files in: {}", path);
39
40		let RequestPayload = IndexRequest { request_id, path, patterns, exclude_patterns, max_depth };
41
42		let Client = self
43			.Client()
44			.ok_or_else(|| AirError::Network("Air client not initialized".to_string()))?;
45
46		let mut ClientGuard = Client.lock().await;
47
48		match ClientGuard.index_files(Request::new(RequestPayload)).await {
49			Ok(Response) => {
50				let Response = Response.into_inner();
51
52				dev_log!(
53					"grpc",
54					"[AirClient] Files indexed: {} (total size: {} bytes)",
55					Response.files_indexed,
56					Response.total_size
57				);
58
59				Ok(IndexInfo::Struct { files_indexed:Response.files_indexed, total_size:Response.total_size })
60			},
61
62			Err(Status) => {
63				dev_log!("grpc", "error: [AirClient] Index files RPC error: {}", Status);
64
65				Err(AirError::Network(format!("Index files RPC error: {}", Status)))
66			},
67		}
68	}
69}