use crate::error::{ClusterError, Result};
use crate::forward::{ChunkSink, PlanExecutor};
use crate::rpc_codec::{
DataProposeRequest, ExecuteRequest, MetadataProposeRequest, RaftRpc, TypedClusterError,
};
use super::super::loop_core::{CommitApplier, RaftLoop};
impl<A: CommitApplier, P: PlanExecutor> RaftLoop<A, P> {
pub(super) async fn handle_execute_rpc(&self, req: ExecuteRequest) -> Result<RaftRpc> {
let resp = self.plan_executor.execute_plan(req).await;
Ok(RaftRpc::ExecuteResponse(resp))
}
pub(super) fn handle_metadata_propose_rpc(
&self,
req: MetadataProposeRequest,
) -> Result<RaftRpc> {
let resp = match self.propose_to_metadata_group(req.bytes) {
Ok(log_index) => crate::rpc_codec::MetadataProposeResponse::ok(log_index),
Err(crate::error::ClusterError::Raft(nodedb_raft::RaftError::NotLeader {
leader_hint,
})) => crate::rpc_codec::MetadataProposeResponse::err("not leader", leader_hint),
Err(e) => crate::rpc_codec::MetadataProposeResponse::err(e.to_string(), None),
};
Ok(RaftRpc::MetadataProposeResponse(resp))
}
pub(super) fn handle_data_propose_rpc(&self, req: DataProposeRequest) -> Result<RaftRpc> {
let resp = {
let mut mr = self.multi_raft.lock().unwrap_or_else(|p| p.into_inner());
match mr.propose(req.vshard_id, req.bytes) {
Ok((group_id, log_index)) => {
crate::rpc_codec::DataProposeResponse::ok(group_id, log_index)
}
Err(crate::error::ClusterError::Raft(nodedb_raft::RaftError::NotLeader {
leader_hint,
})) => crate::rpc_codec::DataProposeResponse::err("not leader", leader_hint),
Err(e) => crate::rpc_codec::DataProposeResponse::err(e.to_string(), None),
}
};
Ok(RaftRpc::DataProposeResponse(resp))
}
pub(super) async fn handle_vshard_envelope_rpc(&self, bytes: Vec<u8>) -> Result<RaftRpc> {
if let Some(ref handler) = self.vshard_handler {
let response_bytes = handler(bytes).await?;
Ok(RaftRpc::VShardEnvelope(response_bytes))
} else {
Err(ClusterError::Transport {
detail: "VShardEnvelope handler not configured".into(),
})
}
}
pub(super) async fn handle_rpc_streaming_impl(
&self,
req: ExecuteRequest,
sink: impl ChunkSink,
) -> Option<TypedClusterError> {
self.plan_executor.execute_plan_streaming(req, sink).await
}
}