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