Skip to content

Commit 27a6871

Browse files
refactor(Mountain/Vine): Standardize gRPC protocol field names and error handling
This commit refactors the Vine gRPC protocol definitions and implementation to establish consistent naming conventions and improve type safety across the IPC layer. Key changes include: 1. **Proto Field Standardization**: - Updated all field names in `Vine.proto` to PascalCase (e.g., `request_id` → `RequestIdentifier`, `params` → `Parameter`) - Renamed `RpcError` to `RPCError` for consistency - Added clearer comments for serialization expectations 2. **Rust Implementation Alignment**: - Updated `Mountain`'s Vine client/server code to match new proto field names - Renamed `VineError::RpcError` variant to `RPCError` - Improved error handling during JSON deserialization in gRPC handlers 3. **Build Process Enhancement**: - Added `compile_well_known_types(true)` in `build.rs` to support future protocol extensions 4. **Minor Refinements**: - Capitalized `IPCProvider` variable in shutdown sequence - Updated cancellation logic comments to reference new field names These changes strengthen the foundation of the Vine IPC layer by: - Ensuring field naming consistency between Mountain and Cocoon - Preparing for advanced gRPC features through well-known type support - Maintaining alignment with Land's core architecture where Vine serves as the critical communication channel between Mountain and Cocoon BREAKING CHANGE: Requires corresponding updates in Cocoon to match new field names (`RequestIdentifier`, `Parameter`, `RPCError` etc.) in Vine.proto
1 parent 6d0b1ff commit 27a6871

7 files changed

Lines changed: 70 additions & 50 deletions

File tree

Proto/Vine.proto

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,60 +4,75 @@ package vine_ipc;
44

55
// Service running on the Mountain host, listening for requests from Cocoon.
66
service MountainService {
7-
// A generic request-response method for Cocoon to call a function on Mountain.
8-
rpc ProcessCocoonRequest(GenericRequest) returns (GenericResponse);
9-
// A generic fire-and-forget method for Cocoon to send a notification to Mountain.
10-
rpc SendCocoonNotification(GenericNotification) returns (Empty);
11-
// A method for Cocoon to request that Mountain cancel a long-running operation.
12-
rpc CancelOperation(CancelOperationRequest) returns (Empty);
7+
// A generic request-response method for Cocoon to call a function on Mountain.
8+
rpc ProcessCocoonRequest(GenericRequest) returns (GenericResponse);
9+
10+
// A generic fire-and-forget method for Cocoon to send a notification to Mountain.
11+
rpc SendCocoonNotification(GenericNotification) returns (Empty);
12+
13+
// A method for Cocoon to request that Mountain cancel a long-running operation.
14+
rpc CancelOperation(CancelOperationRequest) returns (Empty);
1315
}
1416

1517
// Service running on the Cocoon sidecar, listening for requests from Mountain.
1618
service CocoonService {
17-
// A generic request-response method for Mountain to call a function on Cocoon.
18-
rpc ProcessMountainRequest(GenericRequest) returns (GenericResponse);
19-
// A generic fire-and-forget method for Mountain to send a notification to Cocoon.
20-
rpc SendMountainNotification(GenericNotification) returns (Empty);
21-
// A method for Mountain to request that Cocoon cancel a long-running operation.
22-
rpc CancelOperation(CancelOperationRequest) returns (Empty);
19+
// A generic request-response method for Mountain to call a function on Cocoon.
20+
rpc ProcessMountainRequest(GenericRequest) returns (GenericResponse);
21+
22+
// A generic fire-and-forget method for Mountain to send a notification to Cocoon.
23+
rpc SendMountainNotification(GenericNotification) returns (Empty);
24+
25+
// A method for Mountain to request that Cocoon cancel a long-running operation.
26+
rpc CancelOperation(CancelOperationRequest) returns (Empty);
2327
}
2428

2529
// Represents an empty message, typically used for RPCs that don't need to return data.
2630
message Empty {}
2731

2832
// A generic request message containing a method name and serialized parameters.
2933
message GenericRequest {
30-
uint64 request_id = 1;
31-
string method = 2;
32-
bytes params = 3; // Parameters are expected to be a JSON-serialized byte array.
34+
uint64 RequestIdentifier = 1;
35+
36+
string Method = 2;
37+
38+
// Parameters are expected to be a JSON-serialized byte array.
39+
bytes Parameter = 3;
3340
}
3441

3542
// A generic response message containing the result or an error.
3643
message GenericResponse {
37-
uint64 request_id = 1;
38-
bytes result = 2; // The successful result, JSON-serialized.
39-
optional RpcError error = 3;
44+
uint64 RequestIdentifier = 1;
45+
46+
// The successful result, JSON-serialized.
47+
bytes Result = 2;
48+
49+
optional RPCError error = 3;
4050
}
4151

4252
// A generic notification message, which is fire-and-forget and does not have an ID.
4353
message GenericNotification {
44-
string method = 1;
45-
bytes params = 2; // Parameters are expected to be a JSON-serialized byte array.
54+
string Method = 1;
55+
56+
// Parameters are expected to be a JSON-serialized byte array.
57+
bytes Parameter = 2;
4658
}
4759

4860
// A structured error payload, compliant with JSON-RPC error objects.
49-
message RpcError {
50-
int32 code = 1;
51-
string message = 2;
52-
bytes data = 3; // Optional, additional error data, JSON-serialized.
61+
message RPCError {
62+
int32 Code = 1;
63+
64+
string Message = 2;
65+
66+
// Optional, additional error data, JSON-serialized.
67+
bytes Data = 3;
5368
}
5469

5570
// A message to cancel a specific, ongoing operation.
5671
message CancelOperationRequest {
57-
uint64 request_id_to_cancel = 1;
72+
uint64 RequestIdentifierToCancel = 1;
5873
}
5974

6075
// A generic data payload, currently unused but available for future extensions.
6176
message RPCDataPayload {
62-
bytes data = 1;
77+
bytes Data = 1;
6378
}

Source/RunTime/ApplicationRunTime.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ impl ApplicationRunTime {
5353
info!("[ApplicationRunTime] Initiating graceful shutdown of services...");
5454

5555
// 1. Shutdown Cocoon
56-
let IpcProvider:Arc<dyn IPCProvider> = self.Environment.Require();
57-
if let Err(e) = IpcProvider
56+
let IPCProvider:Arc<dyn IPCProvider> = self.Environment.Require();
57+
if let Err(e) = IPCProvider
5858
.SendNotificationToSidecar("cocoon-main".to_string(), "$shutdown".to_string(), serde_json::Value::Null)
5959
.await
6060
{

Source/Vine/Client.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub async fn SendNotification(SidecarIdentifier:String, Method:String, Parameter
4747
};
4848

4949
if let Some(ref mut client) = client {
50-
let request = GenericNotification { method:Method, params:to_vec(&Parameters)? };
50+
let request = GenericNotification { method:Method, parameter:to_vec(&Parameters)? };
5151
client.send_mountain_notification(request).await?;
5252
Ok(())
5353
} else {
@@ -74,9 +74,13 @@ pub async fn SendRequest(
7474
if let Some(ref mut client) = client {
7575
let mut hasher = DefaultHasher::new();
7676
uuid::Uuid::new_v4().hash(&mut hasher);
77-
let request_id = hasher.finish();
77+
let RequestIdentifier = hasher.finish();
7878

79-
let request = GenericRequest { request_id, method:Method.clone(), params:to_vec(&Parameters)? };
79+
let request = GenericRequest {
80+
request_identifier:RequestIdentifier,
81+
method:Method.clone(),
82+
parameter:to_vec(&Parameters)?,
83+
};
8084

8185
let future = client.process_mountain_request(request);
8286

@@ -88,7 +92,7 @@ pub async fn SendRequest(
8892
"[VineClient] Received RPC error from sidecar '{}': {}",
8993
SidecarIdentifier, rpc_error.message
9094
);
91-
Err(VineError::RpcError(rpc_error.message))
95+
Err(VineError::RPCError(rpc_error.message))
9296
} else {
9397
let deserialized_value = from_slice(&response_data.result)?;
9498
Ok(deserialized_value)

Source/Vine/Error.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub enum VineError {
1818

1919
/// An RPC call to a sidecar failed with a specific gRPC status.
2020
#[error("gRPC call failed: {0}")]
21-
RpcError(String),
21+
RPCError(String),
2222

2323
/// An error occurred while serializing or deserializing a JSON payload.
2424
#[error("JSON serialization error for gRPC payload: {0}")]
@@ -50,5 +50,5 @@ impl<T> From<PoisonError<MutexGuard<'_, T>>> for VineError {
5050
}
5151

5252
impl From<tonic::Status> for VineError {
53-
fn from(status:tonic::Status) -> Self { VineError::RpcError(status.to_string()) }
53+
fn from(status:tonic::Status) -> Self { VineError::RPCError(status.to_string()) }
5454
}

Source/Vine/Generated/vine_ipc.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ pub struct Empty {}
66
#[derive(Clone, PartialEq, ::prost::Message)]
77
pub struct GenericRequest {
88
#[prost(uint64, tag = "1")]
9-
pub request_id: u64,
9+
pub request_identifier: u64,
1010
#[prost(string, tag = "2")]
1111
pub method: ::prost::alloc::string::String,
1212
/// Parameters are expected to be a JSON-serialized byte array.
1313
#[prost(bytes = "vec", tag = "3")]
14-
pub params: ::prost::alloc::vec::Vec<u8>,
14+
pub parameter: ::prost::alloc::vec::Vec<u8>,
1515
}
1616
/// A generic response message containing the result or an error.
1717
#[derive(Clone, PartialEq, ::prost::Message)]
1818
pub struct GenericResponse {
1919
#[prost(uint64, tag = "1")]
20-
pub request_id: u64,
20+
pub request_identifier: u64,
2121
/// The successful result, JSON-serialized.
2222
#[prost(bytes = "vec", tag = "2")]
2323
pub result: ::prost::alloc::vec::Vec<u8>,
@@ -31,7 +31,7 @@ pub struct GenericNotification {
3131
pub method: ::prost::alloc::string::String,
3232
/// Parameters are expected to be a JSON-serialized byte array.
3333
#[prost(bytes = "vec", tag = "2")]
34-
pub params: ::prost::alloc::vec::Vec<u8>,
34+
pub parameter: ::prost::alloc::vec::Vec<u8>,
3535
}
3636
/// A structured error payload, compliant with JSON-RPC error objects.
3737
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -48,7 +48,7 @@ pub struct RpcError {
4848
#[derive(Clone, Copy, PartialEq, ::prost::Message)]
4949
pub struct CancelOperationRequest {
5050
#[prost(uint64, tag = "1")]
51-
pub request_id_to_cancel: u64,
51+
pub request_identifier_to_cancel: u64,
5252
}
5353
/// A generic data payload, currently unused but available for future extensions.
5454
#[derive(Clone, PartialEq, ::prost::Message)]

Source/Vine/Server/MountainVinegRPCService.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::{
2020
GenericNotification,
2121
GenericRequest,
2222
GenericResponse,
23-
RpcError,
23+
RpcError as RPCError,
2424
mountain_service_server::MountainService,
2525
},
2626
};
@@ -48,22 +48,22 @@ impl MountainService for MountainVinegRPCService {
4848
) -> Result<Response<GenericResponse>, Status> {
4949
let RequestData = request.into_inner();
5050
let MethodName = RequestData.method;
51-
let RequestIdentifier = RequestData.request_id;
51+
let RequestIdentifier = RequestData.request_identifier;
5252

5353
info!(
5454
"[VineServer] Received gRPC Request [ID: {}]: Method='{}'",
5555
RequestIdentifier, MethodName
5656
);
5757

58-
let ParametersValue:Value = match serde_json::from_slice(&RequestData.params) {
58+
let ParametersValue:Value = match serde_json::from_slice(&RequestData.parameter) {
5959
Ok(v) => v,
6060
Err(e) => {
6161
let msg = format!("Failed to deserialize parameters for method '{}': {}", MethodName, e);
6262
error!("{}", msg);
6363
return Ok(Response::new(GenericResponse {
64-
request_id:RequestIdentifier,
64+
request_identifier:RequestIdentifier,
6565
result:vec![],
66-
error:Some(RpcError { message:msg, code:-32700, data:vec![] }),
66+
error:Some(RPCError { message:msg, code:-32700, data:vec![] }),
6767
}));
6868
},
6969
};
@@ -85,16 +85,16 @@ impl MountainService for MountainVinegRPCService {
8585
b"null".to_vec()
8686
});
8787
Ok(Response::new(GenericResponse {
88-
request_id:RequestIdentifier,
88+
request_identifier:RequestIdentifier,
8989
result:ResultBytes,
9090
error:None,
9191
}))
9292
},
9393
Err(ErrorString) => {
9494
Ok(Response::new(GenericResponse {
95-
request_id:RequestIdentifier,
95+
request_identifier:RequestIdentifier,
9696
result:vec![],
97-
error:Some(RpcError {
97+
error:Some(RPCError {
9898
message:ErrorString,
9999
code:-32000, // JSON-RPC Generic Server Error
100100
data:vec![],
@@ -114,16 +114,16 @@ impl MountainService for MountainVinegRPCService {
114114
// dedicated handler for processing status updates, etc. For now, we
115115
// just log and acknowledge.
116116
// For example:
117-
// let params: Value = serde_json::from_slice(...)?;
118-
// NotificationHandler::Handle(MethodName, params).await;
117+
// let Parameter: Value = serde_json::from_slice(...)?;
118+
// NotificationHandler::Handle(MethodName, Parameter).await;
119119

120120
Ok(Response::new(Empty {}))
121121
}
122122

123123
/// Handles a request from Cocoon to cancel a long-running operation.
124124
async fn cancel_operation(&self, _request:Request<CancelOperationRequest>) -> Result<Response<Empty>, Status> {
125125
info!("[VineServer] Received CancelOperation request, but cancellation is not yet implemented.");
126-
// A full implementation would map the request_id_to_cancel to a
126+
// A full implementation would map the RequestIdentifier_to_cancel to a
127127
// CancellationToken and trigger it.
128128
Ok(Response::new(Empty {}))
129129
}

build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
5555
.build_server(true)
5656
.build_client(true)
5757
.out_dir("Source/Vine/Generated")
58+
.compile_well_known_types(true)
5859
.compile_protos(&["Proto/Vine.proto"], &["Proto"])?;
5960

6061
tauri_build::build();

0 commit comments

Comments
 (0)