mod message;
mod worker;
use crate::Config;
use message::Message;
use worker::Worker;
pub type ResultSender = oneshot::Sender<Result<Value>>;
pub type TaskSender = mpsc::UnboundedSender<Message>;
pub type TaskReceiver = Arc<Mutex<mpsc::UnboundedReceiver<Message>>>;
use crate::Result;
use vk_method::Method;
use serde_json::value::Value;
use std::iter::ExactSizeIterator;
use std::sync::Arc;
use tokio::sync::{mpsc, oneshot, Mutex};
use http::request::Request;
use hyper::body::Body;
use tower::Service;
pub const MAX_METHODS_IN_EXECUTE: u8 = 25;
pub trait HttpsClient:
Service<Request<Body>, Response = http::Response<Body>, Error = hyper::Error>
+ Send
+ Sync
+ 'static
where
Self::Future: Send,
{
}
impl<T> HttpsClient for T
where
T: Service<Request<Body>, Response = http::Response<Body>, Error = hyper::Error>
+ Send
+ Sync
+ 'static,
Self::Future: Send,
{
}
pub type HyperClient = hyper::client::Client<HttpsConnector<HttpConnector>>;
use hyper::client::HttpConnector;
use hyper_tls::HttpsConnector;
pub struct Client<C: HttpsClient = HyperClient>
where
<C as Service<Request<Body>>>::Future: Send,
{
sender: TaskSender,
#[allow(dead_code)]
workers: Vec<Worker<C>>,
}
impl<C: HttpsClient> Client<C>
where
<C as Service<Request<Body>>>::Future: Send,
{
pub fn from_configs<Configs>(configs: Configs) -> Self
where
Configs: Iterator<Item = Config<C>> + ExactSizeIterator,
{
let mut workers = Vec::with_capacity(configs.len());
let (sender, receiver) = mpsc::unbounded_channel();
let receiver = Arc::new(Mutex::new(receiver));
for (index, config) in configs.into_iter().enumerate() {
workers.push(Worker::new(index, config, receiver.clone()));
}
Self { sender, workers }
}
pub async fn method(&self, method: Method) -> Result<Value> {
assert!(
!method.name.starts_with("execute"),
"Execute method is not allowed"
);
let (oneshot_sender, oneshot_receiver) = oneshot::channel();
self.sender
.send(Message::NewMethod(method, oneshot_sender))
.unwrap();
oneshot_receiver.await.unwrap()
}
}
#[cfg(feature = "thisvk")]
#[async_trait::async_trait]
impl<C: HttpsClient> thisvk::API for Client<C>
where
<C as Service<Request<Body>>>::Future: Send,
{
type Error = crate::Error;
async fn method<T>(&self, method: Method) -> Result<T>
where
for<'de> T: serde::Deserialize<'de>,
{
let value = self.method(method).await?;
Ok(serde_json::from_value(value).unwrap())
}
}