appcore_capabilities/
peer_rpc_invoker.rs1use crate::{
12 CapabilityError, CapabilityRequest, CapabilityResponse, CapabilityResult,
13 RemoteCapabilityInvoker,
14};
15use appcore_core::CapabilityMode;
16use appcore_distributed_contracts::{
17 PeerRecord, PeerRpcCallKind, PeerRpcClientExecutor, PeerRpcOutboundRequest,
18};
19
20pub struct PeerRpcRemoteCapabilityInvoker<C> {
22 client: C,
23}
24
25impl<C> PeerRpcRemoteCapabilityInvoker<C> {
26 pub fn new(client: C) -> Self {
28 Self { client }
29 }
30}
31
32impl<C> RemoteCapabilityInvoker for PeerRpcRemoteCapabilityInvoker<C>
33where
34 C: PeerRpcClientExecutor,
35{
36 fn invoke_remote(
37 &self,
38 peer: &PeerRecord,
39 request: &CapabilityRequest,
40 ) -> CapabilityResult<CapabilityResponse> {
41 let endpoint_url = peer_rpc_endpoint(peer).ok_or_else(|| {
42 CapabilityError::RemoteEndpointUnavailable(request.capability.clone())
43 })?;
44 let kind = match request.mode {
45 CapabilityMode::Query => PeerRpcCallKind::Query,
46 CapabilityMode::Command => PeerRpcCallKind::Command,
47 CapabilityMode::Stream => {
48 return Err(CapabilityError::HandlerRejected(
49 "stream_remote_invocation_not_supported".to_string(),
50 ));
51 }
52 };
53 let response = self
54 .client
55 .call_peer(
56 endpoint_url,
57 kind,
58 PeerRpcOutboundRequest::new(
59 request.request_id.clone(),
60 peer.identity.core_id.clone(),
61 request.capability.clone(),
62 request.payload.clone(),
63 request.idempotency_key.clone(),
64 request.trace.clone(),
65 ),
66 )
67 .map_err(|error| CapabilityError::RemoteInvocationFailed(format!("{error:?}")))?;
68 if response.ok {
69 return Ok(CapabilityResponse::accepted(
70 response.payload,
71 Some(peer.identity.core_id.clone()),
72 ));
73 }
74 Ok(CapabilityResponse::rejected(
75 response
76 .error
77 .unwrap_or_else(|| "remote_rejected".to_string()),
78 ))
79 }
80}
81
82fn peer_rpc_endpoint(peer: &PeerRecord) -> Option<&str> {
83 peer.endpoints
84 .iter()
85 .find(|endpoint| {
86 endpoint.name == "peer-rpc"
87 || endpoint.name == "peer_rpc"
88 || endpoint.protocol == "appcore-peer-rpc"
89 })
90 .map(|endpoint| endpoint.url.as_str())
91}