use appcore_core::{CapabilityDescriptor, CapabilityMode, CapabilityName, CoreId, TraceContext};
use appcore_distributed_contracts::PeerRecord;
pub type CapabilityResult<T> = Result<T, CapabilityError>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum CapabilityError {
HandlerAlreadyRegistered(CapabilityName),
HandlerNotFound(CapabilityName),
ProviderUnavailable(CapabilityName),
RequiresLeader(CapabilityName),
LeaseExpired(CapabilityName),
StaleEpoch(CapabilityName),
RemoteEndpointUnavailable(CapabilityName),
RemoteInvocationFailed(String),
HandlerRejected(String),
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct CapabilityRequest {
pub request_id: String,
pub capability: CapabilityName,
pub mode: CapabilityMode,
pub payload: Vec<u8>,
pub idempotency_key: Option<String>,
pub trace: Option<TraceContext>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct CapabilityResponse {
pub accepted: bool,
pub payload: Vec<u8>,
pub provider_core_id: Option<CoreId>,
pub message: Option<String>,
}
impl CapabilityResponse {
pub fn accepted(payload: Vec<u8>, provider_core_id: Option<CoreId>) -> Self {
Self {
accepted: true,
payload,
provider_core_id,
message: None,
}
}
pub fn rejected(message: impl Into<String>) -> Self {
Self {
accepted: false,
payload: Vec::new(),
provider_core_id: None,
message: Some(message.into()),
}
}
}
pub trait LocalCapabilityHandler: Send + Sync {
fn descriptor(&self) -> CapabilityDescriptor;
fn is_healthy(&self) -> bool {
true
}
fn handle(&self, request: &CapabilityRequest) -> CapabilityResult<CapabilityResponse>;
}
pub trait RemoteCapabilityInvoker: Send + Sync {
fn invoke_remote(
&self,
peer: &PeerRecord,
request: &CapabilityRequest,
) -> CapabilityResult<CapabilityResponse>;
}