use super::{
config::Config,
socket::{Socket, SocketClient},
WebsocketClient,
};
use crate::{
Auth, Client, GlimeshError, MutationConn, QueryConn, Subscription, SubscriptionConn,
WebsocketConnectionError,
};
use graphql_client::GraphQLQuery;
use std::{fmt::Debug, time::Duration};
#[derive(Debug, Default)]
pub struct ConnectionBuilder {
config: Config,
}
impl ConnectionBuilder {
pub async fn connect(self, auth: Auth) -> Result<Connection, WebsocketConnectionError> {
let mut socket = Socket::new(auth, self.config);
socket.connect().await?;
let socket_client = socket.client();
socket.stay_conected();
Ok(Connection {
socket: socket_client,
})
}
pub fn api_url(mut self, value: impl Into<String>) -> Self {
self.config.api_url = value.into();
self
}
pub fn version(mut self, value: impl Into<String>) -> Self {
self.config.version = value.into();
self
}
pub fn outgoing_capacity(mut self, value: usize) -> Self {
self.config.outgoing_capacity = value;
self
}
pub fn incoming_capacity(mut self, value: usize) -> Self {
self.config.incoming_capacity = value;
self
}
pub fn ping_interval(mut self, value: Duration) -> Self {
self.config.ping_interval = value;
self
}
pub fn request_timeout(mut self, value: Duration) -> Self {
self.config.request_timeout = value;
self
}
}
#[derive(Debug, Clone)]
pub struct Connection {
socket: SocketClient,
}
impl Connection {
pub fn builder() -> ConnectionBuilder {
ConnectionBuilder::default()
}
pub async fn connect(auth: Auth) -> Result<Self, WebsocketConnectionError> {
ConnectionBuilder::default().connect(auth).await
}
pub fn as_client(&self) -> Client<&Self> {
Client::new(self)
}
pub fn to_client(&self) -> WebsocketClient {
Client::new(self.clone())
}
pub fn into_client(self) -> WebsocketClient {
Client::new(self)
}
pub fn close(self) {
self.socket.close();
}
async fn request<Q>(
&self,
variables: Q::Variables,
) -> Result<Q::ResponseData, WebsocketConnectionError>
where
Q: graphql_client::GraphQLQuery,
{
let reply = self
.socket
.request(
"__absinthe__:control".into(),
"doc".into(),
Q::build_query(variables),
)
.await?;
let res: graphql_client::Response<Q::ResponseData> = reply.response;
if let Some(errs) = res.errors {
if !errs.is_empty() {
return Err(GlimeshError::GraphqlErrors(errs).into());
}
}
let data = res.data.ok_or(GlimeshError::NoData)?;
Ok(data)
}
}
#[async_trait]
impl QueryConn for Connection {
type Error = WebsocketConnectionError;
async fn query<Q>(&self, variables: Q::Variables) -> Result<Q::ResponseData, Self::Error>
where
Q: graphql_client::GraphQLQuery,
Q::Variables: Send + Sync,
{
self.request::<Q>(variables).await
}
}
#[async_trait]
impl MutationConn for Connection {
type Error = WebsocketConnectionError;
async fn mutate<Q>(&self, variables: Q::Variables) -> Result<Q::ResponseData, Self::Error>
where
Q: graphql_client::GraphQLQuery,
Q::Variables: Send + Sync,
{
self.request::<Q>(variables).await
}
}
#[async_trait]
impl SubscriptionConn for Connection {
type Error = WebsocketConnectionError;
async fn subscribe<Q>(
&self,
variables: Q::Variables,
) -> Result<Subscription<Q::ResponseData>, Self::Error>
where
Q: GraphQLQuery,
Q::Variables: Send + Sync,
{
self.socket.subscribe(Q::build_query(variables)).await
}
}