replace singal queue with command bus
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
775040be91
commit
659b44dfe6
@ -0,0 +1,47 @@
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use crate::bus::{Request, RequestEnvelope, ResponseEnvelope};
|
||||
use std::fmt::{Debug, Formatter, Error};
|
||||
|
||||
#[async_trait]
|
||||
pub trait RawBusClient: Send {
|
||||
async fn send(&mut self, request: RequestEnvelope) -> ResponseEnvelope;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BusClient(Arc<Mutex<BusClientState>>);
|
||||
|
||||
impl Debug for BusClient {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
write!(f, "BusClient()")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct BusClientState {
|
||||
id: u64,
|
||||
raw_client: Box<dyn RawBusClient>,
|
||||
}
|
||||
|
||||
impl BusClient {
|
||||
pub fn new(raw_client: Box<dyn RawBusClient>) -> BusClient {
|
||||
BusClient(Arc::new(Mutex::new(
|
||||
BusClientState {
|
||||
id: 0,
|
||||
raw_client,
|
||||
}
|
||||
)))
|
||||
}
|
||||
|
||||
pub async fn send(&mut self, request: Request) -> ResponseEnvelope {
|
||||
let mut state = self.0.lock().await;
|
||||
let id = state.id;
|
||||
state.id += 1;
|
||||
|
||||
let envelope = RequestEnvelope {
|
||||
id,
|
||||
request,
|
||||
};
|
||||
|
||||
state.raw_client.send(envelope).await
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
use crate::bus::{Response, RequestEnvelope};
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use std::fmt::{Formatter, Debug, Error};
|
||||
use futures::Stream;
|
||||
|
||||
#[async_trait]
|
||||
pub trait BusConnection: Send + Stream<Item=RequestEnvelope> + Unpin {
|
||||
async fn close(&mut self);
|
||||
async fn ack(&mut self, id: u64);
|
||||
async fn send(&mut self, id: u64, message: Response);
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Receiver(Arc<Mutex<Box<dyn RawReceiver>>>, String);
|
||||
|
||||
impl Debug for Receiver {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
write!(f, "Receiver {{ {} }}", self.1)
|
||||
}
|
||||
}
|
||||
|
||||
impl Receiver {
|
||||
pub fn new(receiver: Box<dyn RawReceiver>) -> Receiver {
|
||||
let name = receiver.name();
|
||||
Receiver(Arc::new(Mutex::new(receiver)), name.to_string())
|
||||
}
|
||||
|
||||
pub async fn get(&mut self) -> Option<Box<dyn BusConnection>> {
|
||||
self.0.lock().await.get().await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait RawReceiver: Send {
|
||||
fn name<'s>(&self) -> &'s str;
|
||||
async fn disconnect(&mut self);
|
||||
async fn get(&mut self) -> Option<Box<dyn BusConnection>>;
|
||||
}
|
@ -0,0 +1,99 @@
|
||||
use std::collections::HashMap;
|
||||
use crate::bus::{Response, BusConnection, RawReceiver, RequestEnvelope, ResponseEnvelope, RawBusClient};
|
||||
use crate::utils::asyn::{AsyncQueue, Deferred};
|
||||
use futures::Stream;
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use async_macros::utils::task::{Context, Poll};
|
||||
use async_macros::utils::pin::Pin;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProcessReceiver {
|
||||
state: Arc<Mutex<ProcessReceiverState>>,
|
||||
request_queue: AsyncQueue<RequestEnvelope>,
|
||||
}
|
||||
|
||||
impl ProcessReceiver {
|
||||
pub fn new() -> Self {
|
||||
ProcessReceiver {
|
||||
state: Arc::new(Mutex::new(ProcessReceiverState {
|
||||
id: 0,
|
||||
callbacks: Default::default(),
|
||||
registered_client: false,
|
||||
})),
|
||||
request_queue: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn run_callback(&mut self, id: u64, response: Option<Response>) {
|
||||
let mut state = self.state.lock().await;
|
||||
if let Some(mut deferred) = state.callbacks.remove(&id) {
|
||||
deferred.complete(ResponseEnvelope {
|
||||
id,
|
||||
response,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RawReceiver for ProcessReceiver {
|
||||
fn name<'s>(&self) -> &'s str {
|
||||
"in-process"
|
||||
}
|
||||
|
||||
async fn disconnect(&mut self) {}
|
||||
|
||||
async fn get(&mut self) -> Option<Box<dyn BusConnection>> {
|
||||
let mut state = self.state.lock().await;
|
||||
if state.registered_client {
|
||||
None
|
||||
} else {
|
||||
state.registered_client = true;
|
||||
let copy = Box::new(self.clone()) as Box<dyn BusConnection>;
|
||||
Some(copy)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct ProcessReceiverState {
|
||||
id: u64,
|
||||
callbacks: HashMap<u64, Deferred<ResponseEnvelope>>,
|
||||
registered_client: bool,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl BusConnection for ProcessReceiver {
|
||||
async fn close(&mut self) {}
|
||||
|
||||
async fn ack(&mut self, id: u64) {
|
||||
self.run_callback(id, None).await;
|
||||
}
|
||||
|
||||
async fn send(&mut self, id: u64, message: Response) {
|
||||
self.run_callback(id, Some(message)).await;
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for ProcessReceiver {
|
||||
type Item = RequestEnvelope;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
Stream::poll_next(unsafe { Pin::new_unchecked(&mut self.request_queue) }, cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl RawBusClient for ProcessReceiver {
|
||||
async fn send(&mut self, request: RequestEnvelope) -> ResponseEnvelope {
|
||||
let deferred = Deferred::new();
|
||||
let def_clone = deferred.clone();
|
||||
{
|
||||
let mut state = self.state.lock().await;
|
||||
state.callbacks.insert(request.id, def_clone);
|
||||
}
|
||||
|
||||
self.request_queue.push(request);
|
||||
deferred.await
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
mod client;
|
||||
mod server;
|
||||
mod connection;
|
||||
mod connection_process;
|
||||
mod connection_unix;
|
||||
|
||||
pub use client::*;
|
||||
pub use server::*;
|
||||
pub use connection::*;
|
||||
pub use connection_unix::*;
|
||||
pub use connection_process::*;
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct Response;
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct ResponseEnvelope {
|
||||
id: u64,
|
||||
response: Option<Response>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct Request;
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct RequestEnvelope {
|
||||
id: u64,
|
||||
request: Request,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct IncomingMessage {
|
||||
client: Client,
|
||||
request: RequestEnvelope,
|
||||
}
|
||||
|
||||
impl IncomingMessage {
|
||||
pub async fn ack(&mut self) {
|
||||
self.client.ack(self.request.id);
|
||||
}
|
||||
}
|
@ -0,0 +1,240 @@
|
||||
use async_std::sync::{Arc, Mutex};
|
||||
use crate::bus::{BusConnection, IncomingMessage, Receiver, BusClient, ProcessReceiver, RequestEnvelope, RawReceiver, Response};
|
||||
use std::collections::HashMap;
|
||||
use crate::utils::asyn::AsyncQueue;
|
||||
use async_std::task;
|
||||
use std::fmt::{Debug, Formatter, Error};
|
||||
use futures::{Stream, StreamExt};
|
||||
use std::task::{Context, Poll};
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BusServer {
|
||||
process_connection: ProcessReceiver,
|
||||
process_client: BusClient,
|
||||
state: Arc<Mutex<BusServerState>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct BusServerState {
|
||||
receivers: Vec<Receiver>,
|
||||
clients: ClientPool,
|
||||
message_queue: AsyncQueue<IncomingMessage>,
|
||||
}
|
||||
|
||||
impl BusServer {
|
||||
pub fn new() -> Self {
|
||||
let receiver = ProcessReceiver::new();
|
||||
BusServer {
|
||||
process_connection: receiver.clone(),
|
||||
process_client: BusClient::new(Box::new(receiver)),
|
||||
state: Arc::new(Mutex::new(BusServerState {
|
||||
receivers: vec![],
|
||||
clients: ClientPool::new(),
|
||||
message_queue: AsyncQueue::new(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn attach_process_receiver(&mut self) {
|
||||
let copy = Box::new(self.process_connection.clone()) as Box<dyn RawReceiver>;
|
||||
self.add_receiver(Receiver::new(copy)).await;
|
||||
}
|
||||
|
||||
pub async fn add_receiver(&mut self, receiver: Receiver) {
|
||||
let mut state = self.state.lock().await;
|
||||
state.receivers.push(receiver);
|
||||
}
|
||||
|
||||
pub async fn run(&mut self, handler: impl MessageHandler) {
|
||||
for receiver in &self.state.lock().await.receivers {
|
||||
let mut cloned_receiver = receiver.clone();
|
||||
let mut cloned_server = self.clone();
|
||||
|
||||
task::spawn(async move {
|
||||
while let Some(client) = cloned_receiver.get().await {
|
||||
cloned_server.register_client(client).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
self.message_handler(handler).await;
|
||||
}
|
||||
|
||||
async fn message_handler(&mut self, mut handler: impl MessageHandler) {
|
||||
let mut queue = {
|
||||
let state = self.state.lock().await;
|
||||
state.message_queue.clone()
|
||||
};
|
||||
|
||||
while let Some(message) = queue.next().await {
|
||||
handler.handle_message(message, self.clone()).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn register_client(&mut self, client: Box<dyn BusConnection>) {
|
||||
let mut state = self.state.lock().await;
|
||||
let mut client = state.clients.register_client(client, self.clone()).await;
|
||||
task::spawn(async move {
|
||||
client.listen().await
|
||||
});
|
||||
}
|
||||
|
||||
async fn queue(&self, message: IncomingMessage) {
|
||||
let mut queue = {
|
||||
let state = self.state.lock().await;
|
||||
state.message_queue.clone()
|
||||
};
|
||||
queue.push(message);
|
||||
}
|
||||
|
||||
pub fn get_process_client(&self) -> BusClient {
|
||||
self.process_client.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait MessageHandler {
|
||||
async fn handle_message(&mut self, message: IncomingMessage, server: BusServer);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ClientPool {
|
||||
state: Arc<Mutex<ClientMap>>
|
||||
}
|
||||
|
||||
impl ClientPool {
|
||||
async fn register_client(&mut self, client: Box<dyn BusConnection>, server: BusServer) -> Client {
|
||||
self.state.lock().await.register_client(client, server)
|
||||
}
|
||||
|
||||
pub fn new() -> Self {
|
||||
ClientPool { state: Arc::new(Mutex::new(ClientMap::new())) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ClientMap {
|
||||
id: u64,
|
||||
clients: HashMap<u64, Client>,
|
||||
}
|
||||
|
||||
impl ClientMap {
|
||||
fn new() -> ClientMap {
|
||||
ClientMap {
|
||||
id: 0,
|
||||
clients: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn register_client(&mut self, client: Box<dyn BusConnection>, server: BusServer) -> Client {
|
||||
let client_id = self.id;
|
||||
self.id += 1;
|
||||
self.clients.insert(client_id, Client {
|
||||
raw_client: Arc::new(Mutex::new(RawClient {
|
||||
_id: client_id,
|
||||
connection: client,
|
||||
})),
|
||||
bus_server: server,
|
||||
message_queue: AsyncQueue::new(),
|
||||
id: client_id,
|
||||
});
|
||||
|
||||
let client = self.clients.get(&client_id).unwrap();
|
||||
|
||||
client.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Debug for Client {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
|
||||
write!(f, "Client {{ #{} }}", self.id)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Client {
|
||||
raw_client: Arc<Mutex<RawClient>>,
|
||||
bus_server: BusServer,
|
||||
message_queue: AsyncQueue<Message>,
|
||||
id: u64,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Message {
|
||||
In(RequestEnvelope),
|
||||
Ack(u64),
|
||||
Response(u64, Response),
|
||||
Close,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
async fn listen(&mut self) {
|
||||
let client = self.raw_client.clone();
|
||||
|
||||
while let Some(message) = self.next().await {
|
||||
match message {
|
||||
Message::In(message) => self.handle_request(message).await,
|
||||
Message::Ack(id) => client.lock().await.connection.ack(id).await,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.raw_client.lock().await.close().await;
|
||||
}
|
||||
|
||||
async fn handle_request(&self, request: RequestEnvelope) {
|
||||
self.bus_server.queue(IncomingMessage {
|
||||
client: self.clone(),
|
||||
request,
|
||||
}).await;
|
||||
}
|
||||
|
||||
pub fn ack(&mut self, id: u64) {
|
||||
self.message_queue.push(Message::Ack(id));
|
||||
}
|
||||
|
||||
pub fn send(&mut self, id: u64, response: Response) {
|
||||
self.message_queue.push(Message::Response(id, response));
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for Client {
|
||||
type Item = Message;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
let queue_pin = unsafe { Pin::new_unchecked(&mut self.message_queue) };
|
||||
match Stream::poll_next(queue_pin, cx) {
|
||||
Poll::Ready(None) => return Poll::Ready(None),
|
||||
Poll::Ready(Some(message)) => return Poll::Ready(Some(message)),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut lock = self.raw_client.lock();
|
||||
if let Poll::Ready(mut client) = Future::poll(unsafe { Pin::new_unchecked(&mut lock) }, cx) {
|
||||
let connection_pin = unsafe { Pin::new_unchecked(&mut client.connection) };
|
||||
match Stream::poll_next(connection_pin, cx) {
|
||||
Poll::Ready(None) => return Poll::Ready(None),
|
||||
Poll::Ready(Some(message)) => return Poll::Ready(Some(Message::In(message))),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
struct RawClient {
|
||||
_id: u64,
|
||||
connection: Box<dyn BusConnection>,
|
||||
}
|
||||
|
||||
impl RawClient {
|
||||
async fn close(&mut self) {
|
||||
self.connection.close().await;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue