use std::time::Duration;
use crate::client::{OrleansClient, RawResponse};
use crate::error::OrleansError;
use crate::key::GrainKey;
use crate::request_context::RequestContext;
#[derive(Clone)]
pub struct GrainRef {
client: OrleansClient,
interface_name: String,
grain_type: String,
key: GrainKey,
context: RequestContext,
timeout: Option<Duration>,
}
impl GrainRef {
pub(crate) fn new(
client: OrleansClient,
interface_name: String,
grain_type: String,
key: GrainKey,
) -> Self {
Self {
client,
interface_name,
grain_type,
key,
context: RequestContext::new(),
timeout: None,
}
}
#[must_use]
pub fn interface_name(&self) -> &str {
&self.interface_name
}
#[must_use]
pub fn grain_type(&self) -> &str {
&self.grain_type
}
#[must_use]
pub fn key(&self) -> &GrainKey {
&self.key
}
#[must_use]
pub fn with_context(mut self, context: RequestContext) -> Self {
self.context = context;
self
}
#[must_use]
pub fn with_timeout(mut self, timeout: Duration) -> Self {
self.timeout = Some(timeout);
self
}
fn effective_context(&self) -> RequestContext {
self.client
.config()
.default_context
.merged_with(&self.context)
}
pub async fn invoke(
&self,
method: &str,
payload: Vec<u8>,
codec: &str,
) -> Result<RawResponse, OrleansError> {
let context = self.effective_context();
self.client
.invoke_raw(crate::client::InvokeCall {
interface_name: &self.interface_name,
grain_type: &self.grain_type,
key: &self.key,
method,
payload,
codec,
context: &context,
timeout: self.timeout,
})
.await
}
#[cfg(feature = "json")]
pub async fn invoke_json<Req, Resp>(
&self,
method: &str,
request: &Req,
) -> Result<Resp, OrleansError>
where
Req: serde::Serialize + ?Sized,
Resp: serde::de::DeserializeOwned,
{
Ok(self.invoke_json_with_context(method, request).await?.0)
}
#[cfg(feature = "json")]
pub async fn invoke_json_with_context<Req, Resp>(
&self,
method: &str,
request: &Req,
) -> Result<(Resp, std::collections::HashMap<String, String>), OrleansError>
where
Req: serde::Serialize + ?Sized,
Resp: serde::de::DeserializeOwned,
{
let payload =
serde_json::to_vec(request).map_err(|e| OrleansError::Serialization(e.to_string()))?;
let response = self.invoke(method, payload, "json").await?;
let value = serde_json::from_slice(&response.payload)
.map_err(|e| OrleansError::Serialization(e.to_string()))?;
Ok((value, response.response_context))
}
#[cfg(feature = "protobuf")]
pub async fn invoke_protobuf<Req, Resp>(
&self,
method: &str,
request: &Req,
) -> Result<Resp, OrleansError>
where
Req: prost::Message,
Resp: prost::Message + Default,
{
let payload = request.encode_to_vec();
let response = self.invoke(method, payload, "protobuf").await?;
Resp::decode(response.payload.as_slice())
.map_err(|e| OrleansError::Serialization(e.to_string()))
}
}