use super::subscriptions::SubscriptionResponse;
use super::{ProtocolHook, ResponseOrError, State};
use crate::errors::ProtocolError;
use crate::errors::Result;
use async_trait::async_trait;
use tokio::sync::RwLock;
use std::fmt::Debug;
use std::sync::Arc;
use crate::protocol::ErrorResponse;
#[async_trait]
pub trait NashProtocol: Debug + Send + Sync {
type Response: Debug + Send + Sync;
async fn acquire_permit(&self, _state: Arc<RwLock<State>>) -> Option<tokio::sync::OwnedSemaphorePermit> {
None
}
async fn graphql(&self, state: Arc<RwLock<State>>) -> Result<serde_json::Value>;
async fn response_from_json(
&self,
response: serde_json::Value,
state: Arc<RwLock<State>>
) -> Result<ResponseOrError<Self::Response>>;
async fn process_response(
&self,
_response: &Self::Response,
_state: Arc<RwLock<State>>,
) -> Result<()> {
Ok(())
}
async fn process_error(
&self,
_response: &ErrorResponse,
_state: Arc<RwLock<State>>,
) -> Result<()> {
Ok(())
}
async fn run_before(&self, _state: Arc<RwLock<State>>) -> Result<Option<Vec<ProtocolHook>>> {
Ok(None)
}
async fn run_after(&self, _state: Arc<RwLock<State>>) -> Result<Option<Vec<ProtocolHook>>> {
Ok(None)
}
}
#[async_trait]
pub trait NashProtocolPipeline: Debug + Send + Sync {
type PipelineState: Send + Sync;
type ActionType: NashProtocol;
async fn acquire_permit(&self, _state: Arc<RwLock<State>>) -> Option<tokio::sync::OwnedSemaphorePermit> {
None
}
async fn init_state(&self, state: Arc<RwLock<State>>) -> Self::PipelineState;
async fn next_step(
&self,
pipeline_state: &Self::PipelineState,
client_state: Arc<RwLock<State>>,
) -> Result<Option<Self::ActionType>>;
async fn process_step(
&self,
result: <<Self as NashProtocolPipeline>::ActionType as NashProtocol>::Response,
pipeline_state: &mut Self::PipelineState,
);
fn output(
&self,
pipeline_state: Self::PipelineState,
) -> Result<ResponseOrError<<Self::ActionType as NashProtocol>::Response>>;
async fn run_before(&self, _state: Arc<RwLock<State>>) -> Result<Option<Vec<ProtocolHook>>> {
Ok(None)
}
async fn run_after(&self, _state: Arc<RwLock<State>>) -> Result<Option<Vec<ProtocolHook>>> {
Ok(None)
}
}
#[async_trait]
impl<T> NashProtocolPipeline for T
where
T: NashProtocol + Clone + Sync + Send,
{
type PipelineState = Option<ResponseOrError<T::Response>>;
type ActionType = T;
async fn acquire_permit(&self, state: Arc<RwLock<State>>) -> Option<tokio::sync::OwnedSemaphorePermit> {
self.acquire_permit(state).await
}
async fn init_state(&self, _state: Arc<RwLock<State>>) -> Self::PipelineState {
None
}
async fn next_step(
&self,
pipeline_state: &Self::PipelineState,
_client_state: Arc<RwLock<State>>,
) -> Result<Option<Self::ActionType>> {
if let Some(_) = pipeline_state {
Ok(None)
}
else {
Ok(Some(self.clone()))
}
}
async fn process_step(
&self,
result: <<Self as NashProtocolPipeline>::ActionType as NashProtocol>::Response,
state: &mut Self::PipelineState,
) {
*state = Some(ResponseOrError::from_data(result));
}
fn output(&self, state: Self::PipelineState) -> Result<ResponseOrError<T::Response>> {
if let Some(state) = state {
Ok(state)
} else {
Err(ProtocolError(
"Protocol request not run, cannot retrieve output",
))
}
}
async fn run_before(&self, state: Arc<RwLock<State>>) -> Result<Option<Vec<ProtocolHook>>> {
self.run_before(state).await
}
async fn run_after(&self, state: Arc<RwLock<State>>) -> Result<Option<Vec<ProtocolHook>>> {
self.run_after(state).await
}
}
#[async_trait]
pub trait NashProtocolSubscription: Clone {
type SubscriptionResponse: Send + Sync;
async fn graphql(&self, state: Arc<RwLock<State>>) -> Result<serde_json::Value>;
async fn subscription_response_from_json(
&self,
response: serde_json::Value,
state: Arc<RwLock<State>>
) -> Result<ResponseOrError<Self::SubscriptionResponse>>;
async fn process_subscription_response(
&self,
_response: &Self::SubscriptionResponse,
_state: Arc<RwLock<State>>,
) -> Result<()> {
Ok(())
}
async fn wrap_response_as_any_subscription(
&self,
response: serde_json::Value,
state: Arc<RwLock<State>>
) -> Result<ResponseOrError<SubscriptionResponse>>;
}
#[async_trait]
pub trait TryFromState<T>: Sized {
async fn from(source: T, state: Arc<RwLock<State>>) -> Result<Self>;
}