Skip to main content

Mountain/Vine/Client/
ConnectToSideCar.rs

1#![allow(non_snake_case)]
2
3//! Establish a gRPC connection to a Cocoon sidecar with exponential
4//! back-off retry. On success initialises the per-connection metadata
5//! tracked by `Shared::CONNECTION_METADATA`.
6
7use std::time::{Duration, Instant};
8
9use crate::{
10	Vine::{
11		Client::{
12			Shared::{CONNECTION_METADATA, ConnectionMetadata, MAX_RETRY_ATTEMPTS, RETRY_BASE_DELAY_MS},
13			TryConnectSingle,
14		},
15		Error::VineError,
16	},
17	dev_log,
18};
19
20pub async fn Fn(SideCarIdentifier:String, Address:String) -> Result<(), VineError> {
21	dev_log!(
22		"grpc",
23		"[VineClient] Connecting to sidecar '{}' at '{}'...",
24		SideCarIdentifier,
25		Address
26	);
27
28	let Endpoint = format!("http://{}", Address);
29
30	if Endpoint.len() > 256 {
31		return Err(VineError::RPCError(
32			"Invalid endpoint address: exceeds maximum length".to_string(),
33		));
34	}
35
36	let mut LastError = None;
37
38	for Attempt in 1..=MAX_RETRY_ATTEMPTS {
39		let Result = TryConnectSingle::Fn(&SideCarIdentifier, &Endpoint).await;
40
41		if Result.is_ok() {
42			CONNECTION_METADATA.lock().insert(
43				SideCarIdentifier.clone(),
44				ConnectionMetadata { LastActivity:Instant::now(), FailureCount:0, IsHealthy:true },
45			);
46
47			dev_log!("grpc", "[VineClient] Successfully connected to sidecar '{}'", SideCarIdentifier);
48
49			return Result;
50		}
51
52		LastError = Some(Result.unwrap_err());
53
54		if Attempt < MAX_RETRY_ATTEMPTS {
55			let DelayMilliseconds = RETRY_BASE_DELAY_MS * 2_u64.pow(Attempt as u32);
56			tokio::time::sleep(Duration::from_millis(DelayMilliseconds)).await;
57		}
58	}
59
60	Err(LastError.unwrap_or_else(|| VineError::RPCError("Connection failed".to_string())))
61}