Skip to main content

AirLibrary/Client/AirClient/
SetResourceLimits.rs

1//! `AirClient::SetResourceLimits` - asks the Air daemon to enforce
2//! ceilings on its own resource usage. Daemon-side enforcement is
3//! advisory; OS-level cgroups still bound the process.
4
5use tonic::Request;
6
7use crate::{AirError, Client::AirClient::AirClient, Vine::Generated::air::ResourceLimitsRequest, dev_log};
8
9impl AirClient {
10	/// Sets daemon resource ceilings.
11	///
12	/// # Arguments
13	///
14	/// - `request_id` - opaque correlation id.
15	/// - `memory_limit_mb` - max resident memory.
16	/// - `cpu_limit_percent` - max CPU utilisation (whole percent).
17	/// - `disk_limit_mb` - max disk-usage budget.
18	pub async fn SetResourceLimits(
19		&self,
20
21		request_id:String,
22
23		memory_limit_mb:u32,
24
25		cpu_limit_percent:u32,
26
27		disk_limit_mb:u32,
28	) -> Result<(), AirError> {
29		dev_log!(
30			"grpc",
31			"[AirClient] Setting resource limits: memory={}MB, cpu={}%, disk={}MB",
32			memory_limit_mb,
33			cpu_limit_percent,
34			disk_limit_mb
35		);
36
37		let RequestPayload = ResourceLimitsRequest { request_id, memory_limit_mb, cpu_limit_percent, disk_limit_mb };
38
39		let Client = self
40			.Client()
41			.ok_or_else(|| AirError::Network("Air client not initialized".to_string()))?;
42
43		let mut ClientGuard = Client.lock().await;
44
45		match ClientGuard.set_resource_limits(Request::new(RequestPayload)).await {
46			Ok(Response) => {
47				let Response = Response.into_inner();
48
49				if Response.success {
50					dev_log!("grpc", "[AirClient] Resource limits set successfully");
51
52					Ok(())
53				} else {
54					dev_log!("grpc", "error: [AirClient] Failed to set resource limits: {}", Response.error);
55
56					Err(AirError::ResourceLimit(Response.error))
57				}
58			},
59
60			Err(Status) => {
61				dev_log!("grpc", "error: [AirClient] Set resource limits RPC error: {}", Status);
62
63				Err(AirError::Network(format!("Set resource limits RPC error: {}", Status)))
64			},
65		}
66	}
67}