Compare commits

...

56 Commits

Author SHA1 Message Date
1d898b8257 Enable CI
All checks were successful
continuous-integration/drone/push Build is passing
2022-03-17 15:27:17 +04:00
73aeefb46f Rework idle detection 2021-12-16 16:12:28 +04:00
b06eac6504 Fix deadlock bug with flush 2021-12-03 15:30:13 +04:00
c9f03f5b49 AsyncProducer Handler update + version bump 2021-11-25 16:48:41 +04:00
c927dad70e Flush&Sync per message type; Rewrite select receivers; 2021-11-15 20:01:28 +04:00
18bd3c63f4 Tcp relay update; refactoring type tag 2021-11-05 18:39:25 +04:00
bc862cfac6 TCP Relay 2021-10-08 13:03:24 +04:00
1bff5cc70a try_clone 2021-09-29 15:00:35 +04:00
7034e8b87b Bump version 2021-09-28 16:42:09 +04:00
535c39c9dc Redis begin & fixes for QUIC 2021-09-28 15:19:44 +04:00
73763f8a9d add receiver id & remote quic progress 2021-09-24 19:46:23 +04:00
3a0a1019b6 fix message requirement 2021-09-24 13:13:29 +04:00
16690db44c revert upgrate to 2021 edition 2021-09-24 12:47:01 +04:00
bed35670c6 refactor senderror 2021-09-22 17:07:21 +04:00
5ba6f1139d Fix test_relay.rs 2021-09-22 16:53:21 +04:00
79a4441bfd Fix derive sharedmessage namespace 2021-09-22 16:50:30 +04:00
6ef65cbfd1 QUIC Relay progress 2021-09-22 16:48:28 +04:00
22d1d4a569 make clippy happy 2021-09-21 14:47:21 +04:00
9d014d38a1 Refacroting ReciveTypedReceiver 2021-09-20 19:31:06 +04:00
ce64f7f4bc fmt + bechmark example 2021-09-20 17:20:00 +04:00
5c03068c79 QUIC Client Relay progress 2021-09-16 19:04:34 +04:00
a0544f01e4 MessageBus Remote split out; crate reorganization 2021-09-16 16:51:13 +04:00
c9ea551e0d remove sync deadline 2021-09-16 13:57:47 +04:00
ac12bb08ab cleanup receivers 2021-09-16 13:19:28 +04:00
81e5376fe2 refactoring receivers +speed ++clean 2021-09-15 19:54:59 +04:00
da6dc04f71 fix major bug with sync& version bump 2021-09-15 13:33:25 +04:00
21e28ffa12 fix flush 2021-09-07 19:02:29 +04:00
e81a70a197 version bump 2021-09-03 18:57:09 +04:00
c2e67bfcbd minor gug fixes 2021-09-03 18:46:56 +04:00
73cf59afb8 add request_boxed_we 2021-08-20 17:18:56 +04:00
7332c04e53 Add request_boxed_we 2021-08-12 13:16:30 +04:00
6d8dd039b3 Derive TypeTagged correctly 2021-08-10 14:24:28 +04:00
ba67c8251d Add TypeTagged bound for Message derive generics 2021-08-09 18:27:25 +04:00
c47657177c Init event & relays continue 2021-08-04 19:14:56 +04:00
db34774acd Quic relay begin 2021-08-03 13:41:30 +04:00
9a887d4821 Relays + example (test) 2021-07-30 16:59:14 +04:00
3bb2fe7492 Relays: rewrite relay trat 2021-07-29 17:23:08 +04:00
993ff4a46d Relay unification with Receivers 2021-07-23 17:29:47 +04:00
640a8ceee1 SerDe Messages and RelayTrait update 2021-07-20 16:04:10 +04:00
13d1d48a70 Relays: Message and SharedMessage; messagebus_derive 2021-07-16 20:21:27 +04:00
76cc57e7ae Generalize over batch type; subscribe_{sync|async} methods; relays begin 2021-07-02 20:21:53 +04:00
308939801b Add CHANGELOG.md 2021-06-29 13:41:51 +04:00
908059d8c9 Add send_one, send_one_blocked, try_send_one 2021-06-29 13:25:03 +04:00
48756264b8 Cleanup 2021-06-28 19:39:58 +04:00
655fdf8462 Add modules 2021-06-28 19:37:53 +04:00
f51433557e Update error handling 2021-06-28 17:49:34 +04:00
3e0f21153d Update error handling for request/response 2021-06-28 17:41:00 +04:00
2f4a267d09 Update version and README.md 2021-06-24 14:14:53 +04:00
d051922a29 Batched Handlers 2021-06-24 13:32:19 +04:00
dc4bb94ec5 Fix race condition 2021-06-23 16:20:10 +04:00
500e1ce178 Synchronized handlers 2021-06-22 21:04:49 +04:00
db1d22df7f Request/Response 2021-06-22 18:43:06 +04:00
cf0a50a445 Refactoring Receivers' 2021-06-22 13:15:27 +04:00
dc56bd8a8d Message response and error types; fix issues 2021-06-18 21:01:13 +04:00
6b24f39c50 Fix some unwaked receivers 2021-06-09 20:07:22 +04:00
Andrey Tkachenko
b86509178e Bump up tokio 2021-02-01 13:46:06 +04:00
69 changed files with 9349 additions and 2279 deletions

14
.drone.yml Normal file
View File

@ -0,0 +1,14 @@
kind: pipeline
name: default
steps:
- name: build
image: rust
commands:
- cargo build --verbose --all
- name: fmt-check
image: rust
commands:
- rustup component add rustfmt
- cargo fmt --all -- --check

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/target /target
/crates/*/target
Cargo.lock Cargo.lock

58
CHANGELOG.md Normal file
View File

@ -0,0 +1,58 @@
## MewssageBus pending changes:
### 0.8.0
#### new features:
* Generator Handlers
* Message Masking
### 0.7.0
#### new features:
* Bus scopes (`enter` and `leave` methods) instead clone
* Bus relays. Connect other message bus by IP address
#### breaking changes:
* Batched handlers now require `InBatch` and `OutBatch` types
## MewssageBus changelog:
### 0.6.5
#### new features:
* the `Message` trait no more required to be `Clone`
* added methods `send_one`, `send_one_blocked`, `try_send_one` which does not require `Message: Clone`
### 0.6.4
#### new features:
* added struct `Module` and `BusBuilder::add_module`
### 0.6.3
#### fixes:
* Update Error Handling
#### breaking changes:
* all methods now return `messagenus::Error`
### 0.6.2
#### new features:
* add `request_we` for requests when we know the handler's error type
#### fixes:
* Update Error Handling
#### breaking changes:
* send methods now return `messagenus::SendError`
#### notes:
* Got rid of `anyhow::Error`
### 0.6.0
#### new features:
* Request/Response API (request method)
#### fixes:
* Fix some unwaked receivers
#### breaking changes:
* Add `type Response` and `type Error` into all handlers
#### notes:
* Refactorin Receivers API

View File

@ -1,6 +1,6 @@
[package] [package]
name = "messagebus" name = "messagebus"
version = "0.4.6" version = "0.9.13"
authors = ["Andrey Tkachenko <andrey@aidev.ru>"] authors = ["Andrey Tkachenko <andrey@aidev.ru>"]
repository = "https://github.com/andreytkachenko/messagebus.git" repository = "https://github.com/andreytkachenko/messagebus.git"
keywords = ["futures", "async", "tokio", "message", "bus"] keywords = ["futures", "async", "tokio", "message", "bus"]
@ -10,13 +10,34 @@ license = "MIT OR Apache-2.0"
exclude = [".gitignore", ".cargo/config", ".github/**", "codecov.yml"] exclude = [".gitignore", ".cargo/config", ".github/**", "codecov.yml"]
edition = "2018" edition = "2018"
[workspace]
members = ["crates/remote", "crates/derive"]
[dependencies] [dependencies]
tokio = { version = "0.2", features = ["parking_lot", "rt-threaded", "sync", "stream", "blocking"] } messagebus_derive = "0.2.5"
parking_lot = "0.11.1"
async-trait = "0.1.42" tokio = { version = "1", features = ["parking_lot", "rt-multi-thread", "sync", "time"] }
futures = "0.3.8" parking_lot = "0.11"
anyhow = "1.0.34" async-trait = "0.1"
crossbeam = "0.8.0" futures = "0.3"
smallvec = "1.6"
log = "0.4"
sharded-slab = "0.1"
thiserror = "1"
erased-serde = "0.3"
serde = "1"
serde_derive = "1"
dashmap = "4.0"
ctor = "0.1.21"
[dev-dependencies] [dev-dependencies]
tokio = { version = "0.2", features = ["parking_lot", "rt-threaded", "sync", "stream", "macros"] } anyhow = "1.0"
env_logger = "0.9"
serde_json = "1.0"
tokio = { version = "1", features = [
"macros",
"parking_lot",
"rt-multi-thread",
"io-util",
"sync",
] }

154
README.md
View File

@ -11,67 +11,118 @@ Inspired by Actix
### Basics ### Basics
1. Can deliver messages between actors using receivers (usually a queue implementations) 1. Can deliver messages between actors using receivers (usually a queue implementations)
2. Messages distincts and delivers by TypeId 2. Messages distincts and delivers by TypeId
3. Messages delivers in a broadcast fashion to many receivers (Cloned) 3. Messages delivers ether in a broadcast fashion to many receivers (Cloned) or addressed by recevier id, balanced (depends on queue load) or random
4. There are different kind of receivers implemented: 4. There are different kind of receivers implemented:
- BufferUnordered Receiver (in sync and async version depending by handler) - BufferUnordered Receiver (sync and async)
- Synchronized (also sync and async) if receiving part needs syncronization - Synchronized (sync and async)
- SynchronizeBuffered (also sync and async) - BatchedBufferUnordered Receiver (sync and async)
here are the implmented handlers definitions: - BatchedSynchronized (sync and async)
```rust 5. Request/response api. There is an example is [demo_req_resp.rs](./examples/demo_req_resp.rs)
// Handler is Sync and we can spawn many of concurrent tasks Here are the list of implmented handler kinds:
```rust
pub trait Handler<M: Message>: Send + Sync { pub trait Handler<M: Message>: Send + Sync {
fn handle(&self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
fn sync(&self, _bus: &Bus) -> anyhow::Result<()> {Ok(())} type Response: Message;
fn handle(&self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
} }
#[async_trait] #[async_trait]
pub trait AsyncHandler<M: Message>: Send + Sync { pub trait AsyncHandler<M: Message>: Send + Sync {
async fn handle(&self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
async fn sync(&self, _bus: &Bus) -> anyhow::Result<()> {Ok(())} type Response: Message;
async fn handle(&self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
} }
// Handler is not Sync and we cannot spawn many of concurrent tasks same time (uses synchronization primitives such as Mutex or RwLock)
pub trait SynchronizedHandler<M: Message>: Send { pub trait SynchronizedHandler<M: Message>: Send {
fn handle(&mut self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> {Ok(())} type Response: Message;
fn handle(&mut self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
} }
#[async_trait] #[async_trait]
pub trait AsyncSynchronizedHandler<M: Message>: Send { pub trait AsyncSynchronizedHandler<M: Message>: Send {
async fn handle(&mut self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
async fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> {Ok(())} type Response: Message;
async fn handle(&mut self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
async fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
}
pub trait BatchHandler<M: Message>: Send + Sync {
type Error: StdSyncSendError + Clone;
type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
fn handle(&self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
}
#[async_trait]
pub trait AsyncBatchHandler<M: Message>: Send + Sync {
type Error: StdSyncSendError + Clone;
type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
async fn handle(&self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
} }
// Handler is not Sync and handler will process items in batched mode
pub trait BatchSynchronizedHandler<M: Message>: Send { pub trait BatchSynchronizedHandler<M: Message>: Send {
fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> {Ok(())} type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
fn handle(&mut self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
} }
#[async_trait] #[async_trait]
pub trait AsyncBatchSynchronizedHandler<M: Message>: Send { pub trait AsyncBatchSynchronizedHandler<M: Message>: Send {
async fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
async fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> {Ok(())} type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
async fn handle(&mut self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
async fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(())
}
} }
``` ```
4. Handler Kinds: 6. Implemented handler kinds:
1. No Synchronization needed (Handler is `Send` + `Sync`) 1. No Synchronization needed (Handler implements `Send` and `Sync`)
* Not batched operations **(implemented)** * Not batched operations
- sync (spawn_blocking) - sync (spawn_blocking)
- async (spawn) - async (spawn)
* Batched * Batched
- sync (spawn_blocking) - sync (spawn_blocking)
- async (spawn) - async (spawn)
2. Synchronization needed (Handler is `Sync` + `!Send`) 2. Synchronization needed (Handler implements only `Send` but not implements `Sync`)
* Not batched operations **(implemented)**
- sync (spawn_blocking)
- async (spawn)
* Batched **(implemented)**
- sync (spawn_blocking)
- async (spawn)
3. Synchronization needed and thread dedicated (Handler is `!Sync` + `!Send`)
* Not batched operations * Not batched operations
- sync (spawn_blocking) - sync (spawn_blocking)
- async (spawn) - async (spawn)
@ -79,16 +130,28 @@ pub trait AsyncBatchSynchronizedHandler<M: Message>: Send {
- sync (spawn_blocking) - sync (spawn_blocking)
- async (spawn) - async (spawn)
5. Example: 7. Not yet implemented handler kinds:
1. Synchronization needed and thread dedicated (Handler is `!Sync` and `!Send`)
* Not batched operations
- sync (spawn_blocking)
- async (spawn)
* Batched
- sync (spawn_blocking)
- async (spawn)
8. Example:
```rust ```rust
use messagebus::{Bus, AsyncHandler, Result as MbusResult, receivers}; use messagebus::{error::Error, receivers, AsyncHandler, Bus};
use async_trait::async_trait; use async_trait::async_trait;
struct TmpReceiver; struct TmpReceiver;
#[async_trait] #[async_trait]
impl AsyncHandler<i32> for TmpReceiver { impl AsyncHandler<i32> for TmpReceiver {
async fn handle(&self, msg: i32, bus: &Bus) -> MbusResult { type Error = Error;
type Response = ();
async fn handle(&self, msg: i32, bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> i32 {}", msg); println!("---> i32 {}", msg);
bus.send(2i64).await?; bus.send(2i64).await?;
@ -99,7 +162,10 @@ impl AsyncHandler<i32> for TmpReceiver {
#[async_trait] #[async_trait]
impl AsyncHandler<i64> for TmpReceiver { impl AsyncHandler<i64> for TmpReceiver {
async fn handle(&self, msg: i64, _bus: &Bus) -> MbusResult { type Error = Error;
type Response = ();
async fn handle(&self, msg: i64, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> i64 {}", msg); println!("---> i64 {}", msg);
Ok(()) Ok(())
@ -110,12 +176,22 @@ impl AsyncHandler<i64> for TmpReceiver {
async fn main() { async fn main() {
let (b, poller) = Bus::build() let (b, poller) = Bus::build()
.register(TmpReceiver) .register(TmpReceiver)
.subscribe::<i32, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe::<i32, receivers::BufferUnorderedAsync<_>, _, _>(8, Default::default())
.subscribe::<i64, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe::<i64, receivers::BufferUnorderedAsync<_>, _, _>(8, Default::default())
.done() .done()
.build(); .build();
b.send(1i32).await.unwrap(); b.send(1i32).await.unwrap();
poller.await
println!("flush");
b.flush().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
} }
``` ```

19
crates/derive/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "messagebus_derive"
version = "0.2.5"
authors = ["Andrey Tkachenko <andrey@aidev.ru>"]
repository = "https://github.com/andreytkachenko/messagebus.git"
keywords = ["futures", "async", "tokio", "message", "bus"]
categories = ["network-programming", "asynchronous"]
description = "MessageBus allows intercommunicate with messages between modules"
license = "MIT OR Apache-2.0"
exclude = [".gitignore", ".cargo/config", ".github/**", "codecov.yml"]
edition = "2018"
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
syn = {version = "1", features = ["full"]}

350
crates/derive/src/lib.rs Normal file
View File

@ -0,0 +1,350 @@
#![recursion_limit = "128"]
extern crate proc_macro;
// use proc_macro::{TokenStream};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, ToTokens};
use std::collections::hash_map;
use std::fmt::Write;
use std::hash::Hasher;
use syn::parse::{Parse, ParseStream};
use syn::{parenthesized, Result};
use syn::{punctuated::Punctuated, token::Comma, DeriveInput};
fn shared_part(_ast: &syn::DeriveInput, has_shared: bool) -> proc_macro2::TokenStream {
if has_shared {
quote! {
fn as_shared_ref(&self) -> std::option::Option<&dyn messagebus::SharedMessage> {Some(self)}
fn as_shared_mut(&mut self) -> std::option::Option<&mut dyn messagebus::SharedMessage>{Some(self)}
fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn messagebus::SharedMessage>, Box<dyn messagebus::Message>> {Ok(self)}
fn as_shared_arc(self: std::sync::Arc<Self>) -> Option<std::sync::Arc<dyn messagebus::SharedMessage>>{Some(self)}
}
} else {
quote! {
fn as_shared_ref(&self) -> std::option::Option<&dyn messagebus::SharedMessage> {None}
fn as_shared_mut(&mut self) -> std::option::Option<&mut dyn messagebus::SharedMessage> {None}
fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn messagebus::SharedMessage>, Box<dyn messagebus::Message>> {Err(self)}
fn as_shared_arc(self: std::sync::Arc<Self>) -> Option<std::sync::Arc<dyn messagebus::SharedMessage>> {None}
}
}
}
fn clone_part(ast: &syn::DeriveInput, has_clone: bool) -> proc_macro2::TokenStream {
let name = &ast.ident;
let (_, ty_generics, _) = ast.generics.split_for_impl();
if has_clone {
quote! {
fn try_clone_into(&self, into: &mut dyn core::any::Any) -> bool {
let into = if let Some(inner) = into.downcast_mut::<Option<#name #ty_generics>>() {
inner
} else {
return false;
};
into.replace(core::clone::Clone::clone(self));
true
}
fn try_clone_boxed(&self) -> std::option::Option<std::boxed::Box<dyn messagebus::Message>>{
Some(Box::new(core::clone::Clone::clone(self)))
}
fn try_clone(&self) -> Option<Self> {
Some(core::clone::Clone::clone(self))
}
}
} else {
quote! {
fn try_clone_into(&self, into: &mut dyn core::any::Any) -> bool {false}
fn try_clone_boxed(&self) -> std::option::Option<std::boxed::Box<dyn messagebus::Message>>{ None }
fn try_clone(&self) -> Option<Self> { None }
}
}
}
fn type_tag_part(
ast: &syn::DeriveInput,
type_tag: Option<String>,
namespace: Option<String>,
) -> proc_macro2::TokenStream {
let class_name = &ast.ident;
let name = if let Some(tt) = type_tag {
tt
} else if let Some(ns) = namespace {
format!("{}::{}", ns, class_name)
} else {
class_name.to_string()
};
let (_, ty_generics, where_clause) = ast.generics.split_for_impl();
let mut impl_generics = ast.generics.clone();
let mut type_name = String::new();
let mut type_values = String::from("(");
let mut need_close = false;
write!(&mut type_name, "{}", name).unwrap();
for mut param in impl_generics.params.pairs_mut() {
match &mut param.value_mut() {
syn::GenericParam::Lifetime(_) => continue,
syn::GenericParam::Type(param) => {
if !need_close {
type_name.push('<');
need_close = true;
} else {
type_name.push(',');
type_values.push(',');
}
type_name.push_str("{}");
write!(
&mut type_values,
"<{} as messagebus::TypeTagged>::type_tag_()",
param.ident
)
.unwrap();
let bound: syn::TypeParamBound = syn::parse_str("messagebus::TypeTagged").unwrap();
param.bounds.push(bound);
}
syn::GenericParam::Const(_param) => {
unimplemented!()
}
}
}
if need_close {
type_name.push('>');
}
if type_values.len() > 1 {
type_values.push_str(",)");
let type_values: syn::ExprTuple = syn::parse_str(&type_values).unwrap();
let type_values = type_values.elems;
quote! {
impl #impl_generics messagebus::TypeTagged for #class_name #ty_generics #where_clause {
fn type_tag_() -> messagebus::TypeTag { format!(#type_name, #type_values).into() }
fn type_tag(&self) -> messagebus::TypeTag { Self::type_tag_() }
fn type_name(&self) -> std::borrow::Cow<str> { Self::type_tag_() }
fn type_layout(&self) -> std::alloc::Layout { std::alloc::Layout::for_value(self) }
}
}
} else {
quote! {
impl #impl_generics messagebus::TypeTagged for #class_name #ty_generics #where_clause {
fn type_tag_() -> messagebus::TypeTag { #type_name.into() }
fn type_tag(&self) -> messagebus::TypeTag { Self::type_tag_() }
fn type_name(&self) -> std::borrow::Cow<str> { Self::type_tag_() }
fn type_layout(&self) -> std::alloc::Layout { std::alloc::Layout::for_value(self) }
}
}
}
}
struct TypeTag {
pub inner: syn::LitStr,
}
impl Parse for TypeTag {
fn parse(input: ParseStream) -> Result<Self> {
let content;
parenthesized!(content in input);
let punctuated = Punctuated::<syn::LitStr, Comma>::parse_terminated(&content)?;
let inner = punctuated.pairs().map(|x| x.into_value()).next();
Ok(TypeTag {
inner: inner.unwrap().to_owned(),
})
}
}
#[derive(Default, Debug)]
struct Tags {
has_clone: bool,
has_shared: bool,
}
impl Tags {
pub fn add(&mut self, other: Tags) {
self.has_clone = self.has_clone || other.has_clone;
self.has_shared = self.has_shared || other.has_shared;
}
}
impl Parse for Tags {
fn parse(input: ParseStream) -> Result<Self> {
let mut has_shared = false;
let mut has_clone = false;
let content;
parenthesized!(content in input);
let punctuated = Punctuated::<syn::Ident, Comma>::parse_terminated(&content)?;
for pair in punctuated.pairs() {
let val = pair.into_value().to_string();
match val.as_str() {
"shared" => has_shared = true,
"clone" => has_clone = true,
_ => (),
}
}
Ok(Tags {
has_clone,
has_shared,
})
}
}
#[proc_macro_derive(Message, attributes(type_tag, message, namespace))]
pub fn derive_message(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let mut tags = Tags::default();
let mut type_tag = None;
let mut namespace = None;
let ast: DeriveInput = syn::parse(input).unwrap();
let name = &ast.ident;
let (_, ty_generics, where_clause) = ast.generics.split_for_impl();
for attr in &ast.attrs {
if let Some(i) = attr.path.get_ident() {
match i.to_string().as_str() {
"message" => {
let tt: Tags = syn::parse2(attr.tokens.clone()).unwrap();
tags.add(tt);
}
"type_tag" => {
let tt: TypeTag = syn::parse2(attr.tokens.clone()).unwrap();
type_tag = Some(tt.inner.value());
}
"namespace" => {
let tt: TypeTag = syn::parse2(attr.tokens.clone()).unwrap();
namespace = Some(tt.inner.value());
}
_ => (),
}
}
}
let mut impl_generics = ast.generics.clone();
for mut param in impl_generics.params.pairs_mut() {
match &mut param.value_mut() {
syn::GenericParam::Lifetime(_) => {}
syn::GenericParam::Type(params) => {
let bound: syn::TypeParamBound =
syn::parse_str("messagebus::MessageBounds").unwrap();
params.bounds.push(bound);
if tags.has_shared {
let bound: syn::TypeParamBound =
syn::parse_str("messagebus::__reexport::serde::Serialize").unwrap();
params.bounds.push(bound);
let bound: syn::TypeParamBound =
syn::parse_str("messagebus::__reexport::serde::Deserialize<'de>").unwrap();
params.bounds.push(bound);
}
if tags.has_clone {
let bound: syn::TypeParamBound = syn::parse_str("core::clone::Clone").unwrap();
params.bounds.push(bound);
}
}
syn::GenericParam::Const(_) => {}
}
}
let type_tag_part = type_tag_part(&ast, type_tag, namespace);
let shared_part = shared_part(&ast, tags.has_shared);
let clone_part = clone_part(&ast, tags.has_clone);
let init = Ident::new(
&format!("__init_{}", hash(ast.clone().into_token_stream())),
Span::call_site(),
);
let init_impl = if tags.has_shared && impl_generics.params.is_empty() {
quote! {
#[allow(non_upper_case_globals)]
#[messagebus::ctor::ctor]
fn #init() {
messagebus::register_shared_message::<#name>();
}
}
} else {
quote! {}
};
if !impl_generics.params.is_empty() && tags.has_shared {
impl_generics
.params
.push(syn::GenericParam::Lifetime(syn::LifetimeDef::new(
syn::Lifetime::new("'de", Span::call_site()),
)))
}
let tokens = quote! {
#type_tag_part
impl #impl_generics messagebus::Message for #name #ty_generics #where_clause {
fn as_any_ref(&self) -> &dyn core::any::Any {self}
fn as_any_mut(&mut self) -> &mut dyn core::any::Any {self}
fn as_any_boxed(self: std::boxed::Box<Self>) -> std::boxed::Box<dyn core::any::Any> {self}
fn as_any_arc(self: std::sync::Arc<Self>) -> std::sync::Arc<dyn core::any::Any> {self}
#shared_part
#clone_part
}
#init_impl
};
tokens.into()
}
#[proc_macro_derive(Error, attributes(type_tag, namespace))]
pub fn derive_error(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let mut type_tag = None;
let mut namespace = None;
let ast: DeriveInput = syn::parse(input).unwrap();
for attr in &ast.attrs {
if let Some(i) = attr.path.get_ident() {
match i.to_string().as_str() {
"type_tag" => {
let tt: TypeTag = syn::parse2(attr.tokens.clone()).unwrap();
type_tag = Some(tt.inner.value());
}
"namespace" => {
let tt: TypeTag = syn::parse2(attr.tokens.clone()).unwrap();
namespace = Some(tt.inner.value());
}
_ => (),
}
}
}
let type_tag_part = type_tag_part(&ast, type_tag, namespace);
let tokens = quote! {
#type_tag_part
};
tokens.into()
}
fn hash(input: TokenStream) -> u64 {
let mut hasher = hash_map::DefaultHasher::new();
hasher.write(input.to_string().as_bytes());
hasher.finish()
}

44
crates/remote/Cargo.toml Normal file
View File

@ -0,0 +1,44 @@
[package]
name = "messagebus_remote"
version = "0.1.0"
authors = ["Andrey Tkachenko <andrey@aidev.ru>"]
repository = "https://github.com/andreytkachenko/messagebus.git"
keywords = ["futures", "async", "tokio", "message", "bus", "quic", "remote", "rpc", "parallel", "computing"]
categories = ["network-programming", "asynchronous"]
description = "MessageBus remote allows intercommunicate by messages between instances"
license = "MIT OR Apache-2.0"
exclude = [".gitignore", ".cargo/config", ".github/**", "codecov.yml"]
edition = "2018"
# [features]
# quic = ["quinn"]
[dependencies]
thiserror = "1.0"
messagebus = { path = "../../" }
tokio = { version = "1", features = ["parking_lot", "rt-multi-thread", "sync", "time", "io-util"] }
parking_lot = "0.11"
quinn = "0.7"
rmp = "0.8.10"
rmp-serde = "0.15.5"
erased-serde = "0.3.16"
serde_derive = "1.0.130"
serde = "1.0.130"
futures = "0.3.17"
cbor = "0.4.1"
serde_cbor = "0.11.2"
bytes = "1.1.0"
quinn-proto = "0.7.3"
rustls = "0.19.1"
redis = {version = "0.21.2", features = ["aio", "tokio-comp"]}
bitflags = "1.2.1"
serde_json = "1.0.68"
log = "0.4.14"
[dev-dependencies]
anyhow = "1.0.44"
async-trait = "0.1.51"
thiserror = "1.0.29"
tokio = { version = "1.11.0", features = ["full"] }
# quinn = { version = "0.7", optional = true }

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,60 @@
use messagebus::derive::Message;
use messagebus::error::GenericError;
use messagebus::{Bus, TypeTagged};
use messagebus_remote::relays::QuicClientRelay;
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Req {
data: i32,
text: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Resp {
data: i32,
text: String,
}
#[tokio::main]
async fn main() {
let relay = QuicClientRelay::new(
"./examples/cert.der",
"127.0.0.1:8083".parse().unwrap(),
"localhost".into(),
(
vec![(
Req::type_tag_(),
Some((Resp::type_tag_(), GenericError::type_tag_())),
)],
vec![],
),
)
.unwrap();
let (b, poller) = Bus::build().register_relay(relay).build();
b.ready().await;
println!("ready");
let resp: Resp = b
.request(
Req {
data: 12,
text: String::from("test"),
},
Default::default(),
)
.await
.unwrap();
println!("resp {:?}", resp);
b.flush_all().await;
b.close().await;
poller.await;
}

View File

@ -0,0 +1,88 @@
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error::{self, GenericError},
AsyncHandler, Bus, Message, TypeTagged,
};
use messagebus_remote::relays::QuicServerRelay;
use serde_derive::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Req {
data: i32,
text: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Resp {
data: i32,
text: String,
}
struct TmpReceiver;
#[async_trait]
impl AsyncHandler<Req> for TmpReceiver {
type Error = Error;
type Response = Resp;
async fn handle(&self, msg: Req, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver::handle {:?}", msg);
Ok(Resp {
data: msg.data + 12,
text: format!("<< {} >>", msg.text),
})
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver::sync");
Ok(())
}
}
#[tokio::main]
async fn main() {
let relay = QuicServerRelay::new(
"./examples/cert.key",
"./examples/cert.der",
"0.0.0.0:8083".parse().unwrap(),
(
vec![],
vec![(
Req::type_tag_(),
Some((Resp::type_tag_(), GenericError::type_tag_())),
)],
),
)
.unwrap();
let (b, poller) = Bus::build()
.register_relay(relay)
.register(TmpReceiver)
.subscribe_async::<Req>(8, Default::default())
.done()
.build();
b.ready().await;
println!("ready");
poller.await;
}

View File

@ -0,0 +1,58 @@
use messagebus::derive::Message;
use messagebus::error::GenericError;
use messagebus::{Bus, TypeTagged};
use messagebus_remote::relays::TcpRelay;
use serde_derive::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Req {
data: i32,
text: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Resp {
data: i32,
text: String,
}
#[tokio::main]
async fn main() {
let relay = TcpRelay::new(
false,
"0.0.0.0:8083".parse().unwrap(),
(
vec![(
Req::type_tag_(),
Some((Resp::type_tag_(), GenericError::type_tag_())),
)],
vec![],
),
);
let (b, poller) = Bus::build().register_relay(relay).build();
b.ready().await;
println!("ready");
let resp: Resp = b
.request(
Req {
data: 12,
text: String::from("test"),
},
Default::default(),
)
.await
.unwrap();
println!("resp {:?}", resp);
b.flush_all().await;
b.close().await;
poller.await;
}

View File

@ -0,0 +1,86 @@
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error::{self, GenericError},
AsyncHandler, Bus, Message, TypeTagged,
};
use messagebus_remote::relays::TcpRelay;
use serde_derive::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Req {
data: i32,
text: String,
}
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("example")]
#[message(shared, clone)]
pub struct Resp {
data: i32,
text: String,
}
struct TmpReceiver;
#[async_trait]
impl AsyncHandler<Req> for TmpReceiver {
type Error = Error;
type Response = Resp;
async fn handle(&self, msg: Req, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver::handle {:?}", msg);
Ok(Resp {
data: msg.data + 12,
text: format!("<< {} >>", msg.text),
})
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver::sync");
Ok(())
}
}
#[tokio::main]
async fn main() {
let relay = TcpRelay::new(
true,
"0.0.0.0:8083".parse().unwrap(),
(
vec![],
vec![(
Req::type_tag_(),
Some((Resp::type_tag_(), GenericError::type_tag_())),
)],
),
);
let (b, poller) = Bus::build()
.register_relay(relay)
.register(TmpReceiver)
.subscribe_async::<Req>(8, Default::default())
.done()
.build();
b.ready().await;
println!("ready");
poller.await;
}

View File

@ -0,0 +1,45 @@
use quinn::{ConnectError, ConnectionError, EndpointError, ParseError, ReadToEndError, WriteError};
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("IO Error: {0}")]
Io(#[from] std::io::Error),
// #[error("ReadToEnd: {0}")]
// ReadToEnd(#[from] ReadToEndError),
#[error("ConnectionError: {0}")]
ConnectionError(#[from] ConnectionError),
#[error("ConnectError: {0}")]
ConnectError(#[from] ConnectError),
#[error("EndpointError: {0}")]
EndpointError(#[from] EndpointError),
#[error("WriteError: {0}")]
WriteError(#[from] WriteError),
#[error("ReadToEndError: {0}")]
ReadToEndError(#[from] ReadToEndError),
#[error("QuinnConnectError: {0}")]
QuinnParseError(#[from] ParseError),
#[error("ConfigError: {0}")]
ConfigError(#[from] quinn_proto::ConfigError),
#[error("TLSError: {0}")]
TLSError(#[from] rustls::TLSError),
#[error("Redis: {0}")]
Redis(#[from] redis::RedisError),
#[error("ProtocolParseError {0}")]
ProtocolParseError(String),
#[error("UnknownCodec")]
UnknownCodec,
#[error("SerdeErased {0}")]
SerdeErased(#[from] erased_serde::Error),
}

3
crates/remote/src/lib.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod error;
pub mod proto;
pub mod relays;

530
crates/remote/src/proto.rs Normal file
View File

@ -0,0 +1,530 @@
use messagebus::{Action, Bus, Event, SharedMessage, TypeTag};
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
#[derive(Debug, Deserialize, Serialize)]
#[repr(u16)]
pub enum ProtocolHeaderActionKind {
Nop,
Error,
Send,
Response,
BatchComplete,
Flush,
Flushed,
Synchronize,
Synchronized,
Close,
Exited,
Initialize,
Ready,
Pause,
}
#[derive(Debug, Copy, Clone, Deserialize, Serialize)]
#[non_exhaustive]
#[repr(u32)]
pub enum BodyType {
None,
Utf8,
Cbor,
MessagePack,
Json,
Bson,
}
bitflags::bitflags! {
#[derive(Deserialize, Serialize)]
pub struct ProtocolHeaderFlags: u32 {
const TYPE_TAG = 0b00000001;
const BODY = 0b00000010;
const ERROR = 0b00000100;
const ARGUMENT = 0b00001000;
const TT_AND_ERROR = Self::TYPE_TAG.bits | Self::ERROR.bits;
const TT_AND_BODY = Self::TYPE_TAG.bits | Self::BODY.bits;
const TT_ERROR_AND_ARGUMENT = Self::TYPE_TAG.bits | Self::ERROR.bits | Self::ARGUMENT.bits;
const TT_BODY_AND_ARGUMENT = Self::TYPE_TAG.bits | Self::BODY.bits | Self::ARGUMENT.bits;
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ProtocolHeader<'a> {
pub kind: ProtocolHeaderActionKind,
pub type_tag: Option<Cow<'a, [u8]>>,
pub flags: ProtocolHeaderFlags,
pub body_type: BodyType,
pub argument: u64,
}
impl<'a> ProtocolHeader<'a> {
pub fn send(mid: u64, tt: &'a TypeTag, body_type: BodyType) -> ProtocolHeader<'a> {
ProtocolHeader {
kind: ProtocolHeaderActionKind::Send,
type_tag: Some(tt.as_bytes().into()),
flags: ProtocolHeaderFlags::TT_BODY_AND_ARGUMENT,
body_type,
argument: mid,
}
}
pub fn flush() -> Self {
ProtocolHeader {
kind: ProtocolHeaderActionKind::Flush,
type_tag: None,
flags: ProtocolHeaderFlags::empty(),
body_type: BodyType::None,
argument: 0,
}
}
pub fn close() -> Self {
ProtocolHeader {
kind: ProtocolHeaderActionKind::Close,
type_tag: None,
flags: ProtocolHeaderFlags::empty(),
body_type: BodyType::None,
argument: 0,
}
}
pub fn sync() -> Self {
ProtocolHeader {
kind: ProtocolHeaderActionKind::Synchronize,
type_tag: None,
flags: ProtocolHeaderFlags::empty(),
body_type: BodyType::None,
argument: 0,
}
}
// pub fn init() -> Self {
// ProtocolHeader {
// kind: ProtocolHeaderActionKind::Initialize,
// type_tag: None,
// failed: false,
// body_encoding: 0,
// argument: 0,
// }
// }
// pub fn pause() -> Self {
// ProtocolHeader {
// kind: ProtocolHeaderActionKind::Pause,
// type_tag: None,
// failed: false,
// body_encoding: 0,
// argument: 0,
// }
// }
}
#[derive(Debug)]
pub enum ProtocolItem {
Nop,
Event(Event<Box<dyn SharedMessage>, messagebus::error::GenericError>),
Action(Action),
Send(u64, Box<dyn SharedMessage>, bool),
}
impl From<Action> for ProtocolItem {
fn from(action: Action) -> Self {
ProtocolItem::Action(action)
}
}
impl From<Event<Box<dyn SharedMessage>, messagebus::error::GenericError>> for ProtocolItem {
fn from(ev: Event<Box<dyn SharedMessage>, messagebus::error::GenericError>) -> Self {
ProtocolItem::Event(ev)
}
}
impl From<(u64, Box<dyn SharedMessage>, bool)> for ProtocolItem {
fn from(msg: (u64, Box<dyn SharedMessage>, bool)) -> Self {
ProtocolItem::Send(msg.0, msg.1, msg.2)
}
}
impl ProtocolItem {
pub fn unwrap_send(self) -> Result<(u64, Box<dyn SharedMessage>, bool), ProtocolItem> {
match self {
ProtocolItem::Send(a, b, c) => Ok((a, b, c)),
other => Err(other),
}
}
pub fn serialize<'a>(
&self,
mut body_type: BodyType,
body_buff: &'a mut Vec<u8>,
) -> Result<ProtocolPacket<'a>, crate::error::Error> {
let mut argument = 0;
let mut type_tag = None;
let mut body = None;
let mut flags = ProtocolHeaderFlags::empty();
let kind = match self {
ProtocolItem::Nop => ProtocolHeaderActionKind::Nop,
ProtocolItem::Action(action) => match action {
Action::Close => ProtocolHeaderActionKind::Close,
Action::Flush => ProtocolHeaderActionKind::Flush,
Action::Init(..) => ProtocolHeaderActionKind::Initialize,
Action::Sync => ProtocolHeaderActionKind::Synchronize,
_ => unimplemented!(),
},
ProtocolItem::Send(mid, msg, req) => {
let msg = msg
.as_shared_ref()
.ok_or(crate::error::Error::UnknownCodec)?;
argument = *mid;
flags.set(ProtocolHeaderFlags::ARGUMENT, *req);
flags.set(ProtocolHeaderFlags::BODY, true);
flags.set(ProtocolHeaderFlags::TYPE_TAG, true);
type_tag = Some(msg.type_tag());
body = Some(generic_serialize(body_type, &*msg, body_buff)?);
ProtocolHeaderActionKind::Send
}
ProtocolItem::Event(ev) => match ev {
Event::Response(mid, res) => {
argument = *mid;
flags.set(ProtocolHeaderFlags::ARGUMENT, true);
flags.set(ProtocolHeaderFlags::BODY, true);
flags.set(ProtocolHeaderFlags::TYPE_TAG, true);
match res {
Ok(msg) => {
let msg = msg
.as_shared_ref()
.ok_or(crate::error::Error::UnknownCodec)?;
type_tag = Some(msg.type_tag());
body = Some(generic_serialize(body_type, &*msg, body_buff)?);
}
Err(err) => {
flags.set(ProtocolHeaderFlags::ERROR, true);
type_tag = Some("GenericError".into());
body_type = BodyType::Utf8;
body = Some(format!("{}", err).into_bytes().into());
}
}
ProtocolHeaderActionKind::Response
}
Event::Error(err) => {
flags.set(ProtocolHeaderFlags::ERROR, true);
flags.set(ProtocolHeaderFlags::BODY, true);
flags.set(ProtocolHeaderFlags::TYPE_TAG, true);
type_tag = Some("GenericError".into());
body_type = BodyType::Utf8;
body = Some(format!("{}", err).into_bytes().into());
ProtocolHeaderActionKind::Error
}
Event::BatchComplete(tt, n) => {
argument = *n;
type_tag = Some(tt.clone());
flags.set(ProtocolHeaderFlags::TYPE_TAG, true);
flags.set(ProtocolHeaderFlags::ARGUMENT, true);
ProtocolHeaderActionKind::BatchComplete
}
Event::Synchronized(res) => {
match res {
Ok(_) => {}
Err(err) => {
flags.set(ProtocolHeaderFlags::BODY, true);
flags.set(ProtocolHeaderFlags::ERROR, true);
flags.set(ProtocolHeaderFlags::TYPE_TAG, true);
type_tag = Some("GenericError".into());
body_type = BodyType::Utf8;
body = Some(format!("{}", err).into_bytes().into());
}
}
ProtocolHeaderActionKind::Synchronized
}
Event::InitFailed(err) => {
flags.set(ProtocolHeaderFlags::BODY, true);
flags.set(ProtocolHeaderFlags::ERROR, true);
flags.set(ProtocolHeaderFlags::TYPE_TAG, true);
type_tag = Some("GenericError".into());
body_type = BodyType::Utf8;
body = Some(format!("{}", err).into_bytes().into());
ProtocolHeaderActionKind::Ready
}
Event::Ready => ProtocolHeaderActionKind::Ready,
Event::Pause => ProtocolHeaderActionKind::Pause,
Event::Exited => ProtocolHeaderActionKind::Exited,
Event::Flushed => ProtocolHeaderActionKind::Flushed,
_ => unimplemented!(),
},
};
Ok(ProtocolPacket {
header: ProtocolHeader {
kind,
type_tag: type_tag.map(|x| x.to_string().into_bytes().into()),
flags,
body_type,
argument,
},
body,
})
}
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ProtocolPacket<'a> {
pub header: ProtocolHeader<'a>,
pub body: Option<Cow<'a, [u8]>>,
}
impl<'a> ProtocolPacket<'a> {
pub fn deserialize(self, _bus: &Bus) -> Result<ProtocolItem, crate::error::Error> {
let type_tag: Option<TypeTag> = if self.header.flags.contains(ProtocolHeaderFlags::TYPE_TAG)
{
self.header
.type_tag
.map(|x| String::from_utf8_lossy(x.as_ref()).to_string().into())
} else {
None
};
let (body, error) = if self.header.flags.contains(ProtocolHeaderFlags::ERROR) {
let error = messagebus::error::GenericError {
type_tag: type_tag.clone().unwrap(),
description: self
.body
.map(|x| String::from_utf8_lossy(x.as_ref()).to_string())
.unwrap_or_default(),
};
(None, Some(messagebus::error::Error::Other(error)))
} else if self.header.flags.contains(ProtocolHeaderFlags::TT_AND_BODY) {
let body = self
.body
.ok_or_else(|| crate::error::Error::ProtocolParseError("No body".to_string()))?;
let res = generic_deserialize(self.header.body_type, body.as_ref(), |de| {
messagebus::deserialize_shared_message(type_tag.clone().unwrap(), de)
.map_err(|x| x.map_msg(|_| ()))
})?;
match res {
Ok(body) => (Some(body), None),
Err(err) => (None, Some(err)),
}
} else {
(None, None)
};
let argument = if self.header.flags.contains(ProtocolHeaderFlags::ARGUMENT) {
Some(self.header.argument)
} else {
None
};
Ok(ProtocolItem::Event(match self.header.kind {
ProtocolHeaderActionKind::Response => Event::Response(
argument.ok_or_else(|| {
crate::error::Error::ProtocolParseError(
"Event::Response expected argument".into(),
)
})?,
error.map(Err).or_else(|| body.map(Ok)).ok_or_else(|| {
crate::error::Error::ProtocolParseError("Event::Response expected body".into())
})?,
),
ProtocolHeaderActionKind::Synchronized => {
Event::Synchronized(error.map(Err).unwrap_or(Ok(())))
}
ProtocolHeaderActionKind::Error => Event::Error(error.ok_or_else(|| {
crate::error::Error::ProtocolParseError("Event::Error expected body".into())
})?),
ProtocolHeaderActionKind::BatchComplete => {
Event::BatchComplete(type_tag.unwrap(), self.header.argument)
}
ProtocolHeaderActionKind::Flushed => Event::Flushed,
ProtocolHeaderActionKind::Exited => Event::Exited,
ProtocolHeaderActionKind::Ready => Event::Ready,
ProtocolHeaderActionKind::Pause => Event::Pause,
other => {
return Ok(ProtocolItem::Action(match other {
ProtocolHeaderActionKind::Initialize => Action::Init(self.header.argument),
ProtocolHeaderActionKind::Close => Action::Close,
ProtocolHeaderActionKind::Flush => Action::Flush,
ProtocolHeaderActionKind::Synchronize => Action::Sync,
ProtocolHeaderActionKind::Send => {
let req = argument.is_some();
let mid = self.header.argument;
let body = body.ok_or_else(|| {
crate::error::Error::ProtocolParseError(format!(
"Action::Send[{:?}] expected body",
type_tag
))
})?;
return Ok(ProtocolItem::Send(mid, body, req));
}
ProtocolHeaderActionKind::Nop => return Ok(ProtocolItem::Nop),
_ => unreachable!(),
}))
}
}))
}
}
fn generic_deserialize<F, T>(k: BodyType, data: &[u8], f: F) -> Result<T, crate::error::Error>
where
F: FnOnce(&mut dyn erased_serde::Deserializer<'_>) -> T,
{
match k {
BodyType::Cbor => {
let mut cbor_de = serde_cbor::Deserializer::from_slice(data);
let mut de = <dyn erased_serde::Deserializer>::erase(&mut cbor_de);
Ok(f(&mut de))
}
BodyType::Json => {
let mut json_de = serde_json::Deserializer::from_slice(data);
let mut de = <dyn erased_serde::Deserializer>::erase(&mut json_de);
Ok(f(&mut de))
}
_ => Err(crate::error::Error::UnknownCodec),
}
}
fn generic_serialize<'a>(
kind: BodyType,
msg: &dyn SharedMessage,
buffer: &'a mut Vec<u8>,
) -> Result<Cow<'a, [u8]>, crate::error::Error> {
match kind {
BodyType::Cbor => {
let mut cbor_se = serde_cbor::Serializer::new(&mut *buffer);
let mut se = <dyn erased_serde::Serializer>::erase(&mut cbor_se);
msg.erased_serialize(&mut se)?;
}
BodyType::Json => {
let mut json_se = serde_json::Serializer::new(&mut *buffer);
let mut se = <dyn erased_serde::Serializer>::erase(&mut json_se);
msg.erased_serialize(&mut se)?;
}
_ => return Err(crate::error::Error::UnknownCodec),
}
Ok(buffer.as_slice().into())
}
#[cfg(test)]
mod tests {
use crate::proto::ProtocolItem;
use super::{
BodyType, ProtocolHeader, ProtocolHeaderActionKind, ProtocolHeaderFlags, ProtocolPacket,
};
use messagebus::Event;
use messagebus::{derive::Message, Bus, TypeTagged};
use serde_derive::{Deserialize, Serialize};
use std::borrow::Cow;
#[derive(Serialize, Deserialize, Debug, Clone, Message)]
#[namespace("test")]
#[message(shared, clone)]
struct TestSharedMessage {
test: String,
value: i32,
}
#[test]
fn test_proto_pack_event() {
let (bus, _) = Bus::build().build();
let pkt = ProtocolPacket {
header: ProtocolHeader {
kind: ProtocolHeaderActionKind::Response,
type_tag: Some(TestSharedMessage::type_tag_().as_bytes().to_vec().into()),
flags: ProtocolHeaderFlags::TT_BODY_AND_ARGUMENT,
body_type: BodyType::Json,
argument: 222,
},
body: Some(Cow::Borrowed(br#"{"test":"my test","value":12}"#)),
};
let event = match pkt.deserialize(&bus).unwrap() {
ProtocolItem::Event(ev) => ev,
_ => unreachable!(),
};
assert!(matches!(event, Event::Response(..)));
match event {
Event::Response(mid, msg) => {
assert_eq!(mid, 222);
// assert!(msg.is_ok());
let msg = msg.unwrap();
assert_eq!(msg.type_tag(), TestSharedMessage::type_tag_());
let m: Box<TestSharedMessage> = msg.as_any_boxed().downcast().unwrap();
assert_eq!(m.value, 12);
assert_eq!(&m.test, "my test");
}
_ => unreachable!(),
}
}
#[test]
fn test_proto_pack_event_error() {
let (bus, _) = Bus::build().build();
let pkt = ProtocolPacket {
header: ProtocolHeader {
kind: ProtocolHeaderActionKind::Response,
type_tag: Some(TestSharedMessage::type_tag_().as_bytes().to_vec().into()),
flags: ProtocolHeaderFlags::TT_ERROR_AND_ARGUMENT,
body_type: BodyType::Utf8,
argument: 222,
},
body: Some(Cow::Borrowed(br#"error description"#)),
};
let event = match pkt.deserialize(&bus).unwrap() {
ProtocolItem::Event(ev) => ev,
_ => unreachable!(),
};
assert!(matches!(event, Event::Response(..)));
#[allow(clippy::unit_cmp)]
match event {
Event::Response(mid, msg) => {
assert_eq!(mid, 222);
let msg = msg.unwrap_err();
assert!(matches!(msg, messagebus::error::Error::Other(val) if (
assert_eq!(val.type_tag, TestSharedMessage::type_tag_()) == () &&
assert_eq!(val.description, "error description") == ()
)));
}
_ => unreachable!(),
}
}
}

View File

@ -0,0 +1,89 @@
// #[cfg(feature = "quic")]
mod quic;
// mod redis;
mod tcp;
use futures::Stream;
use messagebus::{error::GenericError, Event, Message, TypeTag};
use std::{collections::HashMap, pin::Pin};
// #[cfg(feature = "quic")]
pub use quic::*;
pub use tcp::*;
pub(crate) type GenericEventStream =
Pin<Box<dyn Stream<Item = Event<Box<dyn Message>, GenericError>> + Send>>;
#[derive(Debug, Default)]
pub struct MessageTable {
table: HashMap<TypeTag, Vec<Option<(TypeTag, TypeTag)>>>,
}
impl MessageTable {
#[inline]
pub fn add_any(&mut self, req: TypeTag, resp_err: Option<(TypeTag, TypeTag)>) {
self.table
.entry(req)
.or_insert_with(Vec::new)
.push(resp_err);
}
#[inline]
pub fn add_request(&mut self, req: TypeTag, resp: TypeTag, err: TypeTag) {
self.add_any(req, Some((resp, err)));
}
#[inline]
pub fn add_message(&mut self, msg: TypeTag) {
self.add_any(msg, None);
}
pub fn iter_keys(&self) -> impl Iterator<Item = &str> + '_ {
self.table.keys().map(|k| k.as_ref())
}
#[inline]
pub fn accept_any(&self, msg: &TypeTag) -> bool {
self.table.contains_key(msg)
}
#[inline]
pub fn accept_message(&self, msg: &TypeTag) -> bool {
self.table
.get(msg)
.map_or(false, |v| v.iter().any(Option::is_none))
}
pub fn accept_request(
&self,
msg: &TypeTag,
resp: Option<&TypeTag>,
err: Option<&TypeTag>,
) -> bool {
self.table.get(msg).map_or(false, |v| {
v.iter().filter_map(Option::as_ref).any(|(r, e)| {
resp.map_or(true, |resp| resp.as_ref() == r.as_ref())
&& err.map_or(true, |err| err.as_ref() == e.as_ref())
})
})
}
pub fn iter_types(
&self,
) -> impl Iterator<Item = (&'_ TypeTag, Option<&'_ (TypeTag, TypeTag)>)> + '_ {
self.table
.iter()
.map(|(k, v)| v.iter().map(move |resp| (k, resp.as_ref())))
.flatten()
}
}
impl From<Vec<(TypeTag, Option<(TypeTag, TypeTag)>)>> for MessageTable {
fn from(table: Vec<(TypeTag, Option<(TypeTag, TypeTag)>)>) -> Self {
let mut outgoing_table = MessageTable::default();
for (key, val) in table {
outgoing_table.add_any(key, val);
}
outgoing_table
}
}

View File

@ -0,0 +1,56 @@
use crate::error::Error;
use futures::{Future, Stream};
use quinn::Connecting;
use std::{
net::SocketAddr,
pin::Pin,
task::{Context, Poll},
};
use super::WaitIdle;
pub struct QuicClientEndpoint {
addr: SocketAddr,
host: String,
endpoint: quinn::Endpoint,
}
impl QuicClientEndpoint {
pub fn new(cert: &str, addr: SocketAddr, host: String) -> Result<Self, Error> {
let mut client_config = quinn::ClientConfigBuilder::default();
client_config.protocols(super::ALPN_QUIC_HTTP);
client_config.enable_keylog();
let cert_der = std::fs::read(cert)?;
let cert = quinn::Certificate::from_der(&cert_der)?;
client_config.add_certificate_authority(cert).unwrap();
let mut endpoint = quinn::Endpoint::builder();
endpoint.default_client_config(client_config.build());
let (endpoint, _) = endpoint.bind(&"0.0.0.0:0".parse().unwrap())?;
Ok(Self {
addr,
host,
endpoint,
})
}
}
impl Stream for QuicClientEndpoint {
type Item = Connecting;
fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
Poll::Ready(this.endpoint.connect(&this.addr, &this.host).ok())
}
}
impl<'a> WaitIdle<'a> for QuicClientEndpoint {
type Fut = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
fn wait_idle(&'a self) -> Self::Fut {
Box::pin(self.endpoint.wait_idle())
}
}

View File

@ -0,0 +1,489 @@
mod client;
mod server;
use std::net::SocketAddr;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use bytes::{Buf, BufMut};
pub use client::QuicClientEndpoint;
use futures::{pin_mut, Future, Stream, StreamExt};
use messagebus::error::GenericError;
use messagebus::{
Action, Bus, Event, EventBoxed, Message, ReciveUntypedReceiver, SendOptions,
SendUntypedReceiver, TypeTag, TypeTagAccept, TypeTagAcceptItem,
};
use parking_lot::Mutex;
use quinn::{Connecting, IncomingBiStreams};
pub use server::QuicServerEndpoint;
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
pub const ALPN_QUIC_HTTP: &[&[u8]] = &[b"hq-29"];
use crate::proto::{BodyType, ProtocolItem, ProtocolPacket};
pub type QuicClientRelay = QuicRelay<QuicClientEndpoint>;
pub type QuicServerRelay = QuicRelay<QuicServerEndpoint>;
use super::{GenericEventStream, MessageTable};
pub type MessageList = Vec<(TypeTag, Option<(TypeTag, TypeTag)>)>;
pub trait WaitIdle<'a>: Sync {
type Fut: Future + Send + 'a;
fn wait_idle(&'a self) -> Self::Fut;
}
pub struct QuicRelay<B> {
base: Mutex<Option<B>>,
self_id: Arc<AtomicU64>,
in_table: MessageTable,
_out_table: MessageTable,
item_sender: UnboundedSender<Option<ProtocolItem>>,
item_receiver: Mutex<Option<UnboundedReceiver<Option<ProtocolItem>>>>,
event_sender: UnboundedSender<EventBoxed<GenericError>>,
event_receiver: Mutex<Option<UnboundedReceiver<EventBoxed<GenericError>>>>,
stream_sender: UnboundedSender<IncomingBiStreams>,
stream_receiver: Mutex<Option<UnboundedReceiver<IncomingBiStreams>>>,
}
impl QuicRelay<QuicClientEndpoint> {
pub fn new(
cert: &str,
addr: SocketAddr,
host: String,
table: (MessageList, MessageList),
) -> Result<Self, crate::error::Error> {
let (item_sender, item_receiver) = mpsc::unbounded_channel();
let (event_sender, event_receiver) = mpsc::unbounded_channel();
let (stream_sender, stream_receiver) = mpsc::unbounded_channel();
Ok(QuicRelay {
base: Mutex::new(Some(QuicClientEndpoint::new(cert, addr, host)?)),
self_id: Arc::new(AtomicU64::new(0)),
in_table: MessageTable::from(table.0),
_out_table: MessageTable::from(table.1),
item_sender,
item_receiver: Mutex::new(Some(item_receiver)),
event_sender,
event_receiver: Mutex::new(Some(event_receiver)),
stream_sender,
stream_receiver: Mutex::new(Some(stream_receiver)),
})
}
}
impl QuicRelay<QuicServerEndpoint> {
pub fn new(
key_path: &str,
cert_path: &str,
addr: SocketAddr,
table: (MessageList, MessageList),
) -> Result<Self, crate::error::Error> {
let (item_sender, item_receiver) = mpsc::unbounded_channel();
let (event_sender, event_receiver) = mpsc::unbounded_channel();
let (stream_sender, stream_receiver) = mpsc::unbounded_channel();
Ok(QuicRelay {
base: Mutex::new(Some(QuicServerEndpoint::new(key_path, cert_path, &addr)?)),
self_id: Arc::new(AtomicU64::new(0)),
in_table: MessageTable::from(table.0),
_out_table: MessageTable::from(table.1),
item_sender,
item_receiver: Mutex::new(Some(item_receiver)),
event_sender,
event_receiver: Mutex::new(Some(event_receiver)),
stream_sender,
stream_receiver: Mutex::new(Some(stream_receiver)),
})
}
}
impl<B> TypeTagAccept for QuicRelay<B>
where
B: Stream<Item = Connecting> + Send + 'static,
{
fn iter_types(&self) -> Box<dyn Iterator<Item = TypeTagAcceptItem> + '_> {
let iter = self.in_table.iter_types();
Box::new(iter.map(|(x, y)| (x.clone(), y.cloned())))
}
fn accept_msg(&self, msg: &TypeTag) -> bool {
self.in_table.accept_message(msg)
}
fn accept_req(&self, req: &TypeTag, resp: Option<&TypeTag>, err: Option<&TypeTag>) -> bool {
self.in_table.accept_request(req, resp, err)
}
}
impl<B> SendUntypedReceiver for QuicRelay<B>
where
B: for<'a> WaitIdle<'a> + Stream<Item = Connecting> + Send + 'static,
{
fn send(&self, msg: Action, _bus: &Bus) -> Result<(), messagebus::error::Error<Action>> {
match msg {
Action::Init(self_id) => {
let mut rx = match self.item_receiver.lock().take() {
Some(x) => x,
None => return Ok(()),
};
let stream_sender = self.stream_sender.clone();
let event_sender = self.event_sender.clone();
let incoming = self.base.lock().take().unwrap();
self.self_id.store(self_id, Ordering::SeqCst);
tokio::spawn(async move {
pin_mut!(incoming);
let mut body_buff = Vec::new();
let mut header_buff = Vec::new();
let mut item = None;
loop {
println!("begin");
let conn = match incoming.next().await {
Some(x) => x,
None => {
println!("No more connections. Message {:?} has been lost!", item);
break;
}
};
let conn = match conn.await {
Ok(conn) => conn,
Err(err) => {
println!(
"connection dropped with err {}. waiting next connection",
err
);
continue;
}
};
stream_sender.send(conn.bi_streams).unwrap();
event_sender.send(Event::Ready).unwrap();
loop {
let r = if let Some(r) = item.take() {
r
} else {
match rx.recv().await {
Some(Some(r)) => r,
None | Some(None) => {
println!("closing");
conn.connection.close(0u32.into(), b"done");
incoming.wait_idle().await;
break;
}
}
// match tokio::time::timeout(Duration::from_secs(5), rx.recv()).await {
// Ok(Some(Some(r))) => r,
// Ok(None) | Ok(Some(None)) => {
// conn.connection.close(0u32.into(), b"done");
// incoming.wait_idle().await;
// break;
// },
// Err(_) => {
// // println!("{:?}", err);
// // let (mut send, _) = match conn.connection.open_bi().await {
// // Ok(x) => x,
// // Err(err) => {
// // println!("err {}", err);
// // break;
// // }
// // };
// // println!("<< PING");
// // let _ = send.write_all(b"PING").await.unwrap();
// // let _ = send.finish().await;
// continue;
// }
// }
};
let (mut send, _) = match conn.connection.open_bi().await {
Ok(x) => x,
Err(err) => {
println!("err {}", err);
break;
}
};
body_buff.clear();
let pkt = r.serialize(BodyType::Cbor, &mut body_buff).unwrap();
header_buff.resize(16, 0);
serde_cbor::to_writer(&mut header_buff, &pkt).unwrap();
let body_size = header_buff.len() - 16;
let mut head = &mut header_buff[0..16];
head.put(&b"MBUS"[..]);
head.put_u16(1);
head.put_u16(0);
head.put_u64(body_size as _);
if let Err(err) = send.write_all(&header_buff).await {
item = Some(r);
println!(
"write broken connection err {}. try with next connection",
err
);
break;
}
if let Err(err) = send.finish().await {
item = Some(r);
println!(
"finish broken connection err {}. try with next connection",
err
);
break;
}
}
event_sender.send(Event::Pause).unwrap();
}
println!("exit main loop");
});
}
Action::Close => {
self.item_sender.send(None).unwrap();
self.event_sender.send(Event::Exited).unwrap();
}
other => self.item_sender.send(Some(other.into())).unwrap(),
}
Ok(())
}
fn send_msg(
&self,
mid: u64,
msg: Box<dyn Message>,
req: bool,
_bus: &Bus,
) -> Result<(), messagebus::error::Error<Box<dyn Message>>> {
match msg.as_shared_boxed() {
Ok(msg) => {
if let Err(err) = self.item_sender.send(Some((mid, msg, req).into())) {
Err(messagebus::error::Error::TryAgain(
err.0.unwrap().unwrap_send().unwrap().1.upcast_box(),
))
} else {
Ok(())
}
}
Err(msg) => Err(messagebus::error::Error::TryAgain(msg)),
}
}
}
impl<B> ReciveUntypedReceiver for QuicRelay<B>
where
B: Send,
{
type Stream = GenericEventStream;
fn event_stream(&self, bus: Bus) -> Self::Stream {
let self_id = self.self_id.clone();
let mut recv_stream = self.stream_receiver.lock().take().unwrap();
let mut recv_events = self.event_receiver.lock().take().unwrap();
let sender = self.item_sender.clone();
let stream1 = futures::stream::poll_fn(move |cx| recv_stream.poll_recv(cx))
.map(move |incoming| {
let buff: Vec<u8> = Vec::with_capacity(1024);
let bus = bus.clone();
let self_id = self_id.clone();
let sender = sender.clone();
futures::stream::unfold(
(incoming, bus, sender, self_id, buff),
|(mut incoming, bus, sender, self_id, mut buff)| async move {
loop {
let (_, mut recv) = match incoming.next().await? {
Ok(recv) => recv,
Err(err) => {
println!("error: {}", err);
return None;
}
};
buff.resize(4, 0);
if let Err(err) = recv.read_exact(&mut buff[..]).await {
println!("recv err: {}", err);
continue;
}
let verb = match std::str::from_utf8(&buff[0..4]) {
Ok(m) => m,
Err(err) => {
println!("recv err parse: {}", err);
continue;
}
};
if verb == "PING" {
println!(">> PING");
continue;
}
if verb != "MBUS" {
println!("Not MBUS packet!");
continue;
}
buff.resize(12, 0);
if let Err(err) = recv.read_exact(&mut buff[..]).await {
println!("recv err: {}", err);
continue;
}
let mut reader = &buff[..];
let _version = reader.get_u16();
let content_type = reader.get_u16();
let body_size = reader.get_u64();
buff.resize(body_size as _, 0);
if let Err(err) = recv.read_exact(&mut buff[..]).await {
println!("recv err: {}", err);
continue;
}
drop(recv);
// println!("inbound packet MBUS v: {}; ct: {}; bs: {}",
// version, content_type, body_size);
let event = match content_type {
0 => {
// CBOR
let proto: ProtocolPacket =
match serde_cbor::from_slice(&buff[..]) {
Ok(val) => val,
Err(err) => {
println!("pkt parse err: {}", err);
continue;
}
};
let item: ProtocolItem = match proto.deserialize(&bus) {
Ok(val) => val,
Err(err) => {
println!("item parse err: {}", err);
continue;
}
};
match item {
ProtocolItem::Event(ev) => {
ev.map_msg(|msg| msg.upcast_box())
}
ProtocolItem::Action(action) => {
match action {
Action::Close => {
println!("warning: Close recevied - ignoring!");
sender
.send(Some(ProtocolItem::Event(
Event::Exited,
)))
.unwrap();
}
Action::Flush => {
println!("flush");
bus.flush_all().await;
sender
.send(Some(ProtocolItem::Event(
Event::Flushed,
)))
.unwrap();
}
Action::Sync => {
println!("flush");
bus.sync_all().await;
sender
.send(Some(ProtocolItem::Event(
Event::Synchronized(Ok(())),
)))
.unwrap();
}
Action::Init(..) => (),
Action::Stats => (),
_ => (),
}
continue;
}
ProtocolItem::Send(mid, msg, req) => {
let self_id = self_id.clone();
let sender = sender.clone();
let bus = bus.clone();
let _ = tokio::spawn(async move {
if req {
let res = bus
.request_boxed(
msg.upcast_box(),
SendOptions::Except(
self_id.load(Ordering::SeqCst),
),
)
.await
.map(|x| x.as_shared_boxed().unwrap())
.map_err(|x| x.map_msg(|_| ()));
sender
.send(Some(ProtocolItem::Event(
Event::Response(mid, res),
)))
.unwrap();
} else {
let tt = msg.type_tag();
let _ = bus
.send_boxed(
msg.upcast_box(),
Default::default(),
)
.await;
sender
.send(Some(ProtocolItem::Event(
Event::BatchComplete(tt, 1),
)))
.unwrap();
}
});
continue;
}
_ => unimplemented!(),
}
}
_ => unimplemented!(),
};
return Some((event, (incoming, bus, sender, self_id, buff)));
}
},
)
})
.flatten();
let stream2 = futures::stream::poll_fn(move |cx| recv_events.poll_recv(cx));
Box::pin(
futures::stream::select(stream1, stream2)
.take_while(|x| futures::future::ready(!matches!(x, Event::Exited))),
)
}
}

View File

@ -0,0 +1,64 @@
use crate::error::Error;
use futures::{Future, Stream};
use quinn::Connecting;
use std::{
net::SocketAddr,
pin::Pin,
sync::Arc,
task::{Context, Poll},
};
use super::WaitIdle;
pub struct QuicServerEndpoint {
endpoint: quinn::Endpoint,
incoming: quinn::Incoming,
}
impl QuicServerEndpoint {
pub fn new(key_path: &str, cert_path: &str, addr: &SocketAddr) -> Result<Self, Error> {
let mut transport_config = quinn::TransportConfig::default();
transport_config.max_concurrent_uni_streams(0)?;
let mut server_config = quinn::ServerConfig::default();
server_config.transport = Arc::new(transport_config);
let mut server_config = quinn::ServerConfigBuilder::new(server_config);
server_config.protocols(super::ALPN_QUIC_HTTP);
server_config.enable_keylog();
let key = std::fs::read(key_path)?;
let cert_der = std::fs::read(cert_path)?;
let key = quinn::PrivateKey::from_der(&key)?;
let cert_chain = quinn::Certificate::from_der(&cert_der)?;
let cert = quinn::CertificateChain::from_certs([cert_chain]);
server_config.certificate(cert, key)?;
let mut endpoint = quinn::Endpoint::builder();
endpoint.listen(server_config.build());
let (endpoint, incoming) = endpoint.bind(addr)?;
Ok(Self { endpoint, incoming })
}
}
impl Stream for QuicServerEndpoint {
type Item = Connecting;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
unsafe { Pin::new_unchecked(&mut this.incoming) }.poll_next(cx)
}
}
impl<'a> WaitIdle<'a> for QuicServerEndpoint {
type Fut = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
fn wait_idle(&'a self) -> Self::Fut {
Box::pin(self.endpoint.wait_idle())
}
}

View File

@ -0,0 +1,252 @@
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use futures::StreamExt;
use messagebus::{
Action, Bus, Event, Message, ReciveUntypedReceiver, SendUntypedReceiver, TypeTag, TypeTagAccept,
};
use parking_lot::Mutex;
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use super::{GenericEventStream, MessageTable};
use crate::proto::{BodyType, ProtocolItem};
use redis::AsyncCommands;
#[derive(Debug)]
enum RecvDo {
Ready,
}
pub struct RedisRelay {
client: Arc<redis::Client>,
self_id: Arc<AtomicU64>,
table: MessageTable,
item_sender: UnboundedSender<Option<ProtocolItem>>,
item_receiver: Mutex<Option<UnboundedReceiver<Option<ProtocolItem>>>>,
event_sender: UnboundedSender<RecvDo>,
event_receiver: Mutex<Option<UnboundedReceiver<RecvDo>>>,
}
impl RedisRelay {
pub fn new(
path: &str,
table: Vec<(TypeTag, Option<(TypeTag, TypeTag)>)>,
) -> Result<Self, crate::error::Error> {
let client = redis::Client::open(path)?;
let (item_sender, item_receiver) = mpsc::unbounded_channel();
let (event_sender, event_receiver) = mpsc::unbounded_channel();
Ok(RedisRelay {
client: Arc::new(client),
self_id: Arc::new(AtomicU64::new(0)),
table: MessageTable::from(table),
item_sender,
item_receiver: Mutex::new(Some(item_receiver)),
event_sender,
event_receiver: Mutex::new(Some(event_receiver)),
})
}
}
impl TypeTagAccept for RedisRelay {
fn accept_msg(&self, msg: &TypeTag) -> bool {
self.table.accept_message(msg)
}
fn accept_req(&self, msg: &TypeTag, resp: Option<&TypeTag>, err: Option<&TypeTag>) -> bool {
self.table.accept_request(msg, resp, err)
}
fn iter_types(&self) -> Box<dyn Iterator<Item = (TypeTag, Option<(TypeTag, TypeTag)>)> + '_> {
let iter = self.table.iter_types();
Box::new(iter.map(|(x, y)| (x.clone(), y.cloned())))
}
}
impl SendUntypedReceiver for RedisRelay {
fn send(&self, msg: Action, _bus: &Bus) -> Result<(), messagebus::error::Error<Action>> {
match msg {
Action::Init(self_id) => {
let event_sender = self.event_sender.clone();
let mut rx = self.item_receiver.lock().take().unwrap();
let client = self.client.clone();
self.self_id.store(self_id, Ordering::SeqCst);
tokio::spawn(async move {
let mut connection = client.get_tokio_connection().await.unwrap();
let mut body_buff = Vec::new();
let mut header_buff = Vec::new();
// let mut item = None;
event_sender.send(RecvDo::Ready).unwrap();
while let Some(Some(item)) = rx.recv().await {
header_buff.clear();
body_buff.clear();
let pkt = item.serialize(BodyType::Cbor, &mut body_buff).unwrap();
serde_cbor::to_writer(&mut header_buff, &pkt).unwrap();
let channel = match &item {
ProtocolItem::Action(_) => "mbus_action".into(),
ProtocolItem::Send(_, msg, _) => {
format!("mbus_request::{}", msg.type_tag())
}
ProtocolItem::Event(_ev) => "mbus_response::".into(),
_ => unreachable!(),
};
let () = connection.publish(channel, &header_buff).await.unwrap();
}
});
}
Action::Close => {
self.item_sender.send(None).unwrap();
// self.event_sender.send(RecvDo::Closed).unwrap();
}
other => self.item_sender.send(Some(other.into())).unwrap(),
}
Ok(())
}
fn send_msg(
&self,
mid: u64,
msg: Box<dyn Message>,
req: bool,
_bus: &Bus,
) -> Result<(), messagebus::error::Error<Box<dyn Message>>> {
match msg.as_shared_boxed() {
Ok(msg) => {
if let Err(err) = self.item_sender.send(Some((mid, msg, req).into())) {
Err(messagebus::error::Error::TryAgain(
err.0.unwrap().unwrap_send().unwrap().1.upcast_box(),
))
} else {
Ok(())
}
}
Err(msg) => Err(messagebus::error::Error::TryAgain(msg)),
}
}
}
impl ReciveUntypedReceiver for RedisRelay {
type Stream = GenericEventStream;
fn event_stream(&self, bus: Bus) -> Self::Stream {
let self_id = self.self_id.clone();
let sender = self.item_sender.clone();
let mut recv = self.event_receiver.lock().take().unwrap();
Box::pin(
futures::stream::poll_fn(move |cx| recv.poll_recv(cx))
.map(move |recv_do| {
let self_id = self_id.clone();
let bus = bus.clone();
let sender = sender.clone();
match recv_do {
// RecvDo::Incoming(incoming) => {
// futures::stream::unfold((incoming, bus, sender, self_id), |(mut incoming, bus, sender, self_id)| async move {
// loop {
// let (_, recv) = match incoming.next().await? {
// Ok(recv) => recv,
// Err(err) => {
// println!("error: {}", err);
// return None;
// }
// };
// let buff = recv
// .read_to_end(usize::max_value())
// .await
// .unwrap();
// // assert_eq!(&buff[0..4], b"MBUS");
// if buff.is_empty() {
// println!("PONG");
// continue;
// }
// let mut reader = &buff[4..];
// let version = reader.get_u16();
// let content_type = reader.get_u16();
// let body_size = reader.get_u64();
// println!("inbound packet {}: v: {}; ct: {}; bs: {}", String::from_utf8_lossy(&buff[0..4]), version, content_type, body_size);
// let event = match content_type {
// 0 => { // CBOR
// let proto: ProtocolPacket = serde_cbor::from_slice(&buff[16..]).unwrap();
// match proto.deserialize(&bus).unwrap() {
// ProtocolItem::Event(ev) => ev.map_msg(|msg|msg.upcast_box()),
// ProtocolItem::Action(action) => {
// match action {
// Action::Close => {
// println!("warning: Close recevied - ignoring!");
// sender.send(Some(ProtocolItem::Event(Event::Exited))).unwrap();
// },
// Action::Flush => {
// bus.flush().await;
// sender.send(Some(ProtocolItem::Event(Event::Flushed))).unwrap();
// },
// Action::Sync => {
// bus.sync().await;
// sender.send(Some(ProtocolItem::Event(Event::Synchronized(Ok(()))))).unwrap();
// },
// Action::Init(..) => (),
// Action::Stats => (),
// _ => (),
// }
// continue;
// }
// ProtocolItem::Send(mid, msg, req) => {
// if req {
// let res = bus.request_boxed(
// msg.upcast_box(),
// SendOptions::Except(self_id.load(Ordering::SeqCst))
// )
// .await
// .map(|x|x.as_shared_boxed().unwrap())
// .map_err(|x|x.map_msg(|_|()));
// sender.send(Some(ProtocolItem::Event(Event::Response(mid, res)))).unwrap();
// } else {
// let _ = bus.send_boxed(msg.upcast_box(), Default::default())
// .await;
// }
// continue;
// }
// _ => unimplemented!()
// }
// },
// _ => unimplemented!()
// };
// return Some((event, (incoming, bus, sender, self_id)));
// }
// }).right_stream()
// }
other => futures::stream::once(async move {
match other {
RecvDo::Ready => Event::Ready,
_ => unreachable!(),
}
}), // .left_stream()
}
})
.flatten(),
)
}
}

View File

@ -0,0 +1,429 @@
use std::net::SocketAddr;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use bytes::{Buf, BufMut};
use futures::stream::unfold;
use futures::{pin_mut, Stream, StreamExt};
use messagebus::error::GenericError;
use messagebus::{
Action, Bus, Event, EventBoxed, Message, ReciveUntypedReceiver, SendOptions,
SendUntypedReceiver, TypeTag, TypeTagAccept, TypeTagAcceptItem,
};
use parking_lot::Mutex;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::net::tcp::{OwnedReadHalf, OwnedWriteHalf};
use tokio::net::{TcpListener, TcpStream};
use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
use crate::proto::{BodyType, ProtocolItem, ProtocolPacket};
use super::{GenericEventStream, MessageList, MessageTable};
pub struct TcpRelay {
server_mode: bool,
addr: SocketAddr,
self_id: Arc<AtomicU64>,
in_table: MessageTable,
// _out_table: MessageTable,
item_sender: UnboundedSender<Option<ProtocolItem>>,
item_receiver: Mutex<Option<UnboundedReceiver<Option<ProtocolItem>>>>,
event_sender: UnboundedSender<EventBoxed<GenericError>>,
event_receiver: Mutex<Option<UnboundedReceiver<EventBoxed<GenericError>>>>,
stream_sender: UnboundedSender<OwnedReadHalf>,
stream_receiver: Mutex<Option<UnboundedReceiver<OwnedReadHalf>>>,
}
impl TcpRelay {
pub fn new(server_mode: bool, addr: SocketAddr, table: (MessageList, MessageList)) -> Self {
let (item_sender, item_receiver) = mpsc::unbounded_channel();
let (event_sender, event_receiver) = mpsc::unbounded_channel();
let (stream_sender, stream_receiver) = mpsc::unbounded_channel();
Self {
self_id: Arc::new(AtomicU64::new(0)),
server_mode,
addr,
item_sender,
in_table: MessageTable::from(table.0),
item_receiver: Mutex::new(Some(item_receiver)),
event_sender,
event_receiver: Mutex::new(Some(event_receiver)),
stream_sender,
stream_receiver: Mutex::new(Some(stream_receiver)),
}
}
fn connections(&self) -> impl Stream<Item = TcpRelayConnection> {
unfold(
(self.server_mode, self.addr),
move |(sm, addr)| async move {
let stream = if sm {
let bind_res = TcpListener::bind(addr).await;
let listener = match bind_res {
Err(err) => {
println!("bind error: {}", err);
return None;
}
Ok(listener) => listener,
};
unfold((listener,), move |(listener,)| async move {
let (stream, _addr) = match listener.accept().await {
Err(err) => {
println!("accept error: {}", err);
return None;
}
Ok(listener) => listener,
};
Some((TcpRelayConnection::from(stream), (listener,)))
})
.left_stream()
} else {
unfold((addr,), move |(addr,)| async move {
let stream = match TcpStream::connect(addr).await {
Err(err) => {
println!("connect error: {}", err);
return None;
}
Ok(listener) => listener,
};
Some((TcpRelayConnection::from(stream), (addr,)))
})
.right_stream()
};
Some((stream, (sm, addr)))
},
)
.flatten()
}
}
struct TcpRelayConnection {
recv: OwnedReadHalf,
send: OwnedWriteHalf,
}
impl From<TcpStream> for TcpRelayConnection {
fn from(stream: TcpStream) -> Self {
let (recv, send) = stream.into_split();
TcpRelayConnection { recv, send }
}
}
impl TypeTagAccept for TcpRelay {
fn iter_types(&self) -> Box<dyn Iterator<Item = TypeTagAcceptItem> + '_> {
let iter = self.in_table.iter_types();
Box::new(iter.map(|(x, y)| (x.clone(), y.cloned())))
}
fn accept_msg(&self, msg: &TypeTag) -> bool {
self.in_table.accept_message(msg)
}
fn accept_req(&self, req: &TypeTag, resp: Option<&TypeTag>, err: Option<&TypeTag>) -> bool {
self.in_table.accept_request(req, resp, err)
}
}
impl SendUntypedReceiver for TcpRelay {
fn send(&self, msg: Action, _bus: &Bus) -> Result<(), messagebus::error::Error<Action>> {
match msg {
Action::Init(self_id) => {
let mut rx = match self.item_receiver.lock().take() {
Some(x) => x,
None => return Ok(()),
};
let stream_sender = self.stream_sender.clone();
let event_sender = self.event_sender.clone();
let incoming = self.connections();
self.self_id.store(self_id, Ordering::SeqCst);
tokio::spawn(async move {
pin_mut!(incoming);
let mut body_buff = Vec::new();
let mut header_buff = Vec::new();
let mut item = None;
loop {
println!("begin");
let mut conn = match incoming.next().await {
Some(x) => x,
None => {
println!("No more connections. Message {:?} has been lost!", item);
break;
}
};
stream_sender.send(conn.recv).unwrap();
event_sender.send(Event::Ready).unwrap();
loop {
let r = if let Some(r) = item.take() {
r
} else {
match rx.recv().await {
Some(Some(r)) => r,
None | Some(None) => {
println!("closing");
drop(conn.send);
break;
}
}
};
body_buff.clear();
let pkt = r.serialize(BodyType::Cbor, &mut body_buff).unwrap();
header_buff.resize(16, 0);
serde_cbor::to_writer(&mut header_buff, &pkt).unwrap();
let body_size = header_buff.len() - 16;
let mut head = &mut header_buff[0..16];
head.put(&b"MBUS"[..]);
head.put_u16(1);
head.put_u16(0);
head.put_u64(body_size as _);
if let Err(err) = conn.send.write_all(&header_buff).await {
item = Some(r);
println!(
"write broken connection err {}. try with next connection",
err
);
break;
}
}
event_sender.send(Event::Pause).unwrap();
}
println!("exit main loop");
});
}
Action::Close => {
self.item_sender.send(None).unwrap();
self.event_sender.send(Event::Exited).unwrap();
}
other => self.item_sender.send(Some(other.into())).unwrap(),
}
Ok(())
}
fn send_msg(
&self,
mid: u64,
msg: Box<dyn Message>,
req: bool,
_bus: &Bus,
) -> Result<(), messagebus::error::Error<Box<dyn Message>>> {
match msg.as_shared_boxed() {
Ok(msg) => {
if let Err(err) = self.item_sender.send(Some((mid, msg, req).into())) {
Err(messagebus::error::Error::TryAgain(
err.0.unwrap().unwrap_send().unwrap().1.upcast_box(),
))
} else {
Ok(())
}
}
Err(msg) => Err(messagebus::error::Error::TryAgain(msg)),
}
}
}
impl ReciveUntypedReceiver for TcpRelay {
type Stream = GenericEventStream;
fn event_stream(&self, bus: Bus) -> Self::Stream {
let self_id = self.self_id.clone();
let mut recv_stream = self.stream_receiver.lock().take().unwrap();
let mut recv_events = self.event_receiver.lock().take().unwrap();
let sender = self.item_sender.clone();
let stream1 = futures::stream::poll_fn(move |cx| recv_stream.poll_recv(cx))
.map(move |incoming| {
let buff: Vec<u8> = Vec::with_capacity(1024);
let bus = bus.clone();
let self_id = self_id.clone();
let sender = sender.clone();
futures::stream::unfold(
(incoming, bus, sender, self_id, buff),
|(mut recv, bus, sender, self_id, mut buff)| async move {
loop {
buff.resize(4, 0);
if let Err(err) = recv.read_exact(&mut buff[..]).await {
println!("recv err: {}", err);
break None;
}
if &buff == b"PING" {
println!(">> PING");
continue;
}
if &buff != b"MBUS" {
println!("Not MBUS packet!");
continue;
}
buff.resize(12, 0);
if let Err(err) = recv.read_exact(&mut buff[..]).await {
println!("recv err: {}", err);
continue;
}
let mut reader = &buff[..];
let _version = reader.get_u16();
let content_type = reader.get_u16();
let body_size = reader.get_u64();
buff.resize(body_size as _, 0);
if let Err(err) = recv.read_exact(&mut buff[..]).await {
println!("recv err: {}", err);
continue;
}
// println!("inbound packet MBUS v: {}; ct: {}; bs: {}",
// version, content_type, body_size);
let event = match content_type {
0 => {
// CBOR
let proto: ProtocolPacket =
match serde_cbor::from_slice(&buff[..]) {
Ok(val) => val,
Err(err) => {
println!("pkt parse err: {}", err);
continue;
}
};
let item: ProtocolItem = match proto.deserialize(&bus) {
Ok(val) => val,
Err(err) => {
println!("item parse err: {}", err);
continue;
}
};
match item {
ProtocolItem::Event(ev) => {
ev.map_msg(|msg| msg.upcast_box())
}
ProtocolItem::Action(action) => {
match action {
Action::Close => {
println!("warning: Close recevied - ignoring!");
sender
.send(Some(ProtocolItem::Event(
Event::Exited,
)))
.unwrap();
}
Action::Flush => {
println!("flush");
bus.flush_all().await;
sender
.send(Some(ProtocolItem::Event(
Event::Flushed,
)))
.unwrap();
}
Action::Sync => {
println!("sync");
bus.sync_all().await;
sender
.send(Some(ProtocolItem::Event(
Event::Synchronized(Ok(())),
)))
.unwrap();
}
Action::Init(..) => (),
Action::Stats => (),
_ => (),
}
continue;
}
ProtocolItem::Send(mid, msg, req) => {
let self_id = self_id.clone();
let sender = sender.clone();
let bus = bus.clone();
let _ = tokio::spawn(async move {
if req {
let res = bus
.request_boxed(
msg.upcast_box(),
SendOptions::Except(
self_id.load(Ordering::SeqCst),
),
)
.await
.map(|x| x.as_shared_boxed().unwrap())
.map_err(|x| x.map_msg(|_| ()));
sender
.send(Some(ProtocolItem::Event(
Event::Response(mid, res),
)))
.unwrap();
} else {
let tt = msg.type_tag();
let _ = bus
.send_boxed(
msg.upcast_box(),
Default::default(),
)
.await;
sender
.send(Some(ProtocolItem::Event(
Event::BatchComplete(tt, 1),
)))
.unwrap();
}
});
continue;
}
_ => unimplemented!(),
}
}
_ => unimplemented!(),
};
return Some((event, (recv, bus, sender, self_id, buff)));
}
},
)
})
.flatten();
let stream2 = futures::stream::poll_fn(move |cx| recv_events.poll_recv(cx));
Box::pin(
futures::stream::select(stream1, stream2)
.take_while(|x| futures::future::ready(!matches!(x, Event::Exited))),
)
}
}

168
examples/benchmark.rs Normal file
View File

@ -0,0 +1,168 @@
use std::time::Instant;
use async_trait::async_trait;
use messagebus::{
derive::Message, error, receivers::BufferUnorderedConfig, AsyncHandler, Bus, Message,
};
use thiserror::Error;
#[derive(Debug, Error, messagebus::derive::Error)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
struct TmpReceiver;
struct TmpReceiver2;
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgF32(f32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU16(u16);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU32(u32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI32(i32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI16(i16);
#[async_trait]
impl AsyncHandler<MsgF32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgF32, bus: &Bus) -> Result<Self::Response, Self::Error> {
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
bus.send(MsgU16(1)).await?;
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU16> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgU16, bus: &Bus) -> Result<Self::Response, Self::Error> {
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
bus.send(MsgU32(2)).await?;
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgU32, bus: &Bus) -> Result<Self::Response, Self::Error> {
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
bus.send(MsgI32(3)).await?;
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
bus.send(MsgI16(4)).await?;
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI16> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgI16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI32> for TmpReceiver2 {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
tokio::time::sleep(std::time::Duration::from_millis(1)).await;
bus.send(MsgI16(5)).await?;
Ok(())
}
}
async fn iter(bus: &Bus) {
for _ in 0..10_000 {
bus.send(MsgF32(0.)).await.unwrap();
}
bus.flush_all().await;
}
#[tokio::main]
async fn main() {
let cfg = BufferUnorderedConfig {
buffer_size: 8,
max_parallel: 8,
};
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe_async::<MsgF32>(cfg.buffer_size as _, cfg)
.subscribe_async::<MsgU16>(cfg.buffer_size as _, cfg)
.subscribe_async::<MsgU32>(cfg.buffer_size as _, cfg)
.subscribe_async::<MsgI32>(cfg.buffer_size as _, cfg)
.subscribe_async::<MsgI16>(cfg.buffer_size as _, cfg)
.done()
.register(TmpReceiver2)
.subscribe_async::<MsgI32>(cfg.buffer_size as _, cfg)
.done()
.build();
iter(&b).await;
let count = 5;
let mut time_sum = 0;
for _ in 0..count {
let inst = Instant::now();
iter(&b).await;
let diff = inst.elapsed();
time_sum += diff.as_micros();
}
println!("Avg time: {:.4}", time_sum as f64 / (count as f64 * 1000.0));
println!("flush");
b.flush_all().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
}

View File

@ -1,79 +0,0 @@
use messagebus::{receivers, Bus, Handler, Result as MbusResult};
struct TmpReceiver;
struct TmpReceiver2;
impl Handler<f32> for TmpReceiver {
fn handle(&self, msg: f32, bus: &Bus) -> MbusResult {
bus.try_send(1u16).unwrap();
println!("---> f32 {}", msg);
Ok(())
}
}
impl Handler<u16> for TmpReceiver {
fn handle(&self, msg: u16, bus: &Bus) -> MbusResult {
bus.try_send(1u32).unwrap();
println!("---> u16 {}", msg);
Ok(())
}
}
impl Handler<u32> for TmpReceiver {
fn handle(&self, msg: u32, bus: &Bus) -> MbusResult {
bus.try_send(2i32).unwrap();
println!("---> u32 {}", msg);
Ok(())
}
}
impl Handler<i32> for TmpReceiver {
fn handle(&self, msg: i32, bus: &Bus) -> MbusResult {
bus.try_send(3i16).unwrap();
println!("---> i32 {}", msg);
Ok(())
}
}
impl Handler<i16> for TmpReceiver {
fn handle(&self, msg: i16, _bus: &Bus) -> MbusResult {
println!("---> i16 {}", msg);
Ok(())
}
}
impl Handler<i32> for TmpReceiver2 {
fn handle(&self, msg: i32, bus: &Bus) -> MbusResult {
bus.try_send(3i16).unwrap();
println!("---> 2 i32 {}", msg);
Ok(())
}
}
impl Handler<i16> for TmpReceiver2 {
fn handle(&self, msg: i16, _bus: &Bus) -> MbusResult {
println!("---> 2 i16 {}", msg);
Ok(())
}
}
#[tokio::main]
async fn main() {
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe::<f32, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<u16, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<u32, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<i32, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<i16, receivers::BufferUnorderedSync<_>>(Default::default())
.done()
.register(TmpReceiver2)
.subscribe::<i32, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<i16, receivers::BufferUnorderedSync<_>>(Default::default())
.done()
.build();
b.send(32f32).await.unwrap();
poller.await
}

View File

@ -1,72 +1,166 @@
use async_trait::async_trait; use async_trait::async_trait;
use messagebus::{receivers, AsyncHandler, Bus, Handler, Result as MbusResult}; use messagebus::{derive::Message, error, AsyncHandler, Bus, Handler, Message, TypeTagged};
use thiserror::Error;
#[derive(Debug, Error, messagebus::derive::Error)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
struct TmpReceiver; struct TmpReceiver;
struct TmpReceiver2; struct TmpReceiver2;
#[async_trait] #[derive(Debug, Clone, Message)]
impl AsyncHandler<f32> for TmpReceiver { #[message(clone)]
async fn handle(&self, msg: f32, bus: &Bus) -> MbusResult { struct MsgF32(f32);
bus.send(1u16).await?;
println!("---> f32 {}", msg); #[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU16(u16);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU32(u32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI32(i32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI16(i16);
#[async_trait]
impl AsyncHandler<MsgF32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgF32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgU16(1)).await?;
println!("TmpReceiver ---> {:?} {}", msg, msg.type_tag());
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver f32: sync");
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
impl AsyncHandler<u16> for TmpReceiver { impl AsyncHandler<MsgU16> for TmpReceiver {
async fn handle(&self, msg: u16, bus: &Bus) -> MbusResult { type Error = Error;
bus.send(2u32).await?; type Response = ();
println!("---> u16 {}", msg);
async fn handle(&self, msg: MsgU16, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgU32(2)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver u16: sync");
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
impl AsyncHandler<u32> for TmpReceiver { impl AsyncHandler<MsgU32> for TmpReceiver {
async fn handle(&self, msg: u32, bus: &Bus) -> MbusResult { type Error = Error;
bus.send(3i32).await?; type Response = ();
println!("---> u32 {}", msg);
async fn handle(&self, msg: MsgU32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgI32(3)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver u32: sync");
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
impl AsyncHandler<i32> for TmpReceiver { impl AsyncHandler<MsgI32> for TmpReceiver {
async fn handle(&self, msg: i32, bus: &Bus) -> MbusResult { type Error = Error;
bus.send(4i16).await?; type Response = ();
println!("---> i32 {}", msg);
async fn handle(&self, msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgI16(4)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver i32: sync");
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
impl AsyncHandler<i16> for TmpReceiver { impl AsyncHandler<MsgI16> for TmpReceiver {
async fn handle(&self, msg: i16, _bus: &Bus) -> MbusResult { type Error = Error;
println!("---> i16 {}", msg); type Response = ();
async fn handle(&self, msg: MsgI16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver i16: sync");
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
impl AsyncHandler<i32> for TmpReceiver2 { impl AsyncHandler<MsgI32> for TmpReceiver2 {
async fn handle(&self, msg: i32, bus: &Bus) -> MbusResult { type Error = Error;
bus.send(5i16).await?; type Response = ();
println!("---> 2 i32 {}", msg);
async fn handle(&self, msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver2: ---> {:?}", msg);
bus.send(MsgI16(5)).await?;
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver2: i32: sync");
Ok(()) Ok(())
} }
} }
impl Handler<i16> for TmpReceiver2 { impl Handler<MsgI16> for TmpReceiver2 {
fn handle(&self, msg: i16, _bus: &Bus) -> MbusResult { type Error = Error;
println!("---> 2 i16 {}", msg); type Response = ();
fn handle(&self, msg: MsgI16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver2: ---> {:?}", msg);
Ok(())
}
fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver2: i16: sync");
Ok(()) Ok(())
} }
@ -74,20 +168,32 @@ impl Handler<i16> for TmpReceiver2 {
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
env_logger::init();
let (b, poller) = Bus::build() let (b, poller) = Bus::build()
.register(TmpReceiver) .register(TmpReceiver)
.subscribe::<f32, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe_async::<MsgF32>(8, Default::default())
.subscribe::<u16, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe_async::<MsgU16>(8, Default::default())
.subscribe::<u32, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe_async::<MsgU32>(8, Default::default())
.subscribe::<i32, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe_async::<MsgI32>(8, Default::default())
.subscribe::<i16, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe_async::<MsgI16>(8, Default::default())
.done() .done()
.register(TmpReceiver2) .register(TmpReceiver2)
.subscribe::<i32, receivers::BufferUnorderedAsync<_>>(Default::default()) .subscribe_async::<MsgI32>(8, Default::default())
.subscribe::<i16, receivers::BufferUnorderedSync<_>>(Default::default()) .subscribe_sync::<MsgI16>(8, Default::default())
.done() .done()
.build(); .build();
b.send(0f32).await.unwrap(); b.send(MsgF32(0.)).await.unwrap();
poller.await
println!("flush");
b.flush_all().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
} }

View File

@ -1,63 +0,0 @@
use messagebus::{receivers, Bus, Handler, Result as MbusResult};
struct TmpReceiver;
impl Handler<f32> for TmpReceiver {
fn handle(&self, msg: f32, _bus: &Bus) -> MbusResult {
println!("---> f32 {}", msg);
std::thread::sleep(std::time::Duration::from_secs(1));
println!("done");
Ok(())
}
}
#[tokio::main]
async fn main() {
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe::<f32, receivers::BufferUnorderedSync<_>>(receivers::BufferUnorderedConfig {
buffer_size: 1,
max_parallel: 1,
})
.done()
.build();
println!("sending 1");
b.send(32f32).await.unwrap();
println!("sending 2");
b.send(32f32).await.unwrap();
println!("sending 3");
b.send(32f32).await.unwrap();
println!("sending 4");
b.send(32f32).await.unwrap();
println!("sending 5");
b.send(32f32).await.unwrap();
println!("sending 6");
b.send(32f32).await.unwrap();
println!("sending 7");
b.send(32f32).await.unwrap();
println!("sending 8");
b.send(32f32).await.unwrap();
println!("sending 9");
b.send(32f32).await.unwrap();
println!("sending 10");
b.send(32f32).await.unwrap();
println!("sending 11");
b.send(32f32).await.unwrap();
println!("finish");
poller.await;
}

211
examples/demo_boxed.rs Normal file
View File

@ -0,0 +1,211 @@
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error, AsyncHandler, Bus, Handler, Message,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgF32(f32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU16(u16);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU32(u32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI32(i32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI16(i16);
struct TmpReceiver;
struct TmpReceiver2;
#[async_trait]
impl AsyncHandler<MsgF32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgF32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgU16(1u16)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver f32: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU16> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgU16, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgU32(2u32)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver u16: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgU32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgI32(3i32)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver u32: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgI16(4i16)).await?;
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver i32: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI16> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgI16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver ---> {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver i16: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI32> for TmpReceiver2 {
type Error = Error;
type Response = ();
async fn handle(&self, msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver2: ---> {:?}", msg);
bus.send(MsgI16(5i16)).await?;
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver2: i32: sync");
Ok(())
}
}
impl Handler<MsgI16> for TmpReceiver2 {
type Error = Error;
type Response = ();
fn handle(&self, msg: MsgI16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver2: ---> {:?}", msg);
Ok(())
}
fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver2: i16: sync");
Ok(())
}
}
#[tokio::main]
async fn main() {
env_logger::init();
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe_async::<MsgF32>(8, Default::default())
.subscribe_async::<MsgU16>(8, Default::default())
.subscribe_async::<MsgU32>(8, Default::default())
.subscribe_async::<MsgI32>(8, Default::default())
.subscribe_async::<MsgI16>(8, Default::default())
.done()
.register(TmpReceiver2)
.subscribe_async::<MsgI32>(8, Default::default())
.subscribe_sync::<MsgI16>(8, Default::default())
.done()
.build();
b.send(MsgF32(0f32)).await.unwrap();
println!("flush");
b.flush_all().await;
println!("sending boxed variant");
b.send_boxed(Box::new(MsgF32(0f32)), Default::default())
.await
.unwrap();
println!("flush");
b.flush_all().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
}

57
examples/demo_relay.rs Normal file
View File

@ -0,0 +1,57 @@
use messagebus::{
derive::{Error as MbError, Message},
error, Bus, Handler, Message, MessageBounds, Module,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
pub struct Msg<F: MessageBounds + Clone>(pub F);
struct TmpReceiver;
impl Handler<Msg<u32>> for TmpReceiver {
type Error = Error;
type Response = ();
fn handle(&self, msg: Msg<u32>, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> u32 {:?}", msg);
Ok(())
}
}
fn module() -> Module {
Module::new()
.register(TmpReceiver)
.subscribe_sync::<Msg<u32>>(8, Default::default())
.done()
}
#[tokio::main]
async fn main() {
let (b, poller) = Bus::build().add_module(module()).build();
// b.
println!("flush");
b.flush_all().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
}

View File

@ -1,10 +1,38 @@
use messagebus::{receivers, Bus, Handler, Result as MbusResult}; use messagebus::{
derive::{Error as MbError, Message},
error, Bus, Handler, Message, Module,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
struct MsgF32(pub f32);
#[derive(Debug, Clone, Message)]
struct MsgU32(pub u32);
#[derive(Debug, Clone, Message)]
struct MsgU16(pub u16);
struct TmpReceiver; struct TmpReceiver;
impl Handler<f32> for TmpReceiver { impl Handler<MsgF32> for TmpReceiver {
fn handle(&self, msg: f32, _bus: &Bus) -> MbusResult { type Error = Error;
println!("---> f32 {}", msg); type Response = ();
fn handle(&self, msg: MsgF32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> f32 {:?}", msg);
std::thread::sleep(std::time::Duration::from_secs(5)); std::thread::sleep(std::time::Duration::from_secs(5));
@ -14,33 +42,51 @@ impl Handler<f32> for TmpReceiver {
} }
} }
impl Handler<u16> for TmpReceiver { impl Handler<MsgU16> for TmpReceiver {
fn handle(&self, msg: u16, _bus: &Bus) -> MbusResult { type Error = Error;
println!("---> u16 {}", msg); type Response = ();
fn handle(&self, msg: MsgU16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> u16 {:?}", msg);
Ok(()) Ok(())
} }
} }
impl Handler<u32> for TmpReceiver { impl Handler<MsgU32> for TmpReceiver {
fn handle(&self, msg: u32, _bus: &Bus) -> MbusResult { type Error = Error;
println!("---> u32 {}", msg); type Response = ();
fn handle(&self, msg: MsgU32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> u32 {:?}", msg);
Ok(()) Ok(())
} }
} }
fn module() -> Module {
Module::new()
.register(TmpReceiver)
.subscribe_sync::<MsgF32>(8, Default::default())
.subscribe_sync::<MsgU16>(8, Default::default())
.subscribe_sync::<MsgU32>(8, Default::default())
.done()
}
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let (b, poller) = Bus::build() let (b, poller) = Bus::build().add_module(module()).build();
.register(TmpReceiver)
.subscribe::<f32, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<u16, receivers::BufferUnorderedSync<_>>(Default::default())
.subscribe::<u32, receivers::BufferUnorderedSync<_>>(Default::default())
.done()
.build();
b.send(32f32).await.unwrap(); b.send(MsgF32(32f32)).await.unwrap();
b.send(11u16).await.unwrap(); b.send(MsgU16(11u16)).await.unwrap();
b.send(32u32).await.unwrap(); b.send(MsgU32(32u32)).await.unwrap();
poller.await println!("flush");
b.flush_all().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
} }

View File

@ -0,0 +1,93 @@
use std::sync::Arc;
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error, AsyncBatchSynchronizedHandler, BatchSynchronizedHandler, Bus, Message,
};
use thiserror::Error;
#[derive(Debug, Error, Clone, MbError)]
enum Error {
#[error("Error({0})")]
Error(Arc<anyhow::Error>),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(Arc::new(err.into()))
}
}
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI32(i32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI16(i16);
struct TmpReceiver;
#[async_trait]
impl AsyncBatchSynchronizedHandler<MsgI32> for TmpReceiver {
type Error = Error;
type Response = ();
type InBatch = Vec<MsgI32>;
type OutBatch = Vec<()>;
async fn handle(
&mut self,
msg: Vec<MsgI32>,
_bus: &Bus,
) -> Result<Vec<Self::Response>, Self::Error> {
println!("---> [i32; {}] {:?}", msg.len(), msg);
Ok(vec![])
}
}
impl BatchSynchronizedHandler<MsgI16> for TmpReceiver {
type Error = Error;
type Response = ();
type InBatch = Vec<MsgI16>;
type OutBatch = Vec<()>;
fn handle(&mut self, msg: Vec<MsgI16>, _bus: &Bus) -> Result<Vec<Self::Response>, Self::Error> {
println!("---> [i16; {}] {:?}", msg.len(), msg);
Ok(vec![])
}
}
#[tokio::main]
async fn main() {
let (b, poller) = Bus::build()
.register_unsync(TmpReceiver)
.subscribe_batch_async::<MsgI32>(16, Default::default())
.subscribe_batch_sync::<MsgI16>(16, Default::default())
.done()
.build();
for i in 1..100i32 {
b.send(MsgI32(i)).await.unwrap();
}
b.send(MsgI16(1i16)).await.unwrap();
b.send(MsgI16(2i16)).await.unwrap();
b.send(MsgI16(3i16)).await.unwrap();
b.send(MsgI16(4i16)).await.unwrap();
b.send(MsgI16(5i16)).await.unwrap();
b.send(MsgI16(6i16)).await.unwrap();
b.send(MsgI16(7i16)).await.unwrap();
println!("flush");
b.flush_all().await;
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
}

View File

@ -1,24 +1,51 @@
use messagebus::{receivers, Bus, Result as MbusResult, SynchronizedHandler}; use async_trait::async_trait;
use receivers::SynchronizedConfig; use messagebus::{
derive::{Error as MbError, Message},
error, AsyncSynchronizedHandler, Bus, Message, SynchronizedHandler,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
struct MsgF32(pub f32);
#[derive(Debug, Clone, Message)]
struct MsgI16(pub i16);
struct TmpReceiver; struct TmpReceiver;
impl SynchronizedHandler<f32> for TmpReceiver { impl SynchronizedHandler<MsgF32> for TmpReceiver {
fn handle(&mut self, msg: f32, _bus: &Bus) -> MbusResult { type Error = Error;
println!("---> f32 {}", msg); type Response = ();
std::thread::sleep(std::time::Duration::from_secs(1)); fn handle(&mut self, msg: MsgF32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
// std::thread::sleep(std::time::Duration::from_millis(100));
println!("---> f32 {:?}", msg);
println!("done"); println!("done");
Ok(()) Ok(())
} }
} }
impl SynchronizedHandler<i16> for TmpReceiver { #[async_trait]
fn handle(&mut self, msg: i16, _bus: &Bus) -> MbusResult { impl AsyncSynchronizedHandler<MsgI16> for TmpReceiver {
println!("---> i16 {}", msg); type Error = Error;
type Response = ();
std::thread::sleep(std::time::Duration::from_secs(1)); async fn handle(&mut self, msg: MsgI16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
std::thread::sleep(std::time::Duration::from_millis(100));
println!("---> i16 {:?}", msg);
println!("done"); println!("done");
Ok(()) Ok(())
@ -29,29 +56,42 @@ impl SynchronizedHandler<i16> for TmpReceiver {
async fn main() { async fn main() {
let (b, poller) = Bus::build() let (b, poller) = Bus::build()
.register_unsync(TmpReceiver) .register_unsync(TmpReceiver)
.subscribe::<f32, receivers::SynchronizedSync<_>>(SynchronizedConfig { buffer_size: 1 }) .subscribe_sync::<MsgF32>(8, Default::default())
.subscribe::<i16, receivers::SynchronizedSync<_>>(Default::default()) .subscribe_async::<MsgI16>(8, Default::default())
.done() .done()
.build(); .build();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
b.send(12.0f32).await.unwrap(); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(1i16).await.unwrap(); b.send(MsgI16(1i16)).await.unwrap();
println!("finish"); b.send(MsgF32(12.0f32)).await.unwrap();
b.send(MsgI16(1i16)).await.unwrap();
println!("flush");
b.flush_all().await;
println!("closing");
b.close().await;
println!("closed");
poller.await; poller.await;
println!("[done]");
} }

View File

@ -1,160 +1,388 @@
use std::{any::TypeId, collections::HashMap, marker::PhantomData, pin::Pin, sync::Arc}; use core::{marker::PhantomData, pin::Pin};
use std::{
collections::HashSet,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
};
use futures::{Future, FutureExt}; use futures::{Future, FutureExt};
use receiver::ReceiverTrait;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use crate::{ use crate::{
receiver::{self, Receiver}, error::StdSyncSendError,
Bus, BusInner, Message, Untyped, receiver::{
BusPollerCallback, Receiver, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers, AsyncBatchHandler, AsyncBatchSynchronizedHandler, AsyncHandler,
AsyncSynchronizedHandler, BatchHandler, BatchSynchronizedHandler, Bus, BusInner, Handler,
Message, Relay, SynchronizedHandler, Untyped,
}; };
pub trait ReceiverSubscriber<T: 'static> { static RECEVIER_ID_SEQ: AtomicU64 = AtomicU64::new(1);
fn subscribe(
self,
) -> (
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
);
}
pub trait ReceiverSubscriberBuilder<M, T: 'static> { pub trait ReceiverSubscriberBuilder<T, M, R, E>:
type Entry: ReceiverSubscriber<T>; SendUntypedReceiver + SendTypedReceiver<M> + ReciveTypedReceiver<R, E>
where
T: 'static,
M: Message,
R: Message,
E: StdSyncSendError,
{
type Config: Default; type Config: Default;
fn build(cfg: Self::Config) -> Self::Entry; fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback)
where
Self: Sized;
} }
pub struct SyncEntry; pub struct SyncEntry;
pub struct UnsyncEntry; pub struct UnsyncEntry;
#[must_use] #[must_use]
pub struct RegisterEntry<K, T> { pub struct RegisterEntry<K, T, F, P, B> {
item: Untyped, item: Untyped,
builder: BusBuilder, payload: B,
receivers: HashMap< builder: F,
TypeId, poller: P,
Vec<( receivers: HashSet<Receiver>,
Receiver, pollers: Vec<BusPollerCallback>,
Box<
dyn FnOnce(
Untyped,
)
-> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
)>,
>,
_m: PhantomData<(K, T)>, _m: PhantomData<(K, T)>,
} }
impl<K, T: 'static> RegisterEntry<K, T> { impl<K, T: 'static, F, P, B> RegisterEntry<K, T, F, P, B>
pub fn done(self) -> BusBuilder { where
let mut builder = self.builder; F: FnMut(&mut B, Receiver),
P: FnMut(&mut B, BusPollerCallback),
for (tid, v) in self.receivers { {
for (r, poller) in v { pub fn done(mut self) -> B {
let poller = poller(self.item.clone()); for r in self.receivers {
(self.builder)(&mut self.payload, r);
builder.add_recevier((tid, r), poller);
}
} }
builder for p in self.pollers {
(self.poller)(&mut self.payload, p);
}
self.payload
} }
} }
impl<T: Send + 'static> RegisterEntry<UnsyncEntry, T> { impl<T, F, P, B> RegisterEntry<UnsyncEntry, T, F, P, B> {
pub fn subscribe<M, R>(mut self, cfg: R::Config) -> Self pub fn subscribe<M, S, R, E>(mut self, queue: u64, cfg: S::Config) -> Self
where where
T: Send + 'static, T: Send + 'static,
M: Message + 'static, M: Message,
R: ReceiverSubscriberBuilder<M, T> + 'static, R: Message,
E: StdSyncSendError,
S: ReceiverSubscriberBuilder<T, M, R, E> + 'static,
{ {
let (inner, poller) = R::build(cfg).subscribe(); let (inner, poller) = S::build(cfg);
let receiver = Receiver::new(inner); let receiver = Receiver::new::<M, R, E, S>(
self.receivers RECEVIER_ID_SEQ.fetch_add(1, Ordering::Relaxed),
.entry(TypeId::of::<M>()) queue,
.or_insert_with(Vec::new) true,
.push((receiver, poller)); inner,
);
let poller2 = receiver.start_polling();
self.receivers.insert(receiver);
self.pollers.push(poller(self.item.clone()));
self.pollers.push(poller2);
self self
} }
#[inline]
pub fn subscribe_sync<M>(self, queue: u64, cfg: receivers::SynchronizedConfig) -> Self
where
T: SynchronizedHandler<M> + Send + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::SynchronizedSync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
#[inline]
pub fn subscribe_async<M>(self, queue: u64, cfg: receivers::SynchronizedConfig) -> Self
where
T: AsyncSynchronizedHandler<M> + Send + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::SynchronizedAsync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
#[inline]
pub fn subscribe_batch_sync<M>(
self,
queue: u64,
cfg: receivers::SynchronizedBatchedConfig,
) -> Self
where
T: BatchSynchronizedHandler<M> + Send + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::SynchronizedBatchedSync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
#[inline]
pub fn subscribe_batch_async<M>(
self,
queue: u64,
cfg: receivers::SynchronizedBatchedConfig,
) -> Self
where
T: AsyncBatchSynchronizedHandler<M> + Send + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::SynchronizedBatchedAsync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
} }
impl<T: Send + Sync + 'static> RegisterEntry<SyncEntry, T> { impl<T, F, P, B> RegisterEntry<SyncEntry, T, F, P, B> {
pub fn subscribe<M, R>(mut self, cfg: R::Config) -> Self pub fn subscribe<M, S, R, E>(mut self, queue: u64, cfg: S::Config) -> Self
where where
T: Send + 'static, T: Send + Sync + 'static,
M: Message + 'static, M: Message,
R: ReceiverSubscriberBuilder<M, T> + 'static, R: Message,
E: StdSyncSendError,
S: ReceiverSubscriberBuilder<T, M, R, E> + 'static,
{ {
let (inner, poller) = R::build(cfg).subscribe(); let (inner, poller) = S::build(cfg);
let receiver = Receiver::new(inner); let receiver = Receiver::new::<M, R, E, S>(
self.receivers RECEVIER_ID_SEQ.fetch_add(1, Ordering::Relaxed),
.entry(TypeId::of::<M>()) queue,
.or_insert_with(Vec::new) true,
.push((receiver, poller)); inner,
);
let poller2 = receiver.start_polling();
self.receivers.insert(receiver);
self.pollers.push(poller(self.item.clone()));
self.pollers.push(poller2);
self
}
#[inline]
pub fn subscribe_sync<M>(self, queue: u64, cfg: receivers::BufferUnorderedConfig) -> Self
where
T: Handler<M> + Send + Sync + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::BufferUnorderedSync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
#[inline]
pub fn subscribe_async<M>(self, queue: u64, cfg: receivers::BufferUnorderedConfig) -> Self
where
T: AsyncHandler<M> + Send + Sync + 'static,
M: Message,
T::Response: Message,
T::Error: StdSyncSendError,
{
self.subscribe::<M, receivers::BufferUnorderedAsync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
#[inline]
pub fn subscribe_batch_sync<M>(
self,
queue: u64,
cfg: receivers::BufferUnorderedBatchedConfig,
) -> Self
where
T: BatchHandler<M> + Send + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::BufferUnorderedBatchedSync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
#[inline]
pub fn subscribe_batch_async<M>(
self,
queue: u64,
cfg: receivers::BufferUnorderedBatchedConfig,
) -> Self
where
T: AsyncBatchHandler<M> + Send + 'static,
M: Message,
T::Response: Message,
{
self.subscribe::<M, receivers::BufferUnorderedBatchedAsync<M, T::Response, T::Error>, T::Response, T::Error>(queue, cfg)
}
}
#[derive(Default)]
pub struct Module {
receivers: HashSet<Receiver>,
pollings: Vec<BusPollerCallback>,
}
impl Module {
pub fn new() -> Self {
Self {
receivers: HashSet::new(),
pollings: Vec::new(),
}
}
pub fn register_relay<S: Relay + Send + Sync + 'static>(mut self, inner: S) -> Self {
let receiver =
Receiver::new_relay::<S>(RECEVIER_ID_SEQ.fetch_add(1, Ordering::Relaxed), inner);
self.pollings.push(receiver.start_polling());
self.receivers.insert(receiver);
self
}
pub fn register<T: Send + Sync + 'static>(
self,
item: T,
) -> RegisterEntry<
SyncEntry,
T,
impl FnMut(&mut Self, Receiver),
impl FnMut(&mut Self, Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>),
Self,
> {
RegisterEntry {
item: Arc::new(item) as Untyped,
payload: self,
builder: |p: &mut Self, r| {
p.receivers.insert(r);
},
poller: |p: &mut Self, poller| p.pollings.push(poller),
receivers: HashSet::new(),
pollers: Vec::new(),
_m: Default::default(),
}
}
pub fn register_unsync<T: Send + 'static>(
self,
item: T,
) -> RegisterEntry<
UnsyncEntry,
T,
impl FnMut(&mut Self, Receiver),
impl FnMut(&mut Self, Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>),
Self,
> {
let item = Arc::new(Mutex::new(item)) as Untyped;
RegisterEntry {
item,
payload: self,
builder: |p: &mut Self, r| {
p.receivers.insert(r);
},
poller: |p: &mut Self, poller| p.pollings.push(poller),
receivers: HashSet::new(),
pollers: Vec::new(),
_m: Default::default(),
}
}
pub fn add_module(mut self, module: Module) -> Self {
self.pollings.extend(module.pollings);
self.receivers.extend(module.receivers);
self self
} }
} }
pub struct BusBuilder { pub struct BusBuilder {
receivers: Vec<(TypeId, Receiver)>, inner: Module,
pollings: Vec<Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>>,
} }
impl BusBuilder { impl BusBuilder {
pub fn new() -> Self { pub(crate) fn new() -> Self {
Self { Self {
receivers: Vec::new(), inner: Module::new(),
pollings: Vec::new(),
} }
} }
pub fn register<T: Send + Sync + 'static>(self, item: T) -> RegisterEntry<SyncEntry, T> { pub fn register_relay<S: Relay + Send + Sync + 'static>(self, inner: S) -> Self {
let inner = self.inner.register_relay(inner);
BusBuilder { inner }
}
pub fn register<T: Send + Sync + 'static>(
self,
item: T,
) -> RegisterEntry<
SyncEntry,
T,
impl FnMut(&mut Self, Receiver),
impl FnMut(&mut Self, Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>),
Self,
> {
RegisterEntry { RegisterEntry {
item: Arc::new(item) as Untyped, item: Arc::new(item) as Untyped,
builder: self, payload: self,
receivers: HashMap::new(), builder: |p: &mut Self, r| {
p.inner.receivers.insert(r);
},
poller: |p: &mut Self, poller| p.inner.pollings.push(poller),
receivers: HashSet::new(),
pollers: Vec::new(),
_m: Default::default(), _m: Default::default(),
} }
} }
pub fn register_unsync<T: Send + 'static>(self, item: T) -> RegisterEntry<UnsyncEntry, T> { pub fn register_unsync<T: Send + 'static>(
self,
item: T,
) -> RegisterEntry<
UnsyncEntry,
T,
impl FnMut(&mut Self, Receiver),
impl FnMut(&mut Self, Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>),
Self,
> {
RegisterEntry { RegisterEntry {
item: Arc::new(Mutex::new(item)) as Untyped, item: Arc::new(Mutex::new(item)) as Untyped,
builder: self, payload: self,
receivers: HashMap::new(), builder: |p: &mut Self, r| {
p.inner.receivers.insert(r);
},
poller: |p: &mut Self, poller| p.inner.pollings.push(poller),
receivers: HashSet::new(),
pollers: Vec::new(),
_m: Default::default(), _m: Default::default(),
} }
} }
pub fn add_recevier( pub fn add_module(mut self, module: Module) -> Self {
&mut self, self.inner = self.inner.add_module(module);
val: (TypeId, Receiver),
poller: Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>, self
) {
self.receivers.push(val);
self.pollings.push(poller);
} }
pub fn build(self) -> (Bus, impl Future<Output = ()>) { pub fn build(self) -> (Bus, impl Future<Output = ()>) {
let bus = Bus { let bus = Bus {
inner: Arc::new(BusInner::new(self.receivers)), inner: Arc::new(BusInner::new(self.inner.receivers)),
}; };
let mut futs = Vec::with_capacity(self.pollings.len()); let mut futs = Vec::with_capacity(self.inner.pollings.len() * 2);
for poller in self.pollings { for poller in self.inner.pollings {
futs.push(tokio::task::spawn(poller(bus.clone()))); futs.push(tokio::task::spawn(poller(bus.clone())));
} }
let poller = futures::future::join_all(futs).map(|_| ()).map(|_| ()); let poller = futures::future::join_all(futs).map(|_| ()).map(|_| ());
bus.init();
(bus, poller) (bus, poller)
} }
} }

View File

@ -1,102 +1,462 @@
use core::any::{self, Any}; use core::{
use core::fmt; any::{type_name, Any},
// use erased_serde::{Deserializer, Serialize}; fmt,
};
pub trait Message: Any + fmt::Debug/*Serialize + for<'a> Deserializer<'a> + */ + Unpin + Clone + Send + Sync + 'static {} use std::{alloc::Layout, borrow::Cow, sync::Arc};
impl<T: Any + fmt::Debug + Unpin + Clone + Send + Sync> Message for T {}
trait SafeMessage: Any + fmt::Debug/*+ Serialize + for<'a> Deserializer<'a>*/ + Unpin + Send + Sync + 'static { pub trait MessageBounds: TypeTagged + fmt::Debug + Unpin + Send + Sync + 'static {}
fn type_name(&self) -> &'static str; impl<T: TypeTagged + fmt::Debug + Unpin + Send + Sync + 'static> MessageBounds for T {}
fn clone_boxed(&self) -> Box<dyn SafeMessage>;
pub type TypeTag = Cow<'static, str>;
pub trait TypeTagged {
fn type_tag_() -> TypeTag
where
Self: Sized;
fn type_tag(&self) -> TypeTag;
fn type_name(&self) -> Cow<str>;
fn type_layout(&self) -> Layout;
} }
impl<T: Message> SafeMessage for T { pub trait Message: MessageBounds {
fn type_name(&self) -> &'static str { fn as_any_ref(&self) -> &dyn Any;
any::type_name::<T>() fn as_any_mut(&mut self) -> &mut dyn Any;
fn as_any_boxed(self: Box<Self>) -> Box<dyn Any>;
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any>;
fn as_shared_ref(&self) -> Option<&dyn SharedMessage>;
fn as_shared_mut(&mut self) -> Option<&mut dyn SharedMessage>;
fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn SharedMessage>, Box<dyn Message>>;
fn as_shared_arc(self: Arc<Self>) -> Option<Arc<dyn SharedMessage>>;
fn try_clone_into(&self, into: &mut dyn Any) -> bool;
fn try_clone_boxed(&self) -> Option<Box<dyn Message>>;
fn try_clone(&self) -> Option<Self>
where
Self: Sized;
}
macro_rules! gen_impls {
($t:ty, $($rest:tt)*) => {
impl TypeTagged for $t {
fn type_tag_() -> TypeTag {
type_name::<$t>().into()
}
fn type_tag(&self) -> TypeTag {
type_name::<$t>().into()
}
fn type_name(&self) -> Cow<str> {
type_name::<$t>().into()
}
fn type_layout(&self) -> Layout {
Layout::for_value(self)
}
} }
fn clone_boxed(&self) -> Box<dyn SafeMessage> { gen_impls!{ $($rest)* }
Box::new(self.clone()) };
($t:ty) => {
impl TypeTagged for $t {
fn type_tag_() -> TypeTag {
type_name::<$t>().into()
}
fn type_tag(&self) -> TypeTag {
type_name::<$t>().into()
}
fn type_name(&self) -> Cow<str> {
type_name::<$t>().into()
}
fn type_layout(&self) -> Layout {
Layout::for_value(self)
}
}
};
}
gen_impls! {
(), bool,
i8, u8,
i16, u16,
i32, u32,
i64, u64,
i128, u128,
f32, f64,
String
}
impl<T: TypeTagged> TypeTagged for Arc<T> {
fn type_tag_() -> TypeTag {
T::type_tag_()
}
fn type_tag(&self) -> TypeTag {
T::type_tag(&*self)
}
fn type_name(&self) -> Cow<str> {
T::type_name(&*self)
}
fn type_layout(&self) -> Layout {
Layout::for_value(self)
} }
} }
// pub struct BoxedEnvelop { impl<T: TypeTagged> TypeTagged for Box<T> {
// inner: Box<dyn SafeMessage>, fn type_tag_() -> TypeTag {
// } T::type_tag_()
}
// impl BoxedEnvelop { fn type_tag(&self) -> TypeTag {
// pub fn from_message<M: Message>(m: M) -> Self { T::type_tag(&*self)
// Self { }
// inner: Box::new(m) fn type_name(&self) -> Cow<str> {
// } T::type_name(&*self)
// } }
fn type_layout(&self) -> Layout {
// pub fn as_ref(&self) -> Envelop<'_> { Layout::for_value(self)
// Envelop { inner: &*self.inner }
// }
// pub fn downcast<T: 'static>(self) -> Option<Box<T>> {
// if (*self.inner).type_id() == TypeId::of::<T>() {
// unsafe {
// let raw: *mut dyn SafeMessage = Box::into_raw(self.inner);
// Some(Box::from_raw(raw as *mut T))
// }
// } else {
// None
// }
// }
// }
#[derive(Copy, Clone)]
pub struct Envelop<'inner> {
inner: &'inner dyn SafeMessage,
}
impl<'inner> fmt::Debug for Envelop<'inner> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Envelop(")?;
self.inner.fmt(f)?;
write!(f, ")")?;
Ok(())
} }
} }
impl<'inner> Envelop<'inner> { impl Message for () {
// pub fn new<T: Message>(inner: &'inner T) -> Self { fn as_any_ref(&self) -> &dyn Any {
// Self { inner } self
// } }
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any_boxed(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
self
}
// #[inline] fn as_shared_ref(&self) -> Option<&dyn SharedMessage> {
// pub fn downcast_to<T: 'static>(&self) -> Option<&T> { Some(self)
// if self.inner.type_id() == TypeId::of::<T>() { }
// unsafe { Some(&*(self.inner as *const dyn SafeMessage as *const T)) } fn as_shared_mut(&mut self) -> Option<&mut dyn SharedMessage> {
// } else { Some(self)
// None }
// } fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn SharedMessage>, Box<dyn Message>> {
// } Ok(self)
}
fn as_shared_arc(self: Arc<Self>) -> Option<Arc<dyn SharedMessage>> {
Some(self)
}
fn try_clone_into(&self, into: &mut dyn Any) -> bool {
let into = if let Some(inner) = into.downcast_mut::<Option<()>>() {
inner
} else {
return false;
};
// #[inline] into.replace(());
// pub fn type_id(&self) -> TypeId { true
// self.inner.type_id() }
// } fn try_clone_boxed(&self) -> Option<Box<dyn Message>> {
Some(Box::new(()))
}
// #[inline] fn try_clone(&self) -> Option<Self> {
// pub fn type_name(&self) -> &'static str { Some(())
// self.inner.type_name() }
// }
// #[inline]
// pub fn clone_boxed(&self) -> BoxedEnvelop {
// BoxedEnvelop {
// inner: self.inner.clone_boxed(),
// }
// }
} }
// impl<'inner> serde::Serialize for Envelop<'inner> { pub trait IntoBoxedMessage {
// fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn into_boxed(self) -> Box<dyn Message>;
// erased_serde::serialize(self.inner, serializer) }
impl<T: Message> IntoBoxedMessage for T {
fn into_boxed(self) -> Box<dyn Message> {
Box::new(self)
}
}
pub trait IntoSharedMessage {
fn into_shared(self) -> Box<dyn SharedMessage>;
}
impl<T: Message + serde::Serialize> IntoSharedMessage for T {
fn into_shared(self) -> Box<dyn SharedMessage> {
Box::new(self)
}
}
pub trait SharedMessage: Message + erased_serde::Serialize {
fn upcast_arc(self: Arc<Self>) -> Arc<dyn Message>;
fn upcast_box(self: Box<Self>) -> Box<dyn Message>;
fn upcast_ref(&self) -> &dyn Message;
fn upcast_mut(&mut self) -> &mut dyn Message;
}
impl<T: Message + erased_serde::Serialize> SharedMessage for T {
fn upcast_arc(self: Arc<Self>) -> Arc<dyn Message> {
self
}
fn upcast_box(self: Box<Self>) -> Box<dyn Message> {
self
}
fn upcast_ref(&self) -> &dyn Message {
self
}
fn upcast_mut(&mut self) -> &mut dyn Message {
self
}
}
// pub trait IntoTakeable {
// fn into_takeable(&mut self) -> Takeable<'_>;
// }
// impl<T: 'static> IntoTakeable for Option<T> {
// fn into_takeable(&mut self) -> Takeable<'_> {
// Takeable {
// inner_ref: self
// } // }
// } // }
// }
// pub struct Takeable<'a> {
// inner_ref: &'a mut dyn Any,
// }
// impl Takeable<'_> {
// pub fn take<M: Message>(&mut self) -> Option<M> {
// let m = self.inner_ref.downcast_mut::<Option<M>>()?;
// m.take()
// }
// }
#[cfg(test)]
mod tests {
use super::*;
use erased_serde::Serializer;
use std::{any::type_name, borrow::Cow};
#[derive(Debug, Clone)]
struct Msg0;
impl TypeTagged for Msg0 {
fn type_tag_() -> TypeTag {
type_name::<Self>().into()
}
fn type_tag(&self) -> TypeTag {
type_name::<Self>().into()
}
fn type_name(&self) -> Cow<str> {
type_name::<Self>().into()
}
fn type_layout(&self) -> Layout {
Layout::for_value(self)
}
}
impl Message for Msg0 {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any_boxed(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
self
}
fn as_shared_ref(&self) -> Option<&dyn SharedMessage> {
None
}
fn as_shared_mut(&mut self) -> Option<&mut dyn SharedMessage> {
None
}
fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn SharedMessage>, Box<dyn Message>> {
Err(self)
}
fn as_shared_arc(self: Arc<Self>) -> Option<Arc<dyn SharedMessage>> {
None
}
fn try_clone_into(&self, _: &mut dyn Any) -> bool {
false
}
fn try_clone_boxed(&self) -> Option<Box<dyn Message>> {
None
}
fn try_clone(&self) -> Option<Self> {
None
}
}
#[derive(Debug, Clone)]
struct Msg1;
impl TypeTagged for Msg1 {
fn type_tag_() -> TypeTag {
type_name::<Self>().into()
}
fn type_tag(&self) -> TypeTag {
type_name::<Self>().into()
}
fn type_name(&self) -> Cow<str> {
type_name::<Self>().into()
}
fn type_layout(&self) -> Layout {
Layout::for_value(self)
}
}
impl Message for Msg1 {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any_boxed(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
self
}
fn as_shared_ref(&self) -> Option<&dyn SharedMessage> {
None
}
fn as_shared_mut(&mut self) -> Option<&mut dyn SharedMessage> {
None
}
fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn SharedMessage>, Box<dyn Message>> {
Err(self)
}
fn as_shared_arc(self: Arc<Self>) -> Option<Arc<dyn SharedMessage>> {
None
}
fn try_clone_into(&self, into: &mut dyn Any) -> bool {
let into = if let Some(inner) = into.downcast_mut::<Option<Msg1>>() {
inner
} else {
return false;
};
into.replace(self.clone());
true
}
fn try_clone_boxed(&self) -> Option<Box<dyn Message>> {
Some(Box::new(self.clone()))
}
fn try_clone(&self) -> Option<Self> {
Some(self.clone())
}
}
#[derive(Debug, Clone, serde_derive::Serialize, serde_derive::Deserialize)]
struct Msg2 {
inner: [i32; 2],
}
impl TypeTagged for Msg2 {
fn type_tag_() -> TypeTag {
type_name::<Self>().into()
}
fn type_tag(&self) -> TypeTag {
type_name::<Self>().into()
}
fn type_name(&self) -> Cow<str> {
type_name::<Self>().into()
}
fn type_layout(&self) -> Layout {
Layout::for_value(self)
}
}
impl Message for Msg2 {
fn as_any_ref(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any_boxed(self: Box<Self>) -> Box<dyn Any> {
self
}
fn as_any_arc(self: Arc<Self>) -> Arc<dyn Any> {
self
}
fn as_shared_ref(&self) -> Option<&dyn SharedMessage> {
Some(self)
}
fn as_shared_mut(&mut self) -> Option<&mut dyn SharedMessage> {
Some(self)
}
fn as_shared_boxed(self: Box<Self>) -> Result<Box<dyn SharedMessage>, Box<dyn Message>> {
Ok(self)
}
fn as_shared_arc(self: Arc<Self>) -> Option<Arc<dyn SharedMessage>> {
Some(self)
}
fn try_clone_into(&self, into: &mut dyn Any) -> bool {
let into = if let Some(inner) = into.downcast_mut::<Option<Msg2>>() {
inner
} else {
return false;
};
into.replace(self.clone());
true
}
fn try_clone_boxed(&self) -> Option<Box<dyn Message>> {
Some(Box::new(self.clone()))
}
fn try_clone(&self) -> Option<Self> {
Some(self.clone())
}
}
#[test]
fn test_static_upcast() {
let mut buff: Vec<u8> = Vec::new();
let json = &mut serde_json::Serializer::new(&mut buff);
let mut json = <dyn Serializer>::erase(json);
let x = Msg1;
let y = Msg2 { inner: [12, 13] };
assert!(x.as_shared_ref().is_none());
assert!(y.as_shared_ref().is_some());
assert!(y
.as_shared_ref()
.unwrap()
.erased_serialize(&mut json)
.is_ok());
assert_eq!(buff.as_slice(), b"{\"inner\":[12,13]}");
}
#[test]
fn test_dyn_upcast() {
let mut buff: Vec<u8> = Vec::new();
let json = &mut serde_json::Serializer::new(&mut buff);
let mut json = <dyn Serializer>::erase(json);
let x = Msg1;
let y = Msg2 { inner: [12, 13] };
let x_dyn: &dyn Message = &x;
let y_dyn: &dyn Message = &y;
assert!(x_dyn.as_shared_ref().is_none());
assert!(y_dyn.as_shared_ref().is_some());
assert!(y_dyn
.as_shared_ref()
.unwrap()
.erased_serialize(&mut json)
.is_ok());
assert_eq!(buff.as_slice(), b"{\"inner\":[12,13]}");
}
}

284
src/error.rs Normal file
View File

@ -0,0 +1,284 @@
use core::fmt;
use std::any::type_name;
use thiserror::Error;
use tokio::sync::oneshot;
use crate::{
envelop::{IntoBoxedMessage, TypeTag, TypeTagged},
Message,
};
pub trait DynError: TypeTagged {
fn description(&self) -> String;
}
pub trait StdSyncSendError: std::error::Error + TypeTagged + Send + Sync + Unpin + 'static {}
impl<T: std::error::Error + TypeTagged + Send + Sync + Unpin + 'static> StdSyncSendError for T {}
#[derive(Debug)]
pub struct GenericError {
pub type_tag: TypeTag,
pub description: String,
}
impl GenericError {
pub fn from_any<T: TypeTagged + fmt::Display>(err: T) -> Self {
GenericError {
type_tag: err.type_tag(),
description: format!("{}[{}]", err.type_tag(), err),
}
}
pub fn from_err(tt: TypeTag, err: impl fmt::Display) -> Self {
GenericError {
description: format!("{}[{}]", tt, err),
type_tag: tt,
}
}
}
impl fmt::Display for GenericError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GenericError({}): {}", self.type_tag, self.description)
}
}
impl std::error::Error for GenericError {}
impl TypeTagged for GenericError {
fn type_tag_() -> TypeTag {
type_name::<GenericError>().into()
}
fn type_tag(&self) -> TypeTag {
type_name::<GenericError>().into()
}
fn type_name(&self) -> TypeTag {
type_name::<GenericError>().into()
}
fn type_layout(&self) -> std::alloc::Layout {
std::alloc::Layout::for_value(self)
}
}
#[derive(Debug, Error)]
pub enum SendError<M: fmt::Debug> {
#[error("Closed")]
Closed(M),
#[error("Full")]
Full(M),
}
impl<M: fmt::Debug> SendError<M> {
pub fn map_msg<UM: fmt::Debug + 'static, F: FnOnce(M) -> UM>(self, f: F) -> SendError<UM> {
match self {
SendError::Closed(inner) => SendError::Closed(f(inner)),
SendError::Full(inner) => SendError::Full(f(inner)),
}
}
}
impl<M: Message> SendError<M> {
pub fn into_boxed(self) -> SendError<Box<dyn Message>> {
match self {
SendError::Closed(m) => SendError::Closed(m.into_boxed()),
SendError::Full(m) => SendError::Closed(m.into_boxed()),
}
}
}
#[derive(Debug, Error)]
pub enum Error<M: fmt::Debug + 'static = (), E: StdSyncSendError = GenericError> {
#[error("Message Send Error: {0}")]
SendError(#[from] SendError<M>),
#[error("Message receiver dropped try again another receiver")]
TryAgain(M),
#[error("NoResponse")]
NoResponse,
#[error("NoReceivers")]
NoReceivers,
#[error("AddListenerError")]
AddListenerError,
#[error("MessageCastError")]
MessageCastError,
#[error("Not Ready")]
NotReady,
#[error("Other({0})")]
Other(E),
#[error("Serialization({0})")]
Serialization(#[from] erased_serde::Error),
#[error("Other({0})")]
OtherBoxed(Box<dyn StdSyncSendError>),
#[error("WrongMessageType()")]
WrongMessageType(M),
#[error("TypeTagNotRegistered({0})")]
TypeTagNotRegistered(TypeTag),
#[error("Unknown Error: {0}")]
Unknown(String),
}
impl<M: fmt::Debug + 'static, E: StdSyncSendError> Error<M, E> {
pub fn send_closed(m: M) -> Self {
Error::SendError(SendError::Closed(m))
}
pub fn send_full(m: M) -> Self {
Error::SendError(SendError::Full(m))
}
pub fn map_msg<UM: fmt::Debug + 'static, F: FnOnce(M) -> UM>(self, f: F) -> Error<UM, E> {
match self {
Error::SendError(inner) => Error::SendError(inner.map_msg(f)),
Error::TryAgain(inner) => Error::TryAgain(f(inner)),
Error::NoResponse => Error::NoResponse,
Error::NoReceivers => Error::NoReceivers,
Error::Serialization(s) => Error::Serialization(s),
Error::Other(inner) => Error::Other(inner),
Error::OtherBoxed(inner) => Error::OtherBoxed(inner),
Error::WrongMessageType(inner) => Error::WrongMessageType(f(inner)),
Error::AddListenerError => Error::AddListenerError,
Error::MessageCastError => Error::MessageCastError,
Error::TypeTagNotRegistered(tt) => Error::TypeTagNotRegistered(tt),
Error::NotReady => Error::NotReady,
Error::Unknown(msg) => Error::Unknown(msg),
}
}
pub fn map_err<UE: StdSyncSendError, F: FnOnce(E) -> UE>(self, f: F) -> Error<M, UE> {
match self {
Error::SendError(inner) => Error::SendError(inner),
Error::TryAgain(inner) => Error::TryAgain(inner),
Error::NoResponse => Error::NoResponse,
Error::NoReceivers => Error::NoReceivers,
Error::Serialization(s) => Error::Serialization(s),
Error::Other(inner) => Error::Other(f(inner)),
Error::OtherBoxed(inner) => Error::OtherBoxed(inner),
Error::WrongMessageType(inner) => Error::WrongMessageType(inner),
Error::AddListenerError => Error::AddListenerError,
Error::MessageCastError => Error::MessageCastError,
Error::TypeTagNotRegistered(tt) => Error::TypeTagNotRegistered(tt),
Error::NotReady => Error::NotReady,
Error::Unknown(msg) => Error::Unknown(msg),
}
}
pub fn try_unwrap(self) -> Result<E, Self> {
match self {
Error::Other(inner) => Ok(inner),
s => Err(s),
}
}
}
impl<M: Message, E: StdSyncSendError> Error<M, E> {
pub fn into_dyn(self) -> Error<M> {
match self {
Error::SendError(inner) => Error::SendError(inner),
Error::TryAgain(inner) => Error::TryAgain(inner),
Error::NoResponse => Error::NoResponse,
Error::NoReceivers => Error::NoReceivers,
Error::Serialization(s) => Error::Serialization(s),
Error::Other(inner) => Error::OtherBoxed(Box::new(inner) as _),
Error::OtherBoxed(inner) => Error::OtherBoxed(inner),
Error::WrongMessageType(inner) => Error::WrongMessageType(inner),
Error::AddListenerError => Error::AddListenerError,
Error::MessageCastError => Error::MessageCastError,
Error::TypeTagNotRegistered(tt) => Error::TypeTagNotRegistered(tt),
Error::NotReady => Error::NotReady,
Error::Unknown(msg) => Error::Unknown(msg),
}
}
pub fn map<U: From<Box<dyn StdSyncSendError>> + StdSyncSendError>(self) -> Error<M, U> {
match self {
Error::SendError(inner) => Error::SendError(inner),
Error::TryAgain(inner) => Error::TryAgain(inner),
Error::NoResponse => Error::NoResponse,
Error::NoReceivers => Error::NoReceivers,
Error::Serialization(s) => Error::Serialization(s),
Error::Other(_) => panic!("expected boxed error!"),
Error::OtherBoxed(inner) => Error::Other(inner.into()),
Error::WrongMessageType(inner) => Error::WrongMessageType(inner),
Error::AddListenerError => Error::AddListenerError,
Error::MessageCastError => Error::MessageCastError,
Error::TypeTagNotRegistered(tt) => Error::TypeTagNotRegistered(tt),
Error::NotReady => Error::NotReady,
Error::Unknown(msg) => Error::Unknown(msg),
}
}
}
impl<E: StdSyncSendError> Error<(), E> {
pub fn specify<M: fmt::Debug>(self) -> Error<M, E> {
match self {
Error::SendError(_) => panic!("cannot specify type on typed error"),
Error::TryAgain(_) => panic!("cannot specify type on typed error"),
Error::WrongMessageType(_) => panic!("cannot specify type on typed error"),
Error::NoResponse => Error::NoResponse,
Error::NoReceivers => Error::NoReceivers,
Error::Serialization(s) => Error::Serialization(s),
Error::Other(inner) => Error::Other(inner),
Error::OtherBoxed(inner) => Error::OtherBoxed(inner),
Error::AddListenerError => Error::AddListenerError,
Error::MessageCastError => Error::MessageCastError,
Error::TypeTagNotRegistered(tt) => Error::TypeTagNotRegistered(tt),
Error::NotReady => Error::NotReady,
Error::Unknown(msg) => Error::Unknown(msg),
}
}
}
impl<M: fmt::Debug, E: StdSyncSendError> From<oneshot::error::RecvError> for Error<M, E> {
fn from(_: oneshot::error::RecvError) -> Self {
Error::NoResponse
}
}
impl Error<Box<dyn Message>> {
pub fn from_typed<M: Message>(err: Error<M>) -> Self {
match err {
Error::SendError(SendError::Closed(m)) => {
Error::SendError(SendError::Closed(m.into_boxed()))
}
Error::SendError(SendError::Full(m)) => {
Error::SendError(SendError::Full(m.into_boxed()))
}
Error::TryAgain(inner) => Error::TryAgain(inner.into_boxed()),
Error::WrongMessageType(m) => Error::WrongMessageType(m.into_boxed()),
Error::NoResponse => Error::NoResponse,
Error::NoReceivers => Error::NoReceivers,
Error::Serialization(s) => Error::Serialization(s),
Error::Other(inner) => Error::Other(inner),
Error::OtherBoxed(inner) => Error::OtherBoxed(inner),
Error::AddListenerError => Error::AddListenerError,
Error::MessageCastError => Error::MessageCastError,
Error::TypeTagNotRegistered(tt) => Error::TypeTagNotRegistered(tt),
Error::NotReady => Error::NotReady,
Error::Unknown(msg) => Error::Unknown(msg),
}
}
}
// impl<M: fmt::Debug> Error<M> {
// pub fn downcast<E>(self) -> Result<E, Self> {
// match self {
// Error::OtherBoxed(inner) => Ok(),
// err => Err(err)
// }
// }
// }

View File

@ -1,92 +1,173 @@
use crate::{Bus, Message}; use core::iter::FromIterator;
use std::pin::Pin;
use crate::{error::StdSyncSendError, Bus, Message};
use async_trait::async_trait; use async_trait::async_trait;
use futures::Stream;
#[derive(Debug, Clone, Copy)]
pub struct ProducerStats {
pub completed: usize,
pub failed: usize,
}
#[async_trait]
pub trait AsyncProducer<M: Message>: Send + Sync {
type Item: Message;
type Response: Message;
type Error: StdSyncSendError;
async fn producer(
&self,
msg: M,
bus: &Bus,
) -> Result<Pin<Box<dyn Stream<Item = Result<Self::Item, Self::Error>> + Send + '_>>, Self::Error>;
async fn finish(&self, stats: ProducerStats, bus: &Bus) -> Result<Self::Response, Self::Error>;
}
pub trait Handler<M: Message>: Send + Sync { pub trait Handler<M: Message>: Send + Sync {
fn handle(&self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
fn sync(&self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
fn handle(&self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
pub trait AsyncHandler<M: Message>: Send + Sync { pub trait AsyncHandler<M: Message>: Send + Sync {
async fn handle(&self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
async fn sync(&self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
async fn handle(&self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
pub trait SynchronizedHandler<M: Message>: Send { pub trait SynchronizedHandler<M: Message>: Send {
fn handle(&mut self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
fn handle(&mut self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
pub trait AsyncSynchronizedHandler<M: Message>: Send { pub trait AsyncSynchronizedHandler<M: Message>: Send {
async fn handle(&mut self, msg: M, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
async fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
async fn handle(&mut self, msg: M, bus: &Bus) -> Result<Self::Response, Self::Error>;
async fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
pub trait BatchHandler<M: Message>: Send + Sync { pub trait BatchHandler<M: Message>: Send + Sync {
fn handle(&self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
fn sync(&self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
fn handle(&self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
pub trait AsyncBatchHandler<M: Message>: Send + Sync { pub trait AsyncBatchHandler<M: Message>: Send + Sync {
async fn handle(&self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
async fn sync(&self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
async fn handle(&self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
pub trait BatchSynchronizedHandler<M: Message>: Send { pub trait BatchSynchronizedHandler<M: Message>: Send {
fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
fn handle(&mut self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
pub trait AsyncBatchSynchronizedHandler<M: Message>: Send { pub trait AsyncBatchSynchronizedHandler<M: Message>: Send {
async fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
async fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
async fn handle(
&mut self,
msg: Self::InBatch,
bus: &Bus,
) -> Result<Self::OutBatch, Self::Error>;
async fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
pub trait LocalHandler<M: Message> { pub trait LocalHandler<M: Message> {
fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> Result<Self::Response, Self::Error>;
fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
pub trait LocalAsyncHandler<M: Message> { pub trait LocalAsyncHandler<M: Message> {
async fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError;
async fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
async fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> Result<Self::Response, Self::Error>;
async fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
pub trait LocalBatchHandler<M: Message> { pub trait LocalBatchHandler<M: Message> {
fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
fn handle(&mut self, msg: Self::InBatch, bus: &Bus) -> Result<Self::OutBatch, Self::Error>;
fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }
#[async_trait] #[async_trait]
pub trait LocalAsyncBatchHandler<M: Message> { pub trait LocalAsyncBatchHandler<M: Message> {
async fn handle(&mut self, msg: Vec<M>, bus: &Bus) -> anyhow::Result<()>; type Error: StdSyncSendError + Clone;
async fn sync(&mut self, _bus: &Bus) -> anyhow::Result<()> { type Response: Message;
type InBatch: FromIterator<M> + Send;
type OutBatch: IntoIterator<Item = Self::Response> + Send;
async fn handle(
&mut self,
msg: Self::InBatch,
bus: &Bus,
) -> Result<Self::OutBatch, Self::Error>;
async fn sync(&mut self, _bus: &Bus) -> Result<(), Self::Error> {
Ok(()) Ok(())
} }
} }

View File

@ -1,108 +1,124 @@
mod builder; mod builder;
mod envelop; mod envelop;
pub mod error;
mod handler; mod handler;
pub mod msgs;
mod receiver; mod receiver;
pub mod receivers; pub mod receivers;
mod relay;
mod stats;
mod trait_object; mod trait_object;
mod utils; pub mod type_tag;
pub mod __reexport {
pub use ctor;
pub use serde;
}
#[macro_use]
extern crate log;
pub mod derive {
pub use messagebus_derive::*;
}
// privavte
use core::{
any::Any,
sync::atomic::{AtomicBool, AtomicU64, Ordering},
time::Duration,
};
use smallvec::SmallVec;
use std::{
collections::{HashMap, HashSet},
sync::Arc,
};
use tokio::sync::Mutex;
use builder::BusBuilder; use builder::BusBuilder;
pub use envelop::Message; use error::{Error, SendError, StdSyncSendError};
use receiver::{Permit, Receiver};
use stats::Stats;
// public
pub use builder::Module;
pub use ctor;
pub use envelop::{IntoBoxedMessage, Message, MessageBounds, SharedMessage, TypeTag, TypeTagged};
pub use handler::*; pub use handler::*;
pub use receiver::SendError; pub use receiver::{
use receiver::{Receiver, ReceiverStats}; Action, Event, EventBoxed, ReciveTypedReceiver, ReciveUntypedReceiver, SendTypedReceiver,
use utils::binary_search_range_by_key; SendUntypedReceiver, TypeTagAccept, TypeTagAcceptItem,
use core::any::{Any, TypeId};
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
}; };
pub use relay::Relay;
pub use type_tag::{deserialize_shared_message, register_shared_message};
pub type Untyped = Arc<dyn Any + Send + Sync>; pub type Untyped = Arc<dyn Any + Send + Sync>;
pub type Result = anyhow::Result<()>;
type LookupQuery = (TypeTag, Option<TypeTag>, Option<TypeTag>);
static ID_COUNTER: AtomicU64 = AtomicU64::new(1);
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SendOptions {
Broadcast,
Except(u64),
Direct(u64),
Random,
Balanced,
}
impl Default for SendOptions {
fn default() -> Self {
Self::Broadcast
}
}
pub struct BusInner { pub struct BusInner {
receivers: Vec<(TypeId, Receiver)>, receivers: HashSet<Receiver>,
lookup: HashMap<LookupQuery, SmallVec<[Receiver; 4]>>,
closed: AtomicBool, closed: AtomicBool,
maintain: Mutex<()>,
} }
impl BusInner { impl BusInner {
pub(crate) fn new(mut receivers: Vec<(TypeId, Receiver)>) -> Self { pub(crate) fn new(receivers: HashSet<Receiver>) -> Self {
receivers.sort_unstable_by_key(|(k, _)| *k); let mut lookup = HashMap::new();
for recv in receivers.iter() {
for (msg, resp) in recv.iter_types() {
lookup
.entry((msg.clone(), None, None))
.or_insert_with(HashSet::new)
.insert(recv.clone());
if let Some((resp, err)) = resp {
lookup
.entry((msg.clone(), Some(resp.clone()), None))
.or_insert_with(HashSet::new)
.insert(recv.clone());
lookup
.entry((msg.clone(), None, Some(err.clone())))
.or_insert_with(HashSet::new)
.insert(recv.clone());
lookup
.entry((msg, Some(resp), Some(err)))
.or_insert_with(HashSet::new)
.insert(recv.clone());
}
}
}
let lookup = lookup
.into_iter()
.map(|(k, v)| (k, v.into_iter().collect()))
.collect();
Self { Self {
receivers, receivers,
lookup,
closed: AtomicBool::new(false), closed: AtomicBool::new(false),
maintain: Mutex::new(()),
} }
} }
pub fn close(&self) {
self.closed.store(true, Ordering::SeqCst);
for (_, r) in &self.receivers {
r.close();
}
}
pub async fn sync(&self) {
for (_, r) in &self.receivers {
r.sync().await;
}
}
pub fn stats(&self) -> impl Iterator<Item = ReceiverStats> + '_ {
self.receivers.iter().map(|(_, r)| r.stats())
}
pub fn try_send<M: Message>(&self, msg: M) -> core::result::Result<(), SendError<M>> {
if self.closed.load(Ordering::SeqCst) {
println!("Bus closed. Skipping send!");
return Ok(());
}
let tid = TypeId::of::<M>();
let range = binary_search_range_by_key(&self.receivers, &tid, |(k, _)| *k);
for i in (range.start + 1)..range.end {
self.receivers[i].1.try_broadcast(msg.clone())?;
}
if let Some((_, r)) = self.receivers.get(range.start) {
r.try_broadcast(msg.clone())?;
} else {
println!("Unhandled message {:?}", core::any::type_name::<M>());
}
Ok(())
}
#[inline]
pub fn send_blocking<M: Message>(&self, msg: M) -> core::result::Result<(), SendError<M>> {
futures::executor::block_on(self.send(msg))
}
pub async fn send<M: Message>(&self, msg: M) -> core::result::Result<(), SendError<M>> {
if self.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg));
}
let tid = TypeId::of::<M>();
let range = binary_search_range_by_key(&self.receivers, &tid, |(k, _)| *k);
for i in (range.start + 1)..range.end {
self.receivers[i].1.broadcast(msg.clone()).await?;
}
if let Some((_, r)) = self.receivers.get(range.start) {
r.broadcast(msg.clone()).await?;
} else {
println!("Unhandled message {:?}", core::any::type_name::<M>());
}
Ok(())
}
} }
#[derive(Clone)] #[derive(Clone)]
@ -110,17 +126,696 @@ pub struct Bus {
inner: Arc<BusInner>, inner: Arc<BusInner>,
} }
impl core::ops::Deref for Bus {
type Target = BusInner;
fn deref(&self) -> &Self::Target {
self.inner.as_ref()
}
}
impl Bus { impl Bus {
#[inline] #[inline]
pub fn build() -> BusBuilder { pub fn build() -> BusBuilder {
BusBuilder::new() BusBuilder::new()
} }
pub fn is_closing(&self) -> bool {
self.inner.closed.load(Ordering::SeqCst)
}
pub(crate) fn init(&self) {
for r in self.inner.receivers.iter() {
r.init(self).unwrap();
}
}
pub async fn ready(&self) {
for r in self.inner.receivers.iter() {
r.ready().await;
}
}
pub async fn close(&self) {
let _handle = self.inner.maintain.lock().await;
self.inner.closed.store(true, Ordering::SeqCst);
for r in self.inner.receivers.iter() {
let err = tokio::time::timeout(Duration::from_secs(20), r.close(self)).await;
if let Err(err) = err {
error!("Close timeout on {}: {}", r.name(), err);
}
}
}
pub async fn flush_all(&self) {
let fuse_count = 32i32;
let mut breaked = false;
let mut iters = 0usize;
for _ in 0..fuse_count {
iters += 1;
let mut flushed = false;
for r in self.inner.receivers.iter() {
if r.need_flush() {
flushed = true;
r.flush(self).await;
}
}
if !flushed {
breaked = true;
break;
}
}
if !breaked {
warn!(
"!!! WARNING: unable to reach equilibrium in {} iterations !!!",
fuse_count
);
} else {
info!("flushed in {} iterations !!!", iters);
}
}
pub async fn flush<M: Message>(&self) {
let fuse_count = 32i32;
let mut breaked = false;
let mut iters = 0usize;
for _ in 0..fuse_count {
let receivers =
self.select_receivers(M::type_tag_(), Default::default(), None, None, false);
iters += 1;
let mut flushed = false;
for r in receivers {
if r.need_flush() {
flushed = true;
r.flush(self).await;
}
}
if !flushed {
breaked = true;
break;
}
}
if !breaked {
warn!(
"!!! WARNING: unable to reach equilibrium in {} iterations !!!",
fuse_count
);
} else {
info!("flushed in {} iterations !!!", iters);
}
}
pub async fn flush2<M1: Message, M2: Message>(&self) {
let fuse_count = 32i32;
let mut breaked = false;
let mut iters = 0usize;
for _ in 0..fuse_count {
let receivers1 =
self.select_receivers(M1::type_tag_(), Default::default(), None, None, false);
let receivers2 =
self.select_receivers(M2::type_tag_(), Default::default(), None, None, false);
iters += 1;
let mut flushed = false;
for r in receivers1.chain(receivers2) {
if r.need_flush() {
flushed = true;
r.flush(self).await;
}
}
if !flushed {
breaked = true;
break;
}
}
if !breaked {
warn!(
"!!! WARNING: unable to reach equilibrium in {} iterations !!!",
fuse_count
);
} else {
info!("flushed in {} iterations !!!", iters);
}
}
pub async fn sync_all(&self) {
for r in self.inner.receivers.iter() {
r.sync(self).await;
}
}
pub async fn sync<M: Message>(&self) {
let receivers =
self.select_receivers(M::type_tag_(), Default::default(), None, None, false);
for r in receivers {
r.sync(self).await;
}
}
pub async fn sync2<M1: Message, M2: Message>(&self) {
let receivers1 =
self.select_receivers(M1::type_tag_(), Default::default(), None, None, false);
let receivers2 =
self.select_receivers(M2::type_tag_(), Default::default(), None, None, false);
for r in receivers1.chain(receivers2) {
r.sync(self).await;
}
}
pub async fn idle_all(&self) {
for r in self.inner.receivers.iter() {
r.flush(self).await;
r.idle().await;
}
}
pub async fn idle<M: Message>(&self) {
let receivers =
self.select_receivers(M::type_tag_(), Default::default(), None, None, false);
for r in receivers {
r.flush(self).await;
r.idle().await;
}
}
pub async fn idle2<M1: Message, M2: Message>(&self) {
let receivers1 =
self.select_receivers(M1::type_tag_(), Default::default(), None, None, false);
let receivers2 =
self.select_receivers(M2::type_tag_(), Default::default(), None, None, false);
for r in receivers1.chain(receivers2) {
r.flush(self).await;
r.idle().await;
}
}
#[inline]
pub async fn flush_and_sync_all(&self, force: bool) {
if !force {
self.idle_all().await;
}
println!("flushing all begin");
self.flush_all().await;
self.sync_all().await;
}
#[inline]
pub async fn flush_and_sync<M: Message>(&self, force: bool) {
if !force {
self.idle::<M>().await;
}
println!("flushing 1 begin");
self.flush::<M>().await;
self.sync::<M>().await;
}
#[inline]
pub async fn flush_and_sync2<M1: Message, M2: Message>(&self, force: bool) {
if !force {
self.idle2::<M1, M2>().await;
}
println!("flushing 2 begin");
self.flush2::<M1, M2>().await;
self.sync2::<M1, M2>().await;
}
fn try_reserve(&self, tt: &TypeTag, rs: &[Receiver]) -> Option<SmallVec<[Permit; 32]>> {
let mut permits = SmallVec::<[Permit; 32]>::new();
for r in rs {
if let Some(prmt) = r.try_reserve(tt) {
permits.push(prmt);
} else {
return None;
};
}
Some(permits)
}
#[inline]
pub fn try_send<M: Message + Clone>(&self, msg: M) -> Result<(), Error<M>> {
self.try_send_ext(msg, SendOptions::Broadcast)
}
pub fn try_send_ext<M: Message + Clone>(
&self,
msg: M,
_options: SendOptions,
) -> core::result::Result<(), Error<M>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let tt = msg.type_tag();
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if let Some(rs) = self.inner.lookup.get(&(msg.type_tag(), None, None)) {
let permits = if let Some(x) = self.try_reserve(&tt, rs) {
x
} else {
return Err(SendError::Full(msg).into());
};
let mut iter = permits.into_iter().zip(rs.iter());
let mut counter = 1;
let total = rs.len();
while counter < total {
let (p, r) = iter.next().unwrap();
let _ = r.send(self, mid, msg.clone(), false, p);
counter += 1;
}
if let Some((p, r)) = iter.next() {
let _ = r.send(self, mid, msg, false, p);
return Ok(());
}
}
warn!(
"Unhandled message {:?}: no receivers",
core::any::type_name::<M>()
);
Ok(())
}
#[inline]
pub fn send_blocking<M: Message + Clone>(&self, msg: M) -> Result<(), Error<M>> {
self.send_blocking_ext(msg, SendOptions::Broadcast)
}
#[inline]
pub fn send_blocking_ext<M: Message + Clone>(
&self,
msg: M,
options: SendOptions,
) -> core::result::Result<(), Error<M>> {
futures::executor::block_on(self.send_ext(msg, options))
}
#[inline]
pub async fn send<M: Message + Clone>(&self, msg: M) -> core::result::Result<(), Error<M>> {
Ok(self.send_ext(msg, SendOptions::Broadcast).await?)
}
pub async fn send_ext<M: Message + Clone>(
&self,
msg: M,
_options: SendOptions,
) -> core::result::Result<(), Error<M>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let tt = msg.type_tag();
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if let Some(rs) = self.inner.lookup.get(&(msg.type_tag(), None, None)) {
if let Some((last, head)) = rs.split_last() {
for r in head {
let _ = r.send(self, mid, msg.clone(), false, r.reserve(&tt).await);
}
let _ = last.send(self, mid, msg, false, last.reserve(&tt).await);
return Ok(());
}
}
warn!(
"Unhandled message {:?}: no receivers",
core::any::type_name::<M>()
);
Ok(())
}
#[inline]
pub fn force_send<M: Message + Clone>(&self, msg: M) -> Result<(), Error<M>> {
self.force_send_ext(msg, SendOptions::Broadcast)
}
pub fn force_send_ext<M: Message + Clone>(
&self,
msg: M,
_options: SendOptions,
) -> core::result::Result<(), Error<M>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if let Some(rs) = self.inner.lookup.get(&(msg.type_tag(), None, None)) {
if let Some((last, head)) = rs.split_last() {
for r in head {
let _ = r.force_send(self, mid, msg.clone(), false);
}
let _ = last.force_send(self, mid, msg, false);
return Ok(());
}
}
warn!(
"Unhandled message {:?}: no receivers",
core::any::type_name::<M>()
);
Ok(())
}
#[inline]
pub fn try_send_one<M: Message>(&self, msg: M) -> Result<(), Error<M>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let tt = msg.type_tag();
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if let Some(rs) = self
.inner
.lookup
.get(&(msg.type_tag(), None, None))
.and_then(|rs| rs.first())
{
let permits = if let Some(x) = rs.try_reserve(&tt) {
x
} else {
return Err(SendError::Full(msg).into());
};
Ok(rs.send(self, mid, msg, false, permits)?)
} else {
Err(Error::NoReceivers)
}
}
pub async fn send_one<M: Message>(&self, msg: M) -> Result<(), Error<M>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let tt = msg.type_tag();
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if let Some(rs) = self
.inner
.lookup
.get(&(msg.type_tag(), None, None))
.and_then(|rs| rs.first())
{
Ok(rs.send(self, mid, msg, false, rs.reserve(&tt).await)?)
} else {
Err(Error::NoReceivers)
}
}
#[inline]
pub fn send_one_blocking<M: Message>(&self, msg: M) -> Result<(), Error<M>> {
futures::executor::block_on(self.send_one(msg))
}
pub async fn request<M: Message, R: Message>(
&self,
req: M,
options: SendOptions,
) -> Result<R, Error<M>> {
let tid = M::type_tag_();
let rid = R::type_tag_();
let mut iter = self.select_receivers(tid.clone(), options, Some(rid), None, true);
if let Some(rc) = iter.next() {
let (mid, rx) = rc
.add_response_waiter::<R>()
.map_err(|x| x.specify::<M>())?;
let mid = mid | 1 << (u64::BITS - 1);
rc.send(self, mid, req, true, rc.reserve(&tid).await)?;
rx.await.map_err(|x| x.specify::<M>())
} else {
Err(Error::NoReceivers)
}
}
pub async fn request_we<M, R, E>(&self, req: M, options: SendOptions) -> Result<R, Error<M, E>>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
let tid = M::type_tag_();
let rid = R::type_tag_();
let eid = E::type_tag_();
let mut iter = self.select_receivers(tid.clone(), options, Some(rid), Some(eid), true);
if let Some(rc) = iter.next() {
let (mid, rx) = rc.add_response_waiter_we::<R, E>().map_err(|x| {
x.map_err(|_| unimplemented!())
.map_msg(|_| unimplemented!())
})?;
rc.send(
self,
mid | 1 << (u64::BITS - 1),
req,
true,
rc.reserve(&tid).await,
)
.map_err(|x| x.map_err(|_| unimplemented!()))?;
rx.await.map_err(|x| x.specify::<M>())
} else {
Err(Error::NoReceivers)
}
}
pub async fn send_boxed(
&self,
msg: Box<dyn Message>,
options: SendOptions,
) -> Result<(), Error<Box<dyn Message>>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let tt = msg.type_tag();
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
let mut iter = self.select_receivers(tt.clone(), options, None, None, false);
let first = iter.next();
for r in iter {
let _ = r.send_boxed(
self,
mid,
msg.try_clone_boxed().unwrap(),
false,
r.reserve(&tt).await,
);
}
if let Some(r) = first {
let _ = r.send_boxed(
self,
mid,
msg.try_clone_boxed().unwrap(),
false,
r.reserve(&tt).await,
);
} else {
warn!("Unhandled message: no receivers");
}
Ok(())
}
pub async fn send_boxed_one(
&self,
msg: Box<dyn Message>,
options: SendOptions,
) -> Result<(), Error<Box<dyn Message>>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(msg).into());
}
let tt = msg.type_tag();
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
let mut iter = self.select_receivers(tt.clone(), options, None, None, false);
if let Some(rs) = iter.next() {
Ok(rs.send_boxed(self, mid, msg, false, rs.reserve(&tt).await)?)
} else {
Err(Error::NoReceivers)
}
}
pub async fn request_boxed(
&self,
req: Box<dyn Message>,
options: SendOptions,
) -> Result<Box<dyn Message>, Error<Box<dyn Message>>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(req).into());
}
let tt = req.type_tag();
let mut iter = self.select_receivers(tt.clone(), options, None, None, true);
if let Some(rc) = iter.next() {
let (mid, rx) = rc.add_response_waiter_boxed().map_err(|x| {
x.map_err(|_| unimplemented!())
.map_msg(|_| unimplemented!())
})?;
rc.send_boxed(
self,
mid | 1 << (usize::BITS - 1),
req,
true,
rc.reserve(&tt).await,
)?;
rx.await.map_err(|x| x.specify::<Box<dyn Message>>())
} else {
Err(Error::NoReceivers)
}
}
pub async fn request_boxed_we<E: StdSyncSendError>(
&self,
req: Box<dyn Message>,
options: SendOptions,
) -> Result<Box<dyn Message>, Error<Box<dyn Message>, E>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(req).into());
}
let tt = req.type_tag();
let eid = E::type_tag_();
let mut iter = self.select_receivers(tt.clone(), options, None, Some(eid), true);
if let Some(rc) = iter.next() {
let (mid, rx) = rc.add_response_waiter_boxed_we().map_err(|x| {
x.map_err(|_| unimplemented!())
.map_msg(|_| unimplemented!())
})?;
rc.send_boxed(
self,
mid | 1 << (usize::BITS - 1),
req,
true,
rc.reserve(&tt).await,
)
.map_err(|x| x.map_err(|_| unimplemented!()))?;
rx.await.map_err(|x| x.specify::<Box<dyn Message>>())
} else {
Err(Error::NoReceivers)
}
}
pub async fn send_deserialize_one<'a, 'b: 'a, 'c: 'a>(
&'a self,
tt: TypeTag,
de: &'b mut dyn erased_serde::Deserializer<'c>,
_options: SendOptions,
) -> Result<(), Error<Box<dyn Message>>> {
if self.inner.closed.load(Ordering::SeqCst) {
warn!("closed message bus");
return Err(Error::NoResponse);
}
let mid = ID_COUNTER.fetch_add(1, Ordering::Relaxed);
if let Some(rs) = self
.inner
.lookup
.get(&(tt.clone(), None, None))
.and_then(|rs| rs.first())
{
let msg = deserialize_shared_message(tt.clone(), de)?;
Ok(rs.send_boxed(self, mid, msg.upcast_box(), false, rs.reserve(&tt).await)?)
} else {
Err(Error::NoReceivers)
}
}
pub async fn request_deserialize<'a, 'b: 'a, 'c: 'a>(
&'a self,
tt: TypeTag,
de: &'b mut dyn erased_serde::Deserializer<'c>,
options: SendOptions,
) -> Result<Box<dyn Message>, Error<Box<dyn Message>>> {
if self.inner.closed.load(Ordering::SeqCst) {
warn!("closed message bus");
return Err(Error::NoResponse);
}
let mut iter = self.select_receivers(tt.clone(), options, None, None, true);
if let Some(rc) = iter.next() {
let (mid, rx) = rc.add_response_waiter_boxed().unwrap();
let msg = deserialize_shared_message(tt.clone(), de)?;
rc.send_boxed(
self,
mid | 1 << (usize::BITS - 1),
msg.upcast_box(),
true,
rc.reserve(&tt).await,
)?;
rx.await.map_err(|x| x.specify::<Box<dyn Message>>())
} else {
Err(Error::NoReceivers)
}
}
pub fn stats(&self) -> impl Iterator<Item = Stats> + '_ {
self.inner.receivers.iter().map(|x| x.stats())
}
#[inline]
fn select_receivers(
&self,
tid: TypeTag,
options: SendOptions,
rid: Option<TypeTag>,
eid: Option<TypeTag>,
is_req: bool,
) -> impl Iterator<Item = &Receiver> + '_ {
self.inner
.lookup
.get(&(tid.clone(), rid.clone(), eid.clone()))
.into_iter()
.flatten()
.filter(move |r| r.accept(is_req, &tid, rid.as_ref(), eid.as_ref()))
.filter(move |r| match options {
SendOptions::Except(id) => id != r.id(),
SendOptions::Direct(id) => id == r.id(),
_ => true,
})
}
} }

View File

@ -1,10 +0,0 @@
use std::sync::Arc;
#[derive(Clone, Debug)]
pub struct Error(pub Arc<anyhow::Error>);
impl<T: Into<anyhow::Error>> From<T> for Error {
fn from(e: T) -> Self {
Self(Arc::new(e.into()))
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,65 @@
use std::{ use std::{
any::TypeId,
marker::PhantomData,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, Ordering},
Arc, Arc,
}, },
task::{Context, Poll},
}; };
use crate::{receiver::ReceiverStats, receivers::mpsc};
use futures::{Future, StreamExt};
use super::{BufferUnorderedConfig, BufferUnorderedStats};
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, buffer_unordered_poller_macro,
msgs, builder::ReceiverSubscriberBuilder,
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, error::{Error, StdSyncSendError},
receiver::{
Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers::Request,
AsyncHandler, Bus, Message, Untyped, AsyncHandler, Bus, Message, Untyped,
}; };
pub struct BufferUnorderedAsyncSubscriber<T, M> use super::{BufferUnorderedConfig, BufferUnorderedStats};
use futures::{Future, Stream};
use parking_lot::Mutex;
use tokio::sync::mpsc::{self, UnboundedSender};
buffer_unordered_poller_macro!(
T,
AsyncHandler,
|mid, msg, bus, ut: Arc<T>, stx: UnboundedSender<_>, task_permit| {
tokio::spawn(async move {
let resp = ut.handle(msg, &bus).await;
drop(task_permit);
stx.send(Event::Response(mid, resp.map_err(Error::Other)))
.unwrap();
})
},
|bus, ut: Arc<T>| { async move { ut.sync(&bus).await } }
);
pub struct BufferUnorderedAsync<M, R, E>
where where
T: AsyncHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
cfg: BufferUnorderedConfig, tx: mpsc::UnboundedSender<Request<M>>,
_m: PhantomData<(T, M)>, stats: Arc<BufferUnorderedStats>,
srx: Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
} }
impl<T, M> ReceiverSubscriber<T> for BufferUnorderedAsyncSubscriber<T, M> impl<T, M, R, E> ReceiverSubscriberBuilder<T, M, R, E> for BufferUnorderedAsync<M, R, E>
where where
T: AsyncHandler<M> + 'static, T: AsyncHandler<M, Response = R, Error = E> + 'static,
R: Message,
M: Message, M: Message,
E: StdSyncSendError,
{ {
fn subscribe( type Config = BufferUnorderedConfig;
self,
) -> ( fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback) {
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let stats = Arc::new(BufferUnorderedStats { let stats = Arc::new(BufferUnorderedStats {
buffer: AtomicU64::new(0), buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _), buffer_total: AtomicU64::new(cfg.buffer_size as _),
@ -50,154 +67,81 @@ where
parallel_total: AtomicU64::new(cfg.max_parallel as _), parallel_total: AtomicU64::new(cfg.max_parallel as _),
}); });
let (tx, rx) = mpsc::channel(cfg.buffer_size); let (stx, srx) = mpsc::unbounded_channel();
let arc = Arc::new(BufferUnorderedAsync::<M> { let (tx, rx) = mpsc::unbounded_channel();
tx, let stats_clone = stats.clone();
stats: stats.clone(),
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(buffer_unordered_poller::<T, M, R, E>(
as Pin<Box<dyn Future<Output = ()> + Send>> rx,
bus,
ut,
stats_clone,
cfg,
stx,
)) as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller) (
BufferUnorderedAsync::<M, R, E> {
tx,
stats,
srx: Mutex::new(Some(srx)),
},
poller,
)
} }
} }
async fn buffer_unordered_poller<T, M>( impl<M, R, E> SendUntypedReceiver for BufferUnorderedAsync<M, R, E>
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<BufferUnorderedStats>,
cfg: BufferUnorderedConfig,
) where
T: AsyncHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<T>().unwrap();
let mut x = rx
.map(|msg| {
stats.buffer.fetch_sub(1, Ordering::Relaxed);
stats.parallel.fetch_add(1, Ordering::Relaxed);
let bus = bus.clone();
let ut = ut.clone();
tokio::task::spawn(async move { ut.handle(msg, &bus).await })
})
.buffer_unordered(cfg.max_parallel);
while let Some(err) = x.next().await {
stats.parallel.fetch_sub(1, Ordering::Relaxed);
match err {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn(async move { ut.sync(&bus_clone).await }).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] BufferUnorderedAsync<{}>",
std::any::type_name::<M>()
);
}
pub struct BufferUnorderedAsync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<BufferUnorderedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for BufferUnorderedAsync<M>
where where
T: AsyncHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
type Entry = BufferUnorderedAsyncSubscriber<T, M>; fn send(&self, m: Action, _bus: &Bus) -> Result<(), Error<Action>> {
type Config = BufferUnorderedConfig; match self.tx.send(Request::Action(m)) {
Ok(_) => Ok(()),
fn build(cfg: Self::Config) -> Self::Entry { Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
BufferUnorderedAsyncSubscriber { _ => unimplemented!(),
cfg,
_m: Default::default(),
} }
} }
} }
impl<M: Message> TypedReceiver<M> for BufferUnorderedAsync<M> { impl<M, R, E> SendTypedReceiver<M> for BufferUnorderedAsync<M, R, E>
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> { where
match self.tx.poll_ready(ctx) { M: Message,
Poll::Ready(_) => Poll::Ready(()), R: Message,
Poll::Pending => Poll::Pending, E: StdSyncSendError,
} {
} fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => { Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed); self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
} }
Err(err) => Err(err), Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
} }
} }
} }
impl<M: Message> ReceiverTrait for BufferUnorderedAsync<M> { impl<M, R, E> ReciveTypedReceiver<R, E> for BufferUnorderedAsync<M, R, E>
fn typed(&self) -> AnyReceiver<'_> { where
AnyReceiver::new(self) M: Message,
} R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn type_id(&self) -> TypeId { fn event_stream(&self, _: Bus) -> Self::Stream {
TypeId::of::<BufferUnorderedAsync<M>>() let mut rx = self.srx.lock().take().unwrap();
}
fn close(&self) { Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
self.tx.close();
}
fn stats(&self) -> ReceiverStats {
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
(
"buffer_total".into(),
self.stats.buffer_total.load(Ordering::SeqCst),
),
(
"parallel".into(),
self.stats.parallel.load(Ordering::SeqCst),
),
(
"parallel_total".into(),
self.stats.parallel_total.load(Ordering::SeqCst),
),
],
}
}
fn sync(&self) {
self.tx.flush();
}
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
} }
} }

View File

@ -3,8 +3,9 @@ mod sync;
use std::sync::atomic::AtomicU64; use std::sync::atomic::AtomicU64;
pub use r#async::{BufferUnorderedAsync, BufferUnorderedAsyncSubscriber}; pub use r#async::BufferUnorderedAsync;
pub use sync::{BufferUnorderedSync, BufferUnorderedSyncSubscriber}; use serde_derive::{Deserialize, Serialize};
pub use sync::BufferUnorderedSync;
#[derive(Debug)] #[derive(Debug)]
pub struct BufferUnorderedStats { pub struct BufferUnorderedStats {
@ -14,7 +15,7 @@ pub struct BufferUnorderedStats {
pub parallel_total: AtomicU64, pub parallel_total: AtomicU64,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct BufferUnorderedConfig { pub struct BufferUnorderedConfig {
pub buffer_size: usize, pub buffer_size: usize,
pub max_parallel: usize, pub max_parallel: usize,
@ -28,3 +29,62 @@ impl Default for BufferUnorderedConfig {
} }
} }
} }
#[macro_export]
macro_rules! buffer_unordered_poller_macro {
($t: tt, $h: tt, $st1: expr, $st2: expr) => {
async fn buffer_unordered_poller<$t, M, R, E>(
mut rx: mpsc::UnboundedReceiver<Request<M>>,
bus: Bus,
ut: Untyped,
_stats: Arc<BufferUnorderedStats>,
cfg: BufferUnorderedConfig,
stx: mpsc::UnboundedSender<Event<R, E>>,
) where
$t: $h<M, Response = R, Error = E> + 'static,
M: Message,
R: Message,
E: StdSyncSendError,
{
let ut = ut.downcast::<$t>().unwrap();
let semaphore = Arc::new(tokio::sync::Semaphore::new(cfg.max_parallel));
while let Some(msg) = rx.recv().await {
match msg {
Request::Request(mid, msg, _req) => {
#[allow(clippy::redundant_closure_call)]
let _ = ($st1)(
mid,
msg,
bus.clone(),
ut.clone(),
stx.clone(),
semaphore.clone().acquire_owned().await,
);
}
Request::Action(Action::Init(..)) => stx.send(Event::Ready).unwrap(),
Request::Action(Action::Close) => rx.close(),
Request::Action(Action::Flush) => {
let _ = semaphore.acquire_many(cfg.max_parallel as _).await;
stx.send(Event::Flushed).unwrap();
}
Request::Action(Action::Sync) => {
let lock = semaphore.acquire_many(cfg.max_parallel as _).await;
#[allow(clippy::redundant_closure_call)]
let resp = ($st2)(bus.clone(), ut.clone()).await;
drop(lock);
stx.send(Event::Synchronized(resp.map_err(Error::Other)))
.unwrap();
}
_ => unimplemented!(),
}
}
}
};
}

View File

@ -1,48 +1,68 @@
use crate::{receiver::ReceiverStats, receivers::mpsc};
use futures::{Future, StreamExt};
use std::{ use std::{
any::TypeId,
marker::PhantomData,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, Ordering},
Arc, Arc,
}, },
task::{Context, Poll},
}; };
use super::{BufferUnorderedConfig, BufferUnorderedStats}; use super::{BufferUnorderedConfig, BufferUnorderedStats};
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, buffer_unordered_poller_macro,
msgs, builder::ReceiverSubscriberBuilder,
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, error::{Error, StdSyncSendError},
receiver::{
Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers::Request,
Bus, Handler, Message, Untyped, Bus, Handler, Message, Untyped,
}; };
pub struct BufferUnorderedSyncSubscriber<T, M> use futures::{Future, Stream};
use parking_lot::Mutex;
use tokio::sync::mpsc::{self, UnboundedSender};
buffer_unordered_poller_macro!(
T,
Handler,
|mid, msg, bus, ut: Arc<T>, stx: UnboundedSender<_>, task_permit| {
tokio::task::spawn_blocking(move || {
let resp = ut.handle(msg, &bus);
drop(task_permit);
stx.send(Event::Response(mid, resp.map_err(Error::Other)))
.unwrap();
})
},
|bus, ut: Arc<T>| async move {
tokio::task::spawn_blocking(move || ut.sync(&bus))
.await
.unwrap()
}
);
pub struct BufferUnorderedSync<M, R, E>
where where
T: Handler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
cfg: BufferUnorderedConfig, tx: mpsc::UnboundedSender<Request<M>>,
_m: PhantomData<(M, T)>, stats: Arc<BufferUnorderedStats>,
srx: Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
} }
impl<T, M> ReceiverSubscriber<T> for BufferUnorderedSyncSubscriber<T, M> impl<T, M, R, E> ReceiverSubscriberBuilder<T, M, R, E> for BufferUnorderedSync<M, R, E>
where where
T: Handler<M> + 'static, T: Handler<M, Response = R, Error = E> + 'static,
R: Message,
M: Message, M: Message,
E: StdSyncSendError,
{ {
fn subscribe( type Config = BufferUnorderedConfig;
self,
) -> ( fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback) {
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let (tx, rx) = mpsc::channel(cfg.buffer_size);
let stats = Arc::new(BufferUnorderedStats { let stats = Arc::new(BufferUnorderedStats {
buffer: AtomicU64::new(0), buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _), buffer_total: AtomicU64::new(cfg.buffer_size as _),
@ -50,154 +70,81 @@ where
parallel_total: AtomicU64::new(cfg.max_parallel as _), parallel_total: AtomicU64::new(cfg.max_parallel as _),
}); });
let arc = Arc::new(BufferUnorderedSync::<M> { let (stx, srx) = mpsc::unbounded_channel();
tx, let (tx, rx) = mpsc::unbounded_channel();
stats: stats.clone(), let stats_clone = stats.clone();
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(buffer_unordered_poller::<T, M, R, E>(
as Pin<Box<dyn Future<Output = ()> + Send>> rx,
bus,
ut,
stats_clone,
cfg,
stx,
)) as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller) (
BufferUnorderedSync::<M, R, E> {
tx,
stats,
srx: Mutex::new(Some(srx)),
},
poller,
)
} }
} }
async fn buffer_unordered_poller<T, M>( impl<M, R, E> SendUntypedReceiver for BufferUnorderedSync<M, R, E>
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<BufferUnorderedStats>,
cfg: BufferUnorderedConfig,
) where
T: Handler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<T>().unwrap();
let mut x = rx
.map(|msg| {
stats.buffer.fetch_sub(1, Ordering::Relaxed);
stats.parallel.fetch_add(1, Ordering::Relaxed);
let bus = bus.clone();
let ut = ut.clone();
tokio::task::spawn_blocking(move || ut.handle(msg, &bus))
})
.buffer_unordered(cfg.max_parallel);
while let Some(err) = x.next().await {
stats.parallel.fetch_sub(1, Ordering::Relaxed);
match err {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn_blocking(move || ut.sync(&bus_clone)).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] BufferUnorderedSync<{}>",
std::any::type_name::<M>()
);
}
pub struct BufferUnorderedSync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<BufferUnorderedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for BufferUnorderedSync<M>
where where
T: Handler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
type Entry = BufferUnorderedSyncSubscriber<T, M>; fn send(&self, msg: Action, _bus: &Bus) -> Result<(), Error<Action>> {
type Config = BufferUnorderedConfig; match self.tx.send(Request::Action(msg)) {
Ok(_) => Ok(()),
fn build(cfg: Self::Config) -> Self::Entry { Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
BufferUnorderedSyncSubscriber { _ => unimplemented!(),
cfg,
_m: Default::default(),
} }
} }
} }
impl<M: Message> TypedReceiver<M> for BufferUnorderedSync<M> { impl<M, R, E> SendTypedReceiver<M> for BufferUnorderedSync<M, R, E>
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> { where
match self.tx.poll_ready(ctx) { M: Message,
Poll::Ready(_) => Poll::Ready(()), R: Message,
Poll::Pending => Poll::Pending, E: StdSyncSendError,
} {
} fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => { Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed); self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
} }
Err(err) => Err(err), Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
} }
} }
} }
impl<M: Message> ReceiverTrait for BufferUnorderedSync<M> { impl<M, R, E> ReciveTypedReceiver<R, E> for BufferUnorderedSync<M, R, E>
fn typed(&self) -> AnyReceiver<'_> { where
AnyReceiver::new(self) M: Message,
} R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn type_id(&self) -> TypeId { fn event_stream(&self, _: Bus) -> Self::Stream {
TypeId::of::<BufferUnorderedSync<M>>() let mut rx = self.srx.lock().take().unwrap();
}
fn stats(&self) -> ReceiverStats { Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
(
"buffer_total".into(),
self.stats.buffer_total.load(Ordering::SeqCst),
),
(
"parallel".into(),
self.stats.parallel.load(Ordering::SeqCst),
),
(
"parallel_total".into(),
self.stats.parallel_total.load(Ordering::SeqCst),
),
],
}
}
fn close(&self) {
self.tx.close();
}
fn sync(&self) {
self.tx.flush();
}
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
} }
} }

View File

@ -1,48 +1,64 @@
use std::{ use std::{
any::TypeId,
marker::PhantomData,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, Ordering},
Arc, Arc,
}, },
task::{Context, Poll},
}; };
use crate::{receiver::ReceiverStats, receivers::mpsc};
use futures::{Future, StreamExt};
use super::{BufferUnorderedBatchedConfig, BufferUnorderedBatchedStats};
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, buffer_unordered_batch_poller_macro,
msgs, builder::ReceiverSubscriberBuilder,
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, error::{Error, StdSyncSendError},
receiver::{
Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers::Request,
AsyncBatchHandler, Bus, Message, Untyped, AsyncBatchHandler, Bus, Message, Untyped,
}; };
pub struct BufferUnorderedBatchedAsyncSubscriber<T, M> use super::{BufferUnorderedBatchedConfig, BufferUnorderedBatchedStats};
use futures::{Future, Stream};
use parking_lot::Mutex;
use tokio::sync::mpsc::{self, UnboundedSender};
buffer_unordered_batch_poller_macro!(
T,
AsyncBatchHandler,
|mids: Vec<_>, msgs, bus, ut: Arc<T>, task_permit, stx: UnboundedSender<_>| {
tokio::spawn(async move {
let resp = ut.handle(msgs, &bus).await;
drop(task_permit);
crate::process_batch_result!(resp, mids, stx);
})
},
|bus, ut: Arc<T>| { async move { ut.sync(&bus).await } }
);
pub struct BufferUnorderedBatchedAsync<M, R, E>
where where
T: AsyncBatchHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
cfg: BufferUnorderedBatchedConfig, tx: mpsc::UnboundedSender<Request<M>>,
_m: PhantomData<(T, M)>, stats: Arc<BufferUnorderedBatchedStats>,
srx: Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
} }
impl<T, M> ReceiverSubscriber<T> for BufferUnorderedBatchedAsyncSubscriber<T, M> impl<T, M, R> ReceiverSubscriberBuilder<T, M, R, T::Error>
for BufferUnorderedBatchedAsync<M, R, T::Error>
where where
T: AsyncBatchHandler<M> + 'static, T: AsyncBatchHandler<M, Response = R> + 'static,
T::Error: StdSyncSendError + Clone,
R: Message,
M: Message, M: Message,
{ {
fn subscribe( type Config = BufferUnorderedBatchedConfig;
self,
) -> ( fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback) {
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let stats = Arc::new(BufferUnorderedBatchedStats { let stats = Arc::new(BufferUnorderedBatchedStats {
buffer: AtomicU64::new(0), buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _), buffer_total: AtomicU64::new(cfg.buffer_size as _),
@ -52,173 +68,81 @@ where
batch_size: AtomicU64::new(cfg.batch_size as _), batch_size: AtomicU64::new(cfg.batch_size as _),
}); });
let (tx, rx) = mpsc::channel(cfg.buffer_size); let (stx, srx) = mpsc::unbounded_channel();
let arc = Arc::new(BufferUnorderedBatchedAsync::<M> { let (tx, rx) = mpsc::unbounded_channel();
tx, let stats_clone = stats.clone();
stats: stats.clone(),
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(buffer_unordered_batch_poller::<T, M, R>(
as Pin<Box<dyn Future<Output = ()> + Send>> rx,
bus,
ut,
stats_clone,
cfg,
stx,
)) as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller) (
BufferUnorderedBatchedAsync::<M, R, T::Error> {
tx,
stats,
srx: Mutex::new(Some(srx)),
},
poller,
)
} }
} }
async fn buffer_unordered_poller<T, M>( impl<M, R, E> SendUntypedReceiver for BufferUnorderedBatchedAsync<M, R, E>
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<BufferUnorderedBatchedStats>,
cfg: BufferUnorderedBatchedConfig,
) where
T: AsyncBatchHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<T>().unwrap();
let rx = rx
.inspect(|_| {
stats.buffer.fetch_sub(1, Ordering::Relaxed);
stats.batch.fetch_add(1, Ordering::Relaxed);
});
let rx = if cfg.when_ready {
rx.ready_chunks(cfg.batch_size)
.left_stream()
} else {
rx.chunks(cfg.batch_size)
.right_stream()
};
let mut rx = rx
.map(|msgs| {
stats.batch.fetch_sub(msgs.len() as _, Ordering::Relaxed);
stats.parallel.fetch_add(1, Ordering::Relaxed);
let bus_clone = bus.clone();
let ut = ut.clone();
tokio::task::spawn(async move { ut.handle(msgs, &bus_clone).await })
})
.buffer_unordered(cfg.max_parallel);
while let Some(err) = rx.next().await {
stats.parallel.fetch_sub(1, Ordering::Relaxed);
match err {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn(async move { ut.sync(&bus_clone).await }).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] BufferUnorderedBatchedAsync<{}>",
std::any::type_name::<M>()
);
}
pub struct BufferUnorderedBatchedAsync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<BufferUnorderedBatchedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for BufferUnorderedBatchedAsync<M>
where where
T: AsyncBatchHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
type Entry = BufferUnorderedBatchedAsyncSubscriber<T, M>; fn send(&self, m: Action, _bus: &Bus) -> Result<(), Error<Action>> {
type Config = BufferUnorderedBatchedConfig; match self.tx.send(Request::Action(m)) {
Ok(_) => Ok(()),
fn build(cfg: Self::Config) -> Self::Entry { Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
BufferUnorderedBatchedAsyncSubscriber { _ => unimplemented!(),
cfg,
_m: Default::default(),
} }
} }
} }
impl<M: Message> TypedReceiver<M> for BufferUnorderedBatchedAsync<M> { impl<M, R, E> SendTypedReceiver<M> for BufferUnorderedBatchedAsync<M, R, E>
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> { where
match self.tx.poll_ready(ctx) { M: Message,
Poll::Ready(_) => Poll::Ready(()), R: Message,
Poll::Pending => Poll::Pending, E: StdSyncSendError,
} {
} fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => { Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed); self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
} }
Err(err) => Err(err), Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
} }
} }
} }
impl<M: Message> ReceiverTrait for BufferUnorderedBatchedAsync<M> { impl<M, R, E> ReciveTypedReceiver<R, E> for BufferUnorderedBatchedAsync<M, R, E>
fn typed(&self) -> AnyReceiver<'_> { where
AnyReceiver::new(self) M: Message,
} R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn type_id(&self) -> TypeId { fn event_stream(&self, _: Bus) -> Self::Stream {
TypeId::of::<BufferUnorderedBatchedAsync<M>>() let mut rx = self.srx.lock().take().unwrap();
}
fn close(&self) { Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
self.tx.close();
}
fn stats(&self) -> ReceiverStats {
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
(
"buffer_total".into(),
self.stats.buffer_total.load(Ordering::SeqCst),
),
(
"parallel".into(),
self.stats.parallel.load(Ordering::SeqCst),
),
(
"parallel_total".into(),
self.stats.parallel_total.load(Ordering::SeqCst),
),
("batch".into(), self.stats.batch.load(Ordering::SeqCst)),
(
"batch_size".into(),
self.stats.batch_size.load(Ordering::SeqCst),
),
],
}
}
fn sync(&self) {
self.tx.flush();
}
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
} }
} }

View File

@ -3,8 +3,9 @@ mod sync;
use std::sync::atomic::AtomicU64; use std::sync::atomic::AtomicU64;
pub use r#async::{BufferUnorderedBatchedAsync, BufferUnorderedBatchedAsyncSubscriber}; pub use r#async::BufferUnorderedBatchedAsync;
pub use sync::{BufferUnorderedBatchedSync, BufferUnorderedBatchedSyncSubscriber}; use serde_derive::{Deserialize, Serialize};
pub use sync::BufferUnorderedBatchedSync;
#[derive(Debug)] #[derive(Debug)]
pub struct BufferUnorderedBatchedStats { pub struct BufferUnorderedBatchedStats {
@ -16,7 +17,7 @@ pub struct BufferUnorderedBatchedStats {
pub batch_size: AtomicU64, pub batch_size: AtomicU64,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct BufferUnorderedBatchedConfig { pub struct BufferUnorderedBatchedConfig {
pub buffer_size: usize, pub buffer_size: usize,
pub max_parallel: usize, pub max_parallel: usize,
@ -34,3 +35,87 @@ impl Default for BufferUnorderedBatchedConfig {
} }
} }
} }
#[macro_export]
macro_rules! buffer_unordered_batch_poller_macro {
($t: tt, $h: tt, $st1: expr, $st2: expr) => {
async fn buffer_unordered_batch_poller<$t, M, R>(
mut rx: mpsc::UnboundedReceiver<Request<M>>,
bus: Bus,
ut: Untyped,
_stats: Arc<BufferUnorderedBatchedStats>,
cfg: BufferUnorderedBatchedConfig,
stx: mpsc::UnboundedSender<Event<R, $t::Error>>,
) where
$t: $h<M, Response = R> + 'static,
M: Message,
R: Message,
{
let ut = ut.downcast::<$t>().unwrap();
let semaphore = Arc::new(tokio::sync::Semaphore::new(cfg.max_parallel));
let mut buffer_mid = Vec::with_capacity(cfg.batch_size);
let mut buffer = Vec::with_capacity(cfg.batch_size);
while let Some(msg) = rx.recv().await {
let bus = bus.clone();
let ut = ut.clone();
let semaphore = semaphore.clone();
let stx = stx.clone();
match msg {
Request::Request(mid, msg, req) => {
buffer_mid.push((mid, req));
buffer.push(msg);
if buffer_mid.len() >= cfg.batch_size {
let task_permit = semaphore.acquire_owned().await;
let buffer_mid_clone = buffer_mid.drain(..).collect::<Vec<_>>();
let buffer_clone = buffer.drain(..).collect();
#[allow(clippy::redundant_closure_call)]
let _ =
($st1)(buffer_mid_clone, buffer_clone, bus, ut, task_permit, stx);
}
}
Request::Action(Action::Init(..)) => {
stx.send(Event::Ready).unwrap();
}
Request::Action(Action::Close) => {
rx.close();
}
Request::Action(Action::Flush) => {
let stx_clone = stx.clone();
if !buffer_mid.is_empty() {
let buffer_mid_clone = buffer_mid.drain(..).collect::<Vec<_>>();
let buffer_clone = buffer.drain(..).collect();
let task_permit = semaphore.clone().acquire_owned().await;
#[allow(clippy::redundant_closure_call)]
let _ =
($st1)(buffer_mid_clone, buffer_clone, bus, ut, task_permit, stx);
}
let _ = semaphore.acquire_many(cfg.max_parallel as _).await;
stx_clone.send(Event::Flushed).unwrap();
}
Request::Action(Action::Sync) => {
let lock = semaphore.acquire_many(cfg.max_parallel as _).await;
#[allow(clippy::redundant_closure_call)]
let resp = ($st2)(bus.clone(), ut.clone()).await;
drop(lock);
stx.send(Event::Synchronized(resp.map_err(Error::Other)))
.unwrap();
}
_ => unimplemented!(),
}
}
}
};
}

View File

@ -1,48 +1,70 @@
use crate::{receiver::ReceiverStats, receivers::mpsc};
use futures::{Future, StreamExt};
use std::{ use std::{
any::TypeId,
marker::PhantomData,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{AtomicU64, Ordering}, atomic::{AtomicU64, Ordering},
Arc, Arc,
}, },
task::{Context, Poll},
}; };
use super::{BufferUnorderedBatchedConfig, BufferUnorderedBatchedStats}; use super::{BufferUnorderedBatchedConfig, BufferUnorderedBatchedStats};
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, buffer_unordered_batch_poller_macro,
msgs, builder::ReceiverSubscriberBuilder,
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, error::{Error, StdSyncSendError},
Bus, BatchHandler, Message, Untyped, receiver::{
Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers::Request,
BatchHandler, Bus, Message, Untyped,
}; };
pub struct BufferUnorderedBatchedSyncSubscriber<T, M> use futures::{Future, Stream};
use parking_lot::Mutex;
use tokio::sync::mpsc::{self, UnboundedSender};
buffer_unordered_batch_poller_macro!(
T,
BatchHandler,
|mids: Vec<_>, msgs, bus, ut: Arc<T>, task_permit, stx: UnboundedSender<_>| {
tokio::task::spawn_blocking(move || {
let resp = ut.handle(msgs, &bus);
drop(task_permit);
crate::process_batch_result!(resp, mids, stx);
})
},
|bus, ut: Arc<T>| {
async move {
tokio::task::spawn_blocking(move || ut.sync(&bus))
.await
.unwrap()
}
}
);
pub struct BufferUnorderedBatchedSync<M, R, E>
where where
T: BatchHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
cfg: BufferUnorderedBatchedConfig, tx: mpsc::UnboundedSender<Request<M>>,
_m: PhantomData<(M, T)>, stats: Arc<BufferUnorderedBatchedStats>,
srx: Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
} }
impl<T, M> ReceiverSubscriber<T> for BufferUnorderedBatchedSyncSubscriber<T, M> impl<T, M, R> ReceiverSubscriberBuilder<T, M, R, T::Error>
for BufferUnorderedBatchedSync<M, R, T::Error>
where where
T: BatchHandler<M> + 'static, T: BatchHandler<M, Response = R> + 'static,
T::Error: StdSyncSendError,
R: Message,
M: Message, M: Message,
{ {
fn subscribe( type Config = BufferUnorderedBatchedConfig;
self,
) -> ( fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback) {
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let (tx, rx) = mpsc::channel(cfg.buffer_size);
let stats = Arc::new(BufferUnorderedBatchedStats { let stats = Arc::new(BufferUnorderedBatchedStats {
buffer: AtomicU64::new(0), buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _), buffer_total: AtomicU64::new(cfg.buffer_size as _),
@ -52,172 +74,81 @@ where
batch_size: AtomicU64::new(cfg.batch_size as _), batch_size: AtomicU64::new(cfg.batch_size as _),
}); });
let arc = Arc::new(BufferUnorderedBatchedSync::<M> { let (stx, srx) = mpsc::unbounded_channel();
tx, let (tx, rx) = mpsc::unbounded_channel();
stats: stats.clone(), let stats_clone = stats.clone();
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(buffer_unordered_batch_poller::<T, M, R>(
as Pin<Box<dyn Future<Output = ()> + Send>> rx,
bus,
ut,
stats_clone,
cfg,
stx,
)) as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller) (
BufferUnorderedBatchedSync::<M, R, T::Error> {
tx,
stats,
srx: Mutex::new(Some(srx)),
},
poller,
)
} }
} }
async fn buffer_unordered_poller<T, M>( impl<M, R, E> SendUntypedReceiver for BufferUnorderedBatchedSync<M, R, E>
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<BufferUnorderedBatchedStats>,
cfg: BufferUnorderedBatchedConfig,
) where
T: BatchHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<T>().unwrap();
let rx = rx
.inspect(|_| {
stats.buffer.fetch_sub(1, Ordering::Relaxed);
stats.batch.fetch_add(1, Ordering::Relaxed);
});
let rx = if cfg.when_ready {
rx.ready_chunks(cfg.batch_size)
.left_stream()
} else {
rx.chunks(cfg.batch_size)
.right_stream()
};
let mut rx = rx
.map(|msgs| {
stats.batch.fetch_sub(msgs.len() as _, Ordering::Relaxed);
stats.parallel.fetch_add(1, Ordering::Relaxed);
let bus = bus.clone();
let ut = ut.clone();
tokio::task::spawn_blocking(move || ut.handle(msgs, &bus))
})
.buffer_unordered(cfg.max_parallel);
while let Some(err) = rx.next().await {
stats.parallel.fetch_sub(1, Ordering::Relaxed);
match err {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn_blocking(move || ut.sync(&bus_clone)).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] BufferUnorderedBatchedSync<{}>",
std::any::type_name::<M>()
);
}
pub struct BufferUnorderedBatchedSync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<BufferUnorderedBatchedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for BufferUnorderedBatchedSync<M>
where where
T: BatchHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
type Entry = BufferUnorderedBatchedSyncSubscriber<T, M>; fn send(&self, msg: Action, _bus: &Bus) -> Result<(), Error<Action>> {
type Config = BufferUnorderedBatchedConfig; match self.tx.send(Request::Action(msg)) {
Ok(_) => Ok(()),
fn build(cfg: Self::Config) -> Self::Entry { Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
BufferUnorderedBatchedSyncSubscriber { _ => unimplemented!(),
cfg,
_m: Default::default(),
} }
} }
} }
impl<M: Message> TypedReceiver<M> for BufferUnorderedBatchedSync<M> { impl<M, R, E> SendTypedReceiver<M> for BufferUnorderedBatchedSync<M, R, E>
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> { where
match self.tx.poll_ready(ctx) { M: Message,
Poll::Ready(_) => Poll::Ready(()), R: Message,
Poll::Pending => Poll::Pending, E: StdSyncSendError,
} {
} fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => { Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed); self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(()) Ok(())
} }
Err(err) => Err(err), Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
} }
} }
} }
impl<M: Message> ReceiverTrait for BufferUnorderedBatchedSync<M> { impl<M, R, E> ReciveTypedReceiver<R, E> for BufferUnorderedBatchedSync<M, R, E>
fn typed(&self) -> AnyReceiver<'_> { where
AnyReceiver::new(self) M: Message,
} R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn type_id(&self) -> TypeId { fn event_stream(&self, _: Bus) -> Self::Stream {
TypeId::of::<BufferUnorderedBatchedSync<M>>() let mut rx = self.srx.lock().take().unwrap();
}
fn stats(&self) -> ReceiverStats { Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
(
"buffer_total".into(),
self.stats.buffer_total.load(Ordering::SeqCst),
),
(
"parallel".into(),
self.stats.parallel.load(Ordering::SeqCst),
),
(
"parallel_total".into(),
self.stats.parallel_total.load(Ordering::SeqCst),
),
("batch".into(), self.stats.batch.load(Ordering::SeqCst)),
(
"batch_size".into(),
self.stats.batch_size.load(Ordering::SeqCst),
),
],
}
}
fn close(&self) {
self.tx.close();
}
fn sync(&self) {
self.tx.flush();
}
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
} }
} }

View File

@ -1,29 +1,56 @@
mod buffer_unordered; mod buffer_unordered;
mod buffer_unordered_batched; mod buffer_unordered_batched;
mod mpsc_futures; // mod producer;
mod synchronize_batched; mod synchronize_batched;
mod synchronized; mod synchronized;
mod mpsc { pub use buffer_unordered::{BufferUnorderedAsync, BufferUnorderedConfig, BufferUnorderedSync};
pub use super::mpsc_futures::*;
}
pub use buffer_unordered::{
BufferUnorderedAsync, BufferUnorderedAsyncSubscriber, BufferUnorderedConfig,
BufferUnorderedSync, BufferUnorderedSyncSubscriber,
};
pub use buffer_unordered_batched::{ pub use buffer_unordered_batched::{
BufferUnorderedBatchedAsync, BufferUnorderedBatchedAsyncSubscriber, BufferUnorderedBatchedConfig, BufferUnorderedBatchedAsync, BufferUnorderedBatchedConfig, BufferUnorderedBatchedSync,
BufferUnorderedBatchedSync, BufferUnorderedBatchedSyncSubscriber,
};
pub use synchronized::{
SynchronizedAsync, SynchronizedAsyncSubscriber, SynchronizedConfig, SynchronizedSync,
SynchronizedSyncSubscriber,
}; };
pub use synchronized::{SynchronizedAsync, SynchronizedConfig, SynchronizedSync};
pub use synchronize_batched::{ pub use synchronize_batched::{
SynchronizeBatchedAsync, SynchronizeBatchedAsyncSubscriber, SynchronizeBatchedConfig, SynchronizedBatchedAsync, SynchronizedBatchedConfig, SynchronizedBatchedSync,
SynchronizeBatchedSync, SynchronizeBatchedSyncSubscriber,
}; };
// pub use producer::{AsyncProducer, AsyncProducerConfig};
use crate::receiver::Action;
#[macro_export]
macro_rules! process_batch_result {
($resp: expr, $mids: expr, $stx: expr) => {
let mids = $mids;
match $resp {
Ok(re) => {
let mut mids = mids.into_iter();
let mut re = re.into_iter();
while let Some((mid, _req)) = mids.next() {
if let Some(r) = re.next() {
$stx.send(Event::Response(mid, Ok(r))).unwrap();
} else {
$stx.send(Event::Response(mid, Err(Error::NoResponse)))
.unwrap();
}
}
}
Err(er) => {
for (mid, _req) in mids {
$stx.send(Event::Response(mid, Err(Error::Other(er.clone()))))
.unwrap();
}
$stx.send(Event::Error(Error::Other(er))).unwrap();
}
}
};
}
#[derive(Debug)]
pub(crate) enum Request<M> {
Action(Action),
Request(u64, M, bool),
}

View File

@ -1,142 +0,0 @@
use futures::{Stream, StreamExt};
use core::pin::Pin;
use crossbeam::queue::ArrayQueue;
use crossbeam::atomic::AtomicCell;
use core::task::{Waker, Context, Poll};
use std::sync::{Arc, atomic::*};
use crate::receiver::SendError;
struct ChannelInner<T> {
queue: ArrayQueue<T>,
send_waker: AtomicCell<Option<Box<Waker>>>,
recv_waker: AtomicCell<Option<Box<Waker>>>,
closed: AtomicBool,
}
pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
let inner = Arc::new(ChannelInner {
queue: ArrayQueue::new(buffer),
send_waker: AtomicCell::new(None),
recv_waker: AtomicCell::new(None),
closed: AtomicBool::new(false),
});
(
Sender {
inner: inner.clone(),
},
Receiver {
inner,
}
)
}
#[derive(Clone)]
pub struct Sender<T> {
inner: Arc<ChannelInner<T>>
}
impl <T> Sender<T> {
pub fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<()> {
if self.inner.closed.load(Ordering::SeqCst) {
return Poll::Ready(());
}
if self.inner.queue.is_full() {
self.inner.send_waker.store(Some(Box::new(cx.waker().clone())));
}
let mut counter = 4;
loop {
if self.inner.queue.is_full() {
if counter > 0 {
counter -= 1;
continue;
} else {
break Poll::Pending;
}
} else {
break Poll::Ready(());
}
}
}
pub fn try_send(&self, mut item: T) -> Result<(), SendError<T>> {
if self.inner.closed.load(Ordering::SeqCst) {
return Err(SendError::Closed(item));
}
let mut counter = 0;
loop {
match self.inner.queue.push(item) {
Ok(_) => {
if let Some(waker) = self.inner.recv_waker.take() {
waker.wake();
}
break Ok(());
}
Err(inner) => {
if counter >= 4 {
break Err(SendError::Full(inner));
} else {
item = inner;
counter += 1;
}
}
}
}
}
pub fn close(&self) {
self.inner.closed.store(true, Ordering::SeqCst);
if let Some(waker) = self.inner.recv_waker.take() {
waker.wake();
}
}
}
pub struct Receiver<T> {
inner: Arc<ChannelInner<T>>
}
impl <T> Stream for Receiver<T> {
type Item = T;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
let mut counter = 0;
loop {
match this.inner.queue.pop() {
Some(inner) => {
if let Some(waker) = this.inner.send_waker.take() {
waker.wake();
}
break Poll::Ready(Some(inner));
},
None => {
if this.inner.closed.load(Ordering::SeqCst) {
break Poll::Ready(None);
} else {
if counter == 0 {
this.inner.recv_waker.store(Some(Box::new(cx.waker().clone())));
}
if counter >= 8 {
break Poll::Pending;
} else {
counter += 1;
}
}
}
}
}
}
}

View File

@ -1,105 +0,0 @@
use crate::receiver::SendError;
use core::pin::Pin;
use core::task::{Context, Poll};
use crossbeam::queue::SegQueue;
use futures::{channel::mpsc, Stream};
use std::{
sync::{
atomic::{AtomicUsize, Ordering},
Arc,
},
task::Waker,
};
pub struct State {
buffer: usize,
counter: AtomicUsize,
send_wakers: SegQueue<Waker>,
}
pub fn channel<T>(buffer: usize) -> (Sender<T>, Receiver<T>) {
let state = Arc::new(State {
buffer,
counter: AtomicUsize::new(0),
send_wakers: SegQueue::new(),
});
let (tx, rx) = mpsc::unbounded();
(
Sender {
inner: tx,
state: state.clone(),
},
Receiver { inner: rx, state },
)
}
pub struct Sender<T> {
inner: mpsc::UnboundedSender<T>,
state: Arc<State>,
}
impl<T> Sender<T> {
pub fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<()> {
if self.state.counter.load(Ordering::SeqCst) >= self.state.buffer {
self.state.send_wakers.push(cx.waker().clone());
return Poll::Pending;
}
Poll::Ready(())
}
pub fn try_send(&self, item: T) -> Result<(), SendError<T>> {
if self.state.counter.load(Ordering::Relaxed) >= self.state.buffer {
return Err(SendError::Full(item));
}
self.state.counter.fetch_add(1, Ordering::SeqCst);
match self.inner.unbounded_send(item) {
Ok(_) => Ok(()),
Err(err) if err.is_full() => Err(SendError::Full(err.into_inner())),
Err(err) => Err(SendError::Closed(err.into_inner())),
}
}
#[inline]
pub fn flush(&self) {}
#[inline]
pub fn close(&self) {
self.inner.close_channel();
}
}
pub struct Receiver<T> {
inner: mpsc::UnboundedReceiver<T>,
state: Arc<State>,
}
impl<T> Stream for Receiver<T> {
type Item = T;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
let this = self.get_mut();
match Pin::new(&mut this.inner).poll_next(cx) {
Poll::Ready(inner) => {
let val = this.state.counter.fetch_sub(1, Ordering::SeqCst);
if val <= this.state.buffer {
if let Some(waker) = this.state.send_wakers.pop() {
waker.wake();
}
}
Poll::Ready(inner)
}
Poll::Pending => {
while let Some(waker) = this.state.send_wakers.pop() {
waker.wake();
}
Poll::Pending
},
}
}
}

View File

@ -0,0 +1,147 @@
use std::pin::Pin;
use futures::{pin_mut, Future, Stream};
use tokio::sync::{mpsc, Mutex};
use crate::builder::ReceiverSubscriberBuilder;
use crate::error::{Error, StdSyncSendError};
use crate::handler::AsyncProducer as AsyncProducerHandler;
use crate::receiver::UntypedPollerCallback;
use crate::receivers::Request;
use crate::{
Action, Bus, Event, Message, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
Untyped,
};
#[derive(Default)]
pub struct AsyncProducerConfig {}
async fn producer_poller<T, M>(
mut rx: mpsc::UnboundedReceiver<Request<M>>,
bus: Bus,
ut: Untyped,
stx: mpsc::UnboundedSender<Event<T::Response, T::Error>>,
) where
T: AsyncProducerHandler<M> + 'static,
T::Error: StdSyncSendError,
T::Item: Message,
T::Response: Message,
M: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
let stream = Option<Pin<Box<dyn Stream<Item = Result<Self::Item, Self::Error>> + Send + '_>>, Self::Error>;
while let Some(msg) = rx.recv().await {
match msg {
Request::Request(mid, msg, _req) => {
let lock = ut.lock().await;
let stream = lock.producer(msg, &bus).await.unwrap();
pin_mut!(stream);
stx.send(Event::BatchComplete(M::type_tag_(), 1)).unwrap();
}
Request::Action(Action::Init(..)) => {
stx.send(Event::Ready).unwrap();
}
Request::Action(Action::Close) => {
rx.close();
}
Request::Action(Action::Flush) => {
stx.send(Event::Flushed).unwrap();
}
Request::Action(Action::Sync) => {}
_ => unimplemented!(),
}
}
}
#[derive(Debug)]
pub struct AsyncProducer<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
tx: mpsc::UnboundedSender<Request<M>>,
srx: parking_lot::Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
}
impl<T, M> ReceiverSubscriberBuilder<T, M, T::Response, T::Error>
for AsyncProducer<M, T::Response, T::Error>
where
T: AsyncProducerHandler<M> + 'static,
T::Item: Message,
T::Response: Message,
T::Error: StdSyncSendError,
M: Message,
{
type Config = AsyncProducerConfig;
fn build(_cfg: Self::Config) -> (Self, UntypedPollerCallback) {
let (stx, srx) = mpsc::unbounded_channel();
let (tx, rx) = mpsc::unbounded_channel();
let poller = Box::new(move |ut| {
Box::new(move |bus| {
Box::pin(producer_poller::<T, M>(rx, bus, ut, stx))
as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
});
(
AsyncProducer::<M, T::Response, T::Error> {
tx,
srx: parking_lot::Mutex::new(Some(srx)),
},
poller,
)
}
}
impl<M, R, E> SendUntypedReceiver for AsyncProducer<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
fn send(&self, m: Action, _bus: &Bus) -> Result<(), Error<Action>> {
match self.tx.send(Request::Action(m)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
_ => unimplemented!(),
}
}
}
impl<M, R, E> SendTypedReceiver<M> for AsyncProducer<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
}
}
}
impl<M, R, E> ReciveTypedReceiver<R, E> for AsyncProducer<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn event_stream(&self, _: Bus) -> Self::Stream {
let mut rx = self.srx.lock().take().unwrap();
Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
}
}

View File

@ -1,211 +1,121 @@
use std::{ use std::{pin::Pin, sync::Arc};
any::TypeId,
marker::PhantomData,
pin::Pin,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
task::{Context, Poll},
};
use crate::{receiver::ReceiverStats, receivers::mpsc}; use super::SynchronizedBatchedConfig;
use futures::{Future, StreamExt};
use tokio::sync::Mutex;
use super::{SynchronizeBatchedConfig, SynchronizeBatchedStats};
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, batch_synchronized_poller_macro,
msgs, builder::ReceiverSubscriberBuilder,
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, error::{Error, StdSyncSendError},
receiver::{
Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers::Request,
AsyncBatchSynchronizedHandler, Bus, Message, Untyped, AsyncBatchSynchronizedHandler, Bus, Message, Untyped,
}; };
pub struct SynchronizeBatchedAsyncSubscriber<T, M> use futures::{Future, Stream};
where use tokio::sync::{
T: AsyncBatchSynchronizedHandler<M> + 'static, mpsc::{self, UnboundedSender},
M: Message, Mutex,
{ };
cfg: SynchronizeBatchedConfig,
_m: PhantomData<(T, M)>, batch_synchronized_poller_macro! {
T,
AsyncBatchSynchronizedHandler,
|mids: Vec<_>, msgs, bus, ut: Arc<Mutex<T>>, stx: UnboundedSender<_>| {
tokio::spawn(async move {
let resp = ut.lock().await.handle(msgs, &bus).await;
crate::process_batch_result!(resp, mids, stx);
})
},
|bus, ut: Arc<Mutex<T>>| { async move { ut.lock().await.sync(&bus).await } }
} }
impl<T, M> ReceiverSubscriber<T> for SynchronizeBatchedAsyncSubscriber<T, M> pub struct SynchronizedBatchedAsync<M, R, E>
where where
T: AsyncBatchSynchronizedHandler<M> + 'static, M: Message,
R: Message,
E: StdSyncSendError,
{
tx: mpsc::UnboundedSender<Request<M>>,
srx: parking_lot::Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
}
impl<T, M, R> ReceiverSubscriberBuilder<T, M, R, T::Error>
for SynchronizedBatchedAsync<M, R, T::Error>
where
T: AsyncBatchSynchronizedHandler<M, Response = R> + 'static,
T::Error: StdSyncSendError + Clone,
R: Message,
M: Message, M: Message,
{ {
fn subscribe( type Config = SynchronizedBatchedConfig;
self,
) -> (
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let (tx, rx) = mpsc::channel(cfg.buffer_size);
let stats = Arc::new(SynchronizeBatchedStats {
buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _),
batch: AtomicU64::new(0),
batch_size: AtomicU64::new(cfg.batch_size as _),
});
let arc = Arc::new(SynchronizeBatchedAsync::<M> { fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback) {
tx, let (stx, srx) = mpsc::unbounded_channel();
stats: stats.clone(), let (tx, rx) = mpsc::unbounded_channel();
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(batch_synchronized_poller::<T, M, R>(rx, bus, ut, cfg, stx))
as Pin<Box<dyn Future<Output = ()> + Send>> as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller) (
SynchronizedBatchedAsync::<M, R, T::Error> {
tx,
srx: parking_lot::Mutex::new(Some(srx)),
},
poller,
)
} }
} }
async fn buffer_unordered_poller<T, M>( impl<M, R, E> SendUntypedReceiver for SynchronizedBatchedAsync<M, R, E>
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<SynchronizeBatchedStats>,
cfg: SynchronizeBatchedConfig,
) where
T: AsyncBatchSynchronizedHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
let rx = rx
.inspect(|_|{
stats.buffer.fetch_sub(1, Ordering::Relaxed);
stats.batch.fetch_add(1, Ordering::Relaxed);
});
let mut rx = if cfg.when_ready {
rx.ready_chunks(cfg.batch_size)
.left_stream()
} else {
rx.chunks(cfg.batch_size)
.right_stream()
};
while let Some(msgs) = rx.next().await {
stats.batch.fetch_sub(msgs.len() as _, Ordering::Relaxed);
let bus_clone = bus.clone();
let ut = ut.clone();
let res =
tokio::task::spawn(async move { ut.lock().await.handle(msgs, &bus_clone).await })
.await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn(async move { ut.lock().await.sync(&bus_clone).await }).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] SynchronizeBatchedAsync<{}>",
std::any::type_name::<M>()
);
}
pub struct SynchronizeBatchedAsync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<SynchronizeBatchedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for SynchronizeBatchedAsync<M>
where where
T: AsyncBatchSynchronizedHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
type Entry = SynchronizeBatchedAsyncSubscriber<T, M>; fn send(&self, m: Action, _bus: &Bus) -> Result<(), Error<Action>> {
type Config = SynchronizeBatchedConfig; match self.tx.send(Request::Action(m)) {
Ok(_) => Ok(()),
fn build(cfg: Self::Config) -> Self::Entry { Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
SynchronizeBatchedAsyncSubscriber { _ => unimplemented!(),
cfg,
_m: Default::default(),
} }
} }
} }
impl<M: Message> TypedReceiver<M> for SynchronizeBatchedAsync<M> { impl<M, R, E> SendTypedReceiver<M> for SynchronizedBatchedAsync<M, R, E>
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> { where
match self.tx.poll_ready(ctx) { M: Message,
Poll::Ready(_) => Poll::Ready(()), R: Message,
Poll::Pending => Poll::Pending, E: StdSyncSendError,
{
fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
} }
} _ => unimplemented!(),
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(())
}
Err(err) => Err(err),
} }
} }
} }
impl<M: Message> ReceiverTrait for SynchronizeBatchedAsync<M> { impl<M, R, E> ReciveTypedReceiver<R, E> for SynchronizedBatchedAsync<M, R, E>
fn typed(&self) -> AnyReceiver<'_> { where
AnyReceiver::new(self) M: Message,
} R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn type_id(&self) -> TypeId { fn event_stream(&self, _: Bus) -> Self::Stream {
TypeId::of::<Self>() let mut rx = self.srx.lock().take().unwrap();
}
fn close(&self) { Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
self.tx.close();
}
fn stats(&self) -> ReceiverStats {
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
(
"buffer_total".into(),
self.stats.buffer_total.load(Ordering::SeqCst),
),
("batch".into(), self.stats.batch.load(Ordering::SeqCst)),
(
"batch_size".into(),
self.stats.batch_size.load(Ordering::SeqCst),
),
],
}
}
fn sync(&self) {
self.tx.flush();
}
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
} }
} }

View File

@ -3,31 +3,104 @@ mod sync;
use std::sync::atomic::AtomicU64; use std::sync::atomic::AtomicU64;
pub use sync::{SynchronizeBatchedSync, SynchronizeBatchedSyncSubscriber}; pub use r#async::SynchronizedBatchedAsync;
use serde_derive::{Deserialize, Serialize};
pub use r#async::{SynchronizeBatchedAsync, SynchronizeBatchedAsyncSubscriber}; pub use sync::SynchronizedBatchedSync;
#[derive(Debug)] #[derive(Debug)]
pub struct SynchronizeBatchedStats { pub struct SynchronizedBatchedStats {
pub buffer: AtomicU64, pub buffer: AtomicU64,
pub buffer_total: AtomicU64, pub buffer_total: AtomicU64,
pub batch: AtomicU64, pub batch: AtomicU64,
pub batch_size: AtomicU64, pub batch_size: AtomicU64,
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct SynchronizeBatchedConfig { pub struct SynchronizedBatchedConfig {
pub buffer_size: usize, pub buffer_size: usize,
pub batch_size: usize, pub batch_size: usize,
pub when_ready: bool, pub when_ready: bool,
} }
impl Default for SynchronizeBatchedConfig { impl Default for SynchronizedBatchedConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
buffer_size: 4, buffer_size: 4,
batch_size: 16, batch_size: 8,
when_ready: false, when_ready: false,
} }
} }
} }
#[macro_export]
macro_rules! batch_synchronized_poller_macro {
($t: tt, $h: tt, $st1: expr, $st2: expr) => {
async fn batch_synchronized_poller<$t, M, R>(
mut rx: mpsc::UnboundedReceiver<Request<M>>,
bus: Bus,
ut: Untyped,
// stats: Arc<SynchronizedBatchedStats>,
cfg: SynchronizedBatchedConfig,
stx: mpsc::UnboundedSender<Event<R, $t::Error>>,
) where
$t: $h<M, Response = R> + 'static,
$t::Error: StdSyncSendError + Clone,
M: Message,
R: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
let mut buffer_mid = Vec::with_capacity(cfg.batch_size);
let mut buffer = Vec::with_capacity(cfg.batch_size);
while let Some(msg) = rx.recv().await {
let bus = bus.clone();
let ut = ut.clone();
let stx = stx.clone();
match msg {
Request::Request(mid, msg, req) => {
buffer_mid.push((mid, req));
buffer.push(msg);
if buffer_mid.len() >= cfg.batch_size {
let buffer_mid_clone = buffer_mid.drain(..).collect::<Vec<_>>();
let buffer_clone = buffer.drain(..).collect();
#[allow(clippy::redundant_closure_call)]
let _ = ($st1)(buffer_mid_clone, buffer_clone, bus, ut, stx);
}
}
Request::Action(Action::Init(..)) => {
stx.send(Event::Ready).unwrap();
}
Request::Action(Action::Close) => {
rx.close();
}
Request::Action(Action::Flush) => {
let stx_clone = stx.clone();
if !buffer_mid.is_empty() {
let buffer_mid_clone = buffer_mid.drain(..).collect::<Vec<_>>();
let buffer_clone = buffer.drain(..).collect();
#[allow(clippy::redundant_closure_call)]
let _ = ($st1)(buffer_mid_clone, buffer_clone, bus, ut, stx);
}
stx_clone.send(Event::Flushed).unwrap();
}
Request::Action(Action::Sync) => {
#[allow(clippy::redundant_closure_call)]
let resp = ($st2)(bus.clone(), ut.clone()).await;
stx.send(Event::Synchronized(resp.map_err(Error::Other)))
.unwrap();
}
_ => unimplemented!(),
}
}
}
};
}

View File

@ -1,213 +1,125 @@
use super::{SynchronizeBatchedConfig, SynchronizeBatchedStats}; use std::{pin::Pin, sync::Arc};
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, batch_synchronized_poller_macro,
msgs, builder::ReceiverSubscriberBuilder,
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, error::{Error, StdSyncSendError},
receiver::{
Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver,
UntypedPollerCallback,
},
receivers::Request,
BatchSynchronizedHandler, Bus, Message, Untyped, BatchSynchronizedHandler, Bus, Message, Untyped,
}; };
use crate::{receiver::ReceiverStats, receivers::mpsc};
use futures::{Future, StreamExt};
use std::{
any::TypeId,
marker::PhantomData,
pin::Pin,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
task::{Context, Poll},
};
use tokio::sync::Mutex;
pub struct SynchronizeBatchedSyncSubscriber<T, M> use super::SynchronizedBatchedConfig;
where use futures::{executor::block_on, Future, Stream};
T: BatchSynchronizedHandler<M> + 'static, use tokio::sync::{
M: Message, mpsc::{self, UnboundedSender},
{ Mutex,
cfg: SynchronizeBatchedConfig, };
_m: PhantomData<(M, T)>,
batch_synchronized_poller_macro! {
T,
BatchSynchronizedHandler,
|mids: Vec<_>, msgs, bus, ut: Arc<Mutex<T>>, stx: UnboundedSender<_>| {
tokio::task::spawn_blocking(move || {
let resp = block_on(ut.lock()).handle(msgs, &bus);
crate::process_batch_result!(resp, mids, stx);
})
},
|bus, ut: Arc<Mutex<T>>| async move {
tokio::task::spawn_blocking(move || block_on(ut.lock()).sync(&bus))
.await
.unwrap()
}
} }
impl<T, M> ReceiverSubscriber<T> for SynchronizeBatchedSyncSubscriber<T, M> pub struct SynchronizedBatchedSync<M, R, E>
where where
T: BatchSynchronizedHandler<M> + 'static, M: Message,
R: Message,
E: StdSyncSendError,
{
tx: mpsc::UnboundedSender<Request<M>>,
srx: parking_lot::Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
}
impl<T, M, R> ReceiverSubscriberBuilder<T, M, R, T::Error>
for SynchronizedBatchedSync<M, R, T::Error>
where
T: BatchSynchronizedHandler<M, Response = R> + 'static,
T::Error: StdSyncSendError,
R: Message,
M: Message, M: Message,
{ {
fn subscribe( type Config = SynchronizedBatchedConfig;
self,
) -> ( fn build(cfg: Self::Config) -> (Self, UntypedPollerCallback) {
Arc<dyn ReceiverTrait>, let (stx, srx) = mpsc::unbounded_channel();
Box< let (tx, rx) = mpsc::unbounded_channel();
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let (tx, rx) = mpsc::channel(cfg.buffer_size);
let stats = Arc::new(SynchronizeBatchedStats {
buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _),
batch: AtomicU64::new(0),
batch_size: AtomicU64::new(cfg.batch_size as _),
});
let arc = Arc::new(SynchronizeBatchedSync::<M> {
tx,
stats: stats.clone(),
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(batch_synchronized_poller::<T, M, R>(rx, bus, ut, cfg, stx))
as Pin<Box<dyn Future<Output = ()> + Send>> as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller) (
SynchronizedBatchedSync::<M, R, T::Error> {
tx,
srx: parking_lot::Mutex::new(Some(srx)),
},
poller,
)
} }
} }
async fn buffer_unordered_poller<T, M>( impl<M, R, E> SendUntypedReceiver for SynchronizedBatchedSync<M, R, E>
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<SynchronizeBatchedStats>,
cfg: SynchronizeBatchedConfig,
) where
T: BatchSynchronizedHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
let rx = rx
.inspect(|_|{
stats.buffer.fetch_sub(1, Ordering::Relaxed);
stats.batch.fetch_add(1, Ordering::Relaxed);
});
let mut rx = if cfg.when_ready {
rx.ready_chunks(cfg.batch_size)
.left_stream()
} else {
rx.chunks(cfg.batch_size)
.right_stream()
};
while let Some(msgs) = rx.next().await {
stats.batch.fetch_sub(msgs.len() as _, Ordering::Relaxed);
let bus_clone = bus.clone();
let ut = ut.clone();
let res = tokio::task::spawn_blocking(move || {
let mut uut = futures::executor::block_on(ut.lock());
uut.handle(msgs, &bus_clone)
}).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn_blocking(move || {
futures::executor::block_on(ut.lock()).sync(&bus_clone)
})
.await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] SynchronizeBatchedSync<{}>",
std::any::type_name::<M>()
);
}
pub struct SynchronizeBatchedSync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<SynchronizeBatchedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for SynchronizeBatchedSync<M>
where where
T: BatchSynchronizedHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
type Entry = SynchronizeBatchedSyncSubscriber<T, M>; fn send(&self, msg: Action, _bus: &Bus) -> Result<(), Error<Action>> {
type Config = SynchronizeBatchedConfig; match self.tx.send(Request::Action(msg)) {
Ok(_) => Ok(()),
fn build(cfg: Self::Config) -> Self::Entry { Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
SynchronizeBatchedSyncSubscriber { _ => unimplemented!(),
cfg,
_m: Default::default(),
} }
} }
} }
impl<M: Message> TypedReceiver<M> for SynchronizeBatchedSync<M> { impl<M, R, E> SendTypedReceiver<M> for SynchronizedBatchedSync<M, R, E>
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> { where
match self.tx.poll_ready(ctx) { M: Message,
Poll::Ready(_) => Poll::Ready(()), R: Message,
Poll::Pending => Poll::Pending, E: StdSyncSendError,
{
fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
} }
} _ => unimplemented!(),
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(())
}
Err(err) => Err(err),
} }
} }
} }
impl<M: Message> ReceiverTrait for SynchronizeBatchedSync<M> { impl<M, R, E> ReciveTypedReceiver<R, E> for SynchronizedBatchedSync<M, R, E>
fn typed(&self) -> AnyReceiver<'_> { where
AnyReceiver::new(self) M: Message,
} R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn type_id(&self) -> TypeId { fn event_stream(&self, _: Bus) -> Self::Stream {
TypeId::of::<Self>() let mut rx = self.srx.lock().take().unwrap();
}
fn stats(&self) -> ReceiverStats { Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
(
"buffer_total".into(),
self.stats.buffer_total.load(Ordering::SeqCst),
),
("batch".into(), self.stats.batch.load(Ordering::SeqCst)),
(
"batch_size".into(),
self.stats.batch_size.load(Ordering::SeqCst),
),
],
}
}
fn close(&self) {
self.tx.close();
}
fn sync(&self) {
self.tx.flush();
}
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> {
Poll::Ready(())
} }
} }

View File

@ -1,186 +1,121 @@
use std::{ use std::{pin::Pin, sync::Arc};
any::TypeId,
marker::PhantomData,
pin::Pin,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
task::{Context, Poll},
};
use crate::{receiver::ReceiverStats, receivers::mpsc}; use crate::{receiver::UntypedPollerCallback, synchronized_poller_macro};
use futures::{Future, StreamExt}; use futures::{Future, Stream};
use tokio::sync::Mutex;
use super::{SynchronizedConfig, SynchronizedStats}; use super::SynchronizedConfig;
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, builder::ReceiverSubscriberBuilder,
msgs, error::{Error, StdSyncSendError},
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, receiver::{Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver},
receivers::Request,
AsyncSynchronizedHandler, Bus, Message, Untyped, AsyncSynchronizedHandler, Bus, Message, Untyped,
}; };
use tokio::sync::{
mpsc::{self, UnboundedSender},
Mutex,
};
pub struct SynchronizedAsyncSubscriber<T, M> synchronized_poller_macro! {
where T,
T: AsyncSynchronizedHandler<M> + 'static, AsyncSynchronizedHandler,
M: Message, |mid, msg, bus, ut: Arc<Mutex<T>>, stx: UnboundedSender<_>| {
{ tokio::spawn(async move {
cfg: SynchronizedConfig, let resp = ut.lock().await.handle(msg, &bus).await;
_m: PhantomData<(T, M)>,
stx.send(Event::Response(mid, resp.map_err(Error::Other)))
.unwrap();
})
},
|bus, ut: Arc<Mutex<T>>| async move {
ut.lock().await.sync(&bus).await
}
} }
impl<T, M> ReceiverSubscriber<T> for SynchronizedAsyncSubscriber<T, M> pub struct SynchronizedAsync<M, R, E>
where where
T: AsyncSynchronizedHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
fn subscribe( tx: mpsc::UnboundedSender<Request<M>>,
self, srx: parking_lot::Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
) -> ( }
Arc<dyn ReceiverTrait>,
Box<
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>,
>,
) {
let cfg = self.cfg;
let (tx, rx) = mpsc::channel(cfg.buffer_size);
let stats = Arc::new(SynchronizedStats {
buffer: AtomicU64::new(0),
buffer_total: AtomicU64::new(cfg.buffer_size as _),
});
let arc = Arc::new(SynchronizedAsync::<M> { impl<T, M, R, E> ReceiverSubscriberBuilder<T, M, R, E> for SynchronizedAsync<M, R, E>
tx, where
stats: stats.clone(), T: AsyncSynchronizedHandler<M, Response = R, Error = E> + 'static,
}); R: Message,
M: Message,
E: StdSyncSendError,
{
type Config = SynchronizedConfig;
fn build(_cfg: Self::Config) -> (Self, UntypedPollerCallback) {
let (stx, srx) = mpsc::unbounded_channel();
let (tx, rx) = mpsc::unbounded_channel();
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(synchronized_poller::<T, M, R>(rx, bus, ut, stx))
as Pin<Box<dyn Future<Output = ()> + Send>> as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller)
}
}
async fn buffer_unordered_poller<T, M>(
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<SynchronizedStats>,
_cfg: SynchronizedConfig,
) where
T: AsyncSynchronizedHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
let mut x = rx.then(|msg| {
let bus = bus.clone();
let ut = ut.clone();
tokio::task::spawn(async move { ut.lock().await.handle(msg, &bus).await })
});
while let Some(err) = x.next().await {
stats.buffer.fetch_sub(1, Ordering::Relaxed);
match err {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn(async move { ut.lock().await.sync(&bus_clone).await }).await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!("[EXIT] SynchronizedAsync<{}>", std::any::type_name::<M>());
}
pub struct SynchronizedAsync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<SynchronizedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for SynchronizedAsync<M>
where
T: AsyncSynchronizedHandler<M> + 'static,
M: Message,
{
type Entry = SynchronizedAsyncSubscriber<T, M>;
type Config = SynchronizedConfig;
fn build(cfg: Self::Config) -> Self::Entry {
SynchronizedAsyncSubscriber {
cfg,
_m: Default::default(),
}
}
}
impl<M: Message> TypedReceiver<M> for SynchronizedAsync<M> {
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> {
match self.tx.poll_ready(ctx) {
Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => Poll::Pending,
}
}
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(())
}
Err(err) => Err(err),
}
}
}
impl<M: Message> ReceiverTrait for SynchronizedAsync<M> {
fn typed(&self) -> AnyReceiver<'_> {
AnyReceiver::new(self)
}
fn type_id(&self) -> TypeId {
TypeId::of::<SynchronizedAsync<M>>()
}
fn stats(&self) -> ReceiverStats {
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
( (
"buffer_total".into(), SynchronizedAsync::<M, R, E> {
self.stats.buffer_total.load(Ordering::SeqCst), tx,
), srx: parking_lot::Mutex::new(Some(srx)),
], },
} poller,
} )
}
fn close(&self) { }
self.tx.close();
} impl<M, R, E> SendUntypedReceiver for SynchronizedAsync<M, R, E>
where
fn sync(&self) { M: Message,
self.tx.flush(); R: Message,
} E: StdSyncSendError,
{
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> { fn send(&self, m: Action, _bus: &Bus) -> Result<(), Error<Action>> {
Poll::Ready(()) match self.tx.send(Request::Action(m)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
_ => unimplemented!(),
}
}
}
impl<M, R, E> SendTypedReceiver<M> for SynchronizedAsync<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
}
}
}
impl<M, R, E> ReciveTypedReceiver<R, E> for SynchronizedAsync<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn event_stream(&self, _: Bus) -> Self::Stream {
let mut rx = self.srx.lock().take().unwrap();
Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
} }
} }

View File

@ -3,9 +3,9 @@ mod sync;
use std::sync::atomic::AtomicU64; use std::sync::atomic::AtomicU64;
pub use sync::{SynchronizedSync, SynchronizedSyncSubscriber}; pub use r#async::SynchronizedAsync;
use serde_derive::{Deserialize, Serialize};
pub use r#async::{SynchronizedAsync, SynchronizedAsyncSubscriber}; pub use sync::SynchronizedSync;
#[derive(Debug)] #[derive(Debug)]
pub struct SynchronizedStats { pub struct SynchronizedStats {
@ -13,7 +13,7 @@ pub struct SynchronizedStats {
pub buffer_total: AtomicU64, pub buffer_total: AtomicU64,
} }
#[derive(Copy, Clone, Debug)] #[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SynchronizedConfig { pub struct SynchronizedConfig {
pub buffer_size: usize, pub buffer_size: usize,
} }
@ -23,3 +23,51 @@ impl Default for SynchronizedConfig {
Self { buffer_size: 1 } Self { buffer_size: 1 }
} }
} }
#[macro_export]
macro_rules! synchronized_poller_macro {
($t: tt, $h: tt, $st1: expr, $st2: expr) => {
async fn synchronized_poller<$t, M, R>(
mut rx: mpsc::UnboundedReceiver<Request<M>>,
bus: Bus,
ut: Untyped,
stx: mpsc::UnboundedSender<Event<R, $t::Error>>,
) where
$t: $h<M, Response = R> + 'static,
$t::Error: StdSyncSendError,
M: Message,
R: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
while let Some(msg) = rx.recv().await {
match msg {
Request::Request(mid, msg, _req) =>
{
#[allow(clippy::redundant_closure_call)]
($st1)(mid, msg, bus.clone(), ut.clone(), stx.clone())
.await
.unwrap()
}
Request::Action(Action::Init(..)) => {
stx.send(Event::Ready).unwrap();
}
Request::Action(Action::Close) => {
rx.close();
}
Request::Action(Action::Flush) => {
stx.send(Event::Flushed).unwrap();
}
Request::Action(Action::Sync) => {
#[allow(clippy::redundant_closure_call)]
let resp = ($st2)(bus.clone(), ut.clone()).await;
stx.send(Event::Synchronized(resp.map_err(Error::Other)))
.unwrap();
}
_ => unimplemented!(),
}
}
}
};
}

View File

@ -1,190 +1,122 @@
use super::{SynchronizedConfig, SynchronizedStats}; use std::{pin::Pin, sync::Arc};
use crate::{receiver::ReceiverStats, receivers::mpsc};
use futures::{executor::block_on, Future, StreamExt};
use std::{
any::TypeId,
marker::PhantomData,
pin::Pin,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
task::{Context, Poll},
};
use tokio::sync::Mutex;
use crate::{receiver::UntypedPollerCallback, synchronized_poller_macro};
use futures::{executor::block_on, Future, Stream};
use super::SynchronizedConfig;
use crate::{ use crate::{
builder::{ReceiverSubscriber, ReceiverSubscriberBuilder}, builder::ReceiverSubscriberBuilder,
msgs, error::{Error, StdSyncSendError},
receiver::{AnyReceiver, ReceiverTrait, SendError, TypedReceiver}, receiver::{Action, Event, ReciveTypedReceiver, SendTypedReceiver, SendUntypedReceiver},
receivers::Request,
Bus, Message, SynchronizedHandler, Untyped, Bus, Message, SynchronizedHandler, Untyped,
}; };
use tokio::sync::{
mpsc::{self, UnboundedSender},
Mutex,
};
pub struct SynchronizedSyncSubscriber<T, M> synchronized_poller_macro! {
where T,
T: SynchronizedHandler<M> + 'static, SynchronizedHandler,
M: Message, |mid, msg, bus, ut: Arc<Mutex<T>>, stx: UnboundedSender<_>| {
{ tokio::task::spawn_blocking(move || {
cfg: SynchronizedConfig, let resp = block_on(ut.lock()).handle(msg, &bus);
_m: PhantomData<(M, T)>,
stx.send(Event::Response(mid, resp.map_err(Error::Other)))
.unwrap();
})
},
|bus, ut: Arc<Mutex<T>>| async move {
tokio::task::spawn_blocking(move || block_on(ut.lock()).sync(&bus))
.await
.unwrap()
}
} }
impl<T, M> ReceiverSubscriber<T> for SynchronizedSyncSubscriber<T, M> pub struct SynchronizedSync<M, R, E>
where where
T: SynchronizedHandler<M> + 'static,
M: Message, M: Message,
R: Message,
E: StdSyncSendError,
{ {
fn subscribe( tx: mpsc::UnboundedSender<Request<M>>,
self, srx: parking_lot::Mutex<Option<mpsc::UnboundedReceiver<Event<R, E>>>>,
) -> ( }
Arc<dyn ReceiverTrait>,
Box< impl<T, M, R, E> ReceiverSubscriberBuilder<T, M, R, E> for SynchronizedSync<M, R, E>
dyn FnOnce(Untyped) -> Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>, where
>, T: SynchronizedHandler<M, Response = R, Error = E> + 'static,
) { R: Message,
let cfg = self.cfg; M: Message,
let (tx, rx) = mpsc::channel(cfg.buffer_size); E: StdSyncSendError,
let stats = Arc::new(SynchronizedStats { {
buffer: AtomicU64::new(0), type Config = SynchronizedConfig;
buffer_total: AtomicU64::new(cfg.buffer_size as _),
}); fn build(_cfg: Self::Config) -> (Self, UntypedPollerCallback) {
let (stx, srx) = mpsc::unbounded_channel();
let (tx, rx) = mpsc::unbounded_channel();
let arc = Arc::new(SynchronizedSync::<M> {
tx,
stats: stats.clone(),
});
let poller = Box::new(move |ut| { let poller = Box::new(move |ut| {
Box::new(move |bus| { Box::new(move |bus| {
Box::pin(buffer_unordered_poller::<T, M>(rx, bus, ut, stats, cfg)) Box::pin(synchronized_poller::<T, M, R>(rx, bus, ut, stx))
as Pin<Box<dyn Future<Output = ()> + Send>> as Pin<Box<dyn Future<Output = ()> + Send>>
}) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>> }) as Box<dyn FnOnce(Bus) -> Pin<Box<dyn Future<Output = ()> + Send>>>
}); });
(arc, poller)
}
}
async fn buffer_unordered_poller<T, M>(
rx: mpsc::Receiver<M>,
bus: Bus,
ut: Untyped,
stats: Arc<SynchronizedStats>,
_cfg: SynchronizedConfig,
) where
T: SynchronizedHandler<M> + 'static,
M: Message,
{
let ut = ut.downcast::<Mutex<T>>().unwrap();
let mut x = rx.then(|msg| {
let ut = ut.clone();
let bus = bus.clone();
tokio::task::spawn_blocking(move || block_on(ut.lock()).handle(msg, &bus))
});
while let Some(err) = x.next().await {
stats.buffer.fetch_sub(1, Ordering::Relaxed);
match err {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
}
let ut = ut.clone();
let bus_clone = bus.clone();
let res = tokio::task::spawn_blocking(move || {
futures::executor::block_on(ut.lock()).sync(&bus_clone)
})
.await;
match res {
Ok(Err(err)) => {
let _ = bus.send(msgs::Error(Arc::new(err))).await;
}
_ => (),
}
println!(
"[EXIT] BufferUnorderedSync<{}>",
std::any::type_name::<M>()
);
}
pub struct SynchronizedSync<M: Message> {
tx: mpsc::Sender<M>,
stats: Arc<SynchronizedStats>,
}
impl<T, M> ReceiverSubscriberBuilder<M, T> for SynchronizedSync<M>
where
T: SynchronizedHandler<M> + 'static,
M: Message,
{
type Entry = SynchronizedSyncSubscriber<T, M>;
type Config = SynchronizedConfig;
fn build(cfg: Self::Config) -> Self::Entry {
SynchronizedSyncSubscriber {
cfg,
_m: Default::default(),
}
}
}
impl<M: Message> TypedReceiver<M> for SynchronizedSync<M> {
fn poll_ready(&self, ctx: &mut Context<'_>) -> Poll<()> {
match self.tx.poll_ready(ctx) {
Poll::Ready(_) => Poll::Ready(()),
Poll::Pending => Poll::Pending,
}
}
fn try_send(&self, m: M) -> Result<(), SendError<M>> {
match self.tx.try_send(m) {
Ok(_) => {
self.stats.buffer.fetch_add(1, Ordering::Relaxed);
Ok(())
}
Err(err) => Err(err),
}
}
}
impl<M: Message> ReceiverTrait for SynchronizedSync<M> {
fn typed(&self) -> AnyReceiver<'_> {
AnyReceiver::new(self)
}
fn type_id(&self) -> TypeId {
TypeId::of::<SynchronizedSync<M>>()
}
fn stats(&self) -> ReceiverStats {
ReceiverStats {
name: std::any::type_name::<M>().into(),
fields: vec![
("buffer".into(), self.stats.buffer.load(Ordering::SeqCst)),
( (
"buffer_total".into(), SynchronizedSync::<M, R, E> {
self.stats.buffer_total.load(Ordering::SeqCst), tx,
), srx: parking_lot::Mutex::new(Some(srx)),
], },
} poller,
} )
}
fn close(&self) { }
self.tx.close();
} impl<M, R, E> SendUntypedReceiver for SynchronizedSync<M, R, E>
where
fn sync(&self) { M: Message,
self.tx.flush(); R: Message,
} E: StdSyncSendError,
{
fn poll_synchronized(&self, _ctx: &mut Context<'_>) -> Poll<()> { fn send(&self, msg: Action, _bus: &Bus) -> Result<(), Error<Action>> {
Poll::Ready(()) match self.tx.send(Request::Action(msg)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Action(msg))) => Err(Error::send_closed(msg)),
_ => unimplemented!(),
}
}
}
impl<M, R, E> SendTypedReceiver<M> for SynchronizedSync<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
fn send(&self, mid: u64, m: M, req: bool, _bus: &Bus) -> Result<(), Error<M>> {
match self.tx.send(Request::Request(mid, m, req)) {
Ok(_) => Ok(()),
Err(mpsc::error::SendError(Request::Request(_, msg, _))) => {
Err(Error::send_closed(msg))
}
_ => unimplemented!(),
}
}
}
impl<M, R, E> ReciveTypedReceiver<R, E> for SynchronizedSync<M, R, E>
where
M: Message,
R: Message,
E: StdSyncSendError,
{
type Stream = Pin<Box<dyn Stream<Item = Event<R, E>> + Send>>;
fn event_stream(&self, _: Bus) -> Self::Stream {
let mut rx = self.srx.lock().take().unwrap();
Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
} }
} }

320
src/relay.rs Normal file
View File

@ -0,0 +1,320 @@
use crate::{
error::Error,
receiver::{
Action, AnyReceiver, AnyWrapperRef, BusPollerCallback, PermitDrop, ReceiverTrait,
SendUntypedReceiver, TypeTagAccept,
},
stats::Stats,
Bus, Event, Message, Permit, ReciveUntypedReceiver, TypeTag, TypeTagAcceptItem,
};
use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use dashmap::DashMap;
use futures::{pin_mut, StreamExt};
use std::sync::Arc;
use tokio::sync::{oneshot, Notify};
pub trait Relay: TypeTagAccept + SendUntypedReceiver + ReciveUntypedReceiver + 'static {}
impl<T: TypeTagAccept + SendUntypedReceiver + ReciveUntypedReceiver + 'static> Relay for T {}
struct SlabCfg;
impl sharded_slab::Config for SlabCfg {
const RESERVED_BITS: usize = 1;
}
type Slab<T> = sharded_slab::Slab<T, SlabCfg>;
pub(crate) struct RelayContext {
receivers: DashMap<TypeTag, Arc<RelayReceiverContext>>,
need_flush: AtomicBool,
ready_flag: AtomicBool,
idling_flag: AtomicBool,
init_sent: AtomicBool,
flushed: Notify,
synchronized: Notify,
closed: Notify,
ready: Notify,
idle: Notify,
}
pub struct RelayReceiverContext {
limit: u64,
processing: AtomicU64,
response: Arc<Notify>,
}
impl RelayReceiverContext {
fn new(limit: u64) -> Self {
Self {
limit,
processing: Default::default(),
response: Arc::new(Notify::new()),
}
}
}
impl PermitDrop for RelayReceiverContext {
fn permit_drop(&self) {
self.processing.fetch_sub(1, Ordering::SeqCst);
}
}
pub(crate) struct RelayWrapper<S>
where
S: 'static,
{
id: u64,
inner: S,
context: Arc<RelayContext>,
waiters: Slab<oneshot::Sender<Result<Box<dyn Message>, Error>>>,
}
impl<S> RelayWrapper<S> {
pub fn new(id: u64, inner: S) -> Self {
Self {
id,
inner,
context: Arc::new(RelayContext {
receivers: DashMap::new(),
need_flush: AtomicBool::new(false),
ready_flag: AtomicBool::new(false),
idling_flag: AtomicBool::new(true),
init_sent: AtomicBool::new(false),
flushed: Notify::new(),
synchronized: Notify::new(),
closed: Notify::new(),
ready: Notify::new(),
idle: Notify::new(),
}),
waiters: sharded_slab::Slab::new_with_config::<SlabCfg>(),
}
}
}
impl<S> TypeTagAccept for RelayWrapper<S>
where
S: Relay + Send + Sync + 'static,
{
fn iter_types(&self) -> Box<dyn Iterator<Item = TypeTagAcceptItem> + '_> {
self.inner.iter_types()
}
fn accept_msg(&self, msg: &TypeTag) -> bool {
self.inner.accept_msg(msg)
}
fn accept_req(&self, req: &TypeTag, resp: Option<&TypeTag>, err: Option<&TypeTag>) -> bool {
self.inner.accept_req(req, resp, err)
}
}
impl<S> ReceiverTrait for RelayWrapper<S>
where
S: Relay + Send + Sync + 'static,
{
fn name(&self) -> &str {
std::any::type_name::<Self>()
}
fn typed(&self) -> Option<AnyReceiver<'_>> {
None
}
fn wrapper(&self) -> Option<AnyWrapperRef<'_>> {
None
}
fn id(&self) -> u64 {
self.id
}
fn send_boxed(
&self,
mid: u64,
boxed_msg: Box<dyn Message>,
req: bool,
bus: &Bus,
) -> Result<(), Error<Box<dyn Message>>> {
self.inner.send_msg(mid, boxed_msg, req, bus)
}
fn add_response_listener(
&self,
listener: oneshot::Sender<Result<Box<dyn Message>, Error>>,
) -> Result<u64, Error> {
Ok(self
.waiters
.insert(listener)
.ok_or(Error::AddListenerError)? as _)
}
fn stats(&self) -> Stats {
unimplemented!()
}
fn send_action(&self, bus: &Bus, action: Action) -> Result<(), Error<Action>> {
SendUntypedReceiver::send(&self.inner, action, bus)
}
fn close_notify(&self) -> &Notify {
&self.context.closed
}
fn sync_notify(&self) -> &Notify {
&self.context.synchronized
}
fn flush_notify(&self) -> &Notify {
&self.context.flushed
}
fn ready_notify(&self) -> &Notify {
&self.context.ready
}
fn idle_notify(&self) -> &Notify {
&self.context.idle
}
fn is_init_sent(&self) -> bool {
self.context.init_sent.load(Ordering::SeqCst)
}
fn is_ready(&self) -> bool {
self.context.ready_flag.load(Ordering::SeqCst)
}
fn is_idling(&self) -> bool {
self.context.idling_flag.load(Ordering::SeqCst)
}
fn need_flush(&self) -> bool {
self.context.need_flush.load(Ordering::SeqCst)
}
fn set_need_flush(&self) {
self.context.need_flush.store(true, Ordering::SeqCst);
}
fn try_reserve(&self, tt: &TypeTag) -> Option<Permit> {
if !self.context.receivers.contains_key(tt) {
self.context
.receivers
.insert(tt.clone(), Arc::new(RelayReceiverContext::new(16)));
}
loop {
let context = self.context.receivers.get(tt).unwrap();
let count = context.processing.load(Ordering::Relaxed);
if count < context.limit {
let res = context.processing.compare_exchange(
count,
count + 1,
Ordering::SeqCst,
Ordering::SeqCst,
);
if res.is_ok() {
break Some(Permit {
fuse: false,
inner: context.clone(),
});
}
// continue
} else {
break None;
}
}
}
fn reserve_notify(&self, tt: &TypeTag) -> Arc<Notify> {
if !self.context.receivers.contains_key(tt) {
self.context
.receivers
.insert(tt.clone(), Arc::new(RelayReceiverContext::new(16)));
}
self.context.receivers.get(tt).unwrap().response.clone()
}
fn increment_processing(&self, tt: &TypeTag) {
self.context
.receivers
.get(tt)
.map(|r| r.processing.fetch_add(1, Ordering::SeqCst));
}
fn start_polling(self: Arc<Self>) -> BusPollerCallback {
Box::new(move |bus| {
Box::pin(async move {
let this = self.clone();
let events = this.inner.event_stream(bus);
pin_mut!(events);
loop {
let event = if let Some(event) = events.next().await {
event
} else {
self.context.closed.notify_waiters();
break;
};
match event {
Event::Error(err) => error!("Batch Error: {}", err),
Event::Pause => self.context.ready_flag.store(false, Ordering::SeqCst),
Event::Ready => {
self.context.ready.notify_waiters();
self.context.ready_flag.store(true, Ordering::SeqCst)
}
Event::InitFailed(err) => {
error!("Relay init failed: {}", err);
self.context.ready.notify_waiters();
self.context.ready_flag.store(false, Ordering::SeqCst);
}
Event::Exited => {
self.context.closed.notify_waiters();
break;
}
Event::Flushed => {
self.context.need_flush.store(false, Ordering::SeqCst);
self.context.flushed.notify_one()
}
Event::Synchronized(_res) => self.context.synchronized.notify_waiters(),
Event::Response(mid, resp) => {
let tt = if let Ok(bm) = &resp {
Some(bm.type_tag())
} else {
None
};
if let Some(chan) = self.waiters.take(mid as _) {
if let Err(err) = chan.send(resp) {
error!("Response error for mid({}): {:?}", mid, err);
}
} else {
warn!("No waiters for mid({})", mid);
};
if let Some(tt) = tt {
if let Some(ctx) = self.context.receivers.get(&tt) {
ctx.processing.fetch_sub(1, Ordering::SeqCst);
ctx.response.notify_one();
}
}
}
Event::BatchComplete(tt, n) => {
if let Some(ctx) = self.context.receivers.get(&tt) {
ctx.processing.fetch_sub(n, Ordering::SeqCst);
for _ in 0..n {
ctx.response.notify_one();
}
}
}
_ => unimplemented!(),
}
}
})
})
}
}

21
src/stats.rs Normal file
View File

@ -0,0 +1,21 @@
use std::borrow::Cow;
#[derive(Default, Debug, Clone)]
pub struct Stats {
pub msg_type_tag: Cow<'static, str>,
pub resp_type_tag: Option<Cow<'static, str>>,
pub err_type_tag: Option<Cow<'static, str>>,
pub has_queue: bool,
pub queue_capacity: i64,
pub queue_size: i64,
pub has_parallel: bool,
pub parallel_capacity: i64,
pub parallel_size: i64,
pub has_batch: bool,
pub batch_capacity: i64,
pub batch_size: i64,
}

84
src/type_tag.rs Normal file
View File

@ -0,0 +1,84 @@
use parking_lot::RwLock;
use std::collections::HashMap;
use crate::envelop::IntoSharedMessage;
use crate::error::Error;
use crate::{Message, SharedMessage, TypeTag};
static TYPE_REGISTRY: TypeRegistry = TypeRegistry::new();
type MessageDeserializerCallback = Box<
dyn Fn(&mut dyn erased_serde::Deserializer<'_>) -> Result<Box<dyn SharedMessage>, Error>
+ Send
+ Sync,
>;
pub struct MessageTypeDescriptor {
de: MessageDeserializerCallback,
}
impl MessageTypeDescriptor {
#[inline]
pub fn deserialize_boxed(
&self,
de: &mut dyn erased_serde::Deserializer<'_>,
) -> Result<Box<dyn SharedMessage>, Error> {
(self.de)(de)
}
}
#[derive(Default)]
pub struct TypeRegistry {
message_types: RwLock<Option<HashMap<TypeTag, MessageTypeDescriptor>>>,
}
impl TypeRegistry {
pub const fn new() -> Self {
Self {
message_types: parking_lot::const_rwlock(None),
}
}
pub fn deserialize(
&self,
tt: TypeTag,
de: &mut dyn erased_serde::Deserializer<'_>,
) -> Result<Box<dyn SharedMessage>, Error<Box<dyn Message>>> {
let guard = self.message_types.read();
let md = guard
.as_ref()
.ok_or_else(|| Error::TypeTagNotRegistered(tt.clone()))?
.get(&tt)
.ok_or(Error::TypeTagNotRegistered(tt))?;
md.deserialize_boxed(de)
.map_err(|err| err.specify::<Box<dyn Message>>())
}
pub fn register<M: Message + serde::Serialize + serde::de::DeserializeOwned>(&self) {
println!("insert {}", M::type_tag_());
self.message_types
.write()
.get_or_insert_with(HashMap::new)
.insert(
M::type_tag_(),
MessageTypeDescriptor {
de: Box::new(move |de| Ok(M::deserialize(de)?.into_shared())),
},
);
}
}
#[inline]
pub fn deserialize_shared_message(
tt: TypeTag,
de: &mut dyn erased_serde::Deserializer<'_>,
) -> Result<Box<dyn SharedMessage>, Error<Box<dyn Message>>> {
TYPE_REGISTRY.deserialize(tt, de)
}
#[inline]
pub fn register_shared_message<M: Message + serde::Serialize + serde::de::DeserializeOwned>() {
TYPE_REGISTRY.register::<M>();
}

View File

@ -1,33 +0,0 @@
use core::cmp::{Ord, Ordering};
use core::ops::Range;
pub fn binary_search_range_by_key<'a, T, B, F>(data: &'a [T], item: &B, mut f: F) -> Range<usize>
where
F: FnMut(&'a T) -> B,
B: Ord,
{
if let Ok(index) = data.binary_search_by_key(item, &mut f) {
let mut begin = index;
let mut end = index + 1;
for i in (0..index).rev() {
if f(unsafe { data.get_unchecked(i) }).cmp(item) != Ordering::Equal {
break;
}
begin = i;
}
for i in end..data.len() {
end = i;
if f(unsafe { data.get_unchecked(i) }).cmp(item) != Ordering::Equal {
break;
}
}
begin..end
} else {
data.len()..data.len()
}
}

View File

@ -0,0 +1,58 @@
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error, receivers, AsyncHandler, Bus, Message,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
struct MsgF32(pub f32);
struct TmpReceiver;
#[async_trait]
impl AsyncHandler<MsgF32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgF32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
std::thread::sleep(std::time::Duration::from_millis(100));
Ok(())
}
}
#[tokio::test]
async fn test_backpressure() {
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe_async::<MsgF32>(
1,
receivers::BufferUnorderedConfig {
buffer_size: 1,
max_parallel: 1,
},
)
.done()
.build();
b.send(MsgF32(32f32)).await.unwrap();
b.send(MsgF32(32f32)).await.unwrap();
assert!(b.try_send(MsgF32(32f32)).is_err());
b.flush_all().await;
b.close().await;
poller.await;
}

115
tests/test_batch.rs Normal file
View File

@ -0,0 +1,115 @@
use std::sync::Arc;
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error,
receivers::BufferUnorderedBatchedConfig,
AsyncBatchHandler, Bus, Message,
};
use parking_lot::Mutex;
use thiserror::Error;
#[derive(Debug, Error, Clone, MbError)]
enum Error {
#[error("Error({0})")]
Error(Arc<anyhow::Error>),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(Arc::new(err.into()))
}
}
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI32(i32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI16(i16);
struct TmpReceiver {
batches: Arc<Mutex<Vec<Vec<i32>>>>,
}
#[async_trait]
impl AsyncBatchHandler<MsgI32> for TmpReceiver {
type Error = Error;
type Response = ();
type InBatch = Vec<MsgI32>;
type OutBatch = Vec<()>;
async fn handle(
&self,
msg: Vec<MsgI32>,
_bus: &Bus,
) -> Result<Vec<Self::Response>, Self::Error> {
self.batches
.lock()
.push(msg.into_iter().map(|x| x.0).collect());
Ok(vec![])
}
}
#[tokio::test]
async fn test_batch() {
let batches = Arc::new(Mutex::new(Vec::new()));
let (b, poller) = Bus::build()
.register(TmpReceiver {
batches: batches.clone(),
})
.subscribe_batch_async::<MsgI32>(
16,
BufferUnorderedBatchedConfig {
batch_size: 8,
..Default::default()
},
)
.done()
.build();
for i in 1..100i32 {
b.send(MsgI32(i)).await.unwrap();
}
let mut re = Vec::new();
let mut counter = 1i32;
for _ in 1..100i32 {
let mut v = Vec::new();
for _ in 0..8 {
if counter >= 100 {
break;
}
v.push(counter);
counter += 1;
}
re.push(v);
if counter >= 100 {
break;
}
}
println!("flush");
b.flush_all().await;
let mut lock = batches.lock();
lock.sort_by(|a, b| a[0].cmp(&b[0]));
assert_eq!(lock.as_slice(), re.as_slice());
println!("close");
b.close().await;
println!("closed");
poller.await;
println!("[done]");
}

133
tests/test_concurrency.rs Normal file
View File

@ -0,0 +1,133 @@
use std::{sync::atomic::AtomicU32, time::Duration};
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error,
receivers::BufferUnorderedConfig,
AsyncHandler, Bus, Message, Module,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
#[error("MyError")]
MyError,
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
struct Req(pub u32);
#[derive(Debug, Clone, Message)]
struct Resp(pub u32);
#[derive(Debug, Clone, Message)]
struct GetCount;
#[derive(Debug, Clone, Message)]
struct CountResult(pub u32);
struct TmpReceiver {
counter: AtomicU32,
}
#[async_trait]
impl AsyncHandler<Req> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: Req, bus: &Bus) -> Result<Self::Response, Self::Error> {
tokio::time::sleep(Duration::from_millis((msg.0 % 20) as _)).await;
if msg.0 % 128 == 0 {
return Err(Error::MyError);
} else {
bus.send(Resp(msg.0)).await?;
}
Ok(())
}
}
#[async_trait]
impl AsyncHandler<Resp> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: Resp, _bus: &Bus) -> Result<Self::Response, Self::Error> {
self.counter
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
Ok(())
}
}
#[async_trait]
impl AsyncHandler<GetCount> for TmpReceiver {
type Error = Error;
type Response = CountResult;
async fn handle(&self, _: GetCount, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(CountResult(
self.counter.load(std::sync::atomic::Ordering::SeqCst),
))
}
}
fn module() -> Module {
Module::new()
.register(TmpReceiver {
counter: AtomicU32::new(0),
})
.subscribe_async::<Req>(
1024,
BufferUnorderedConfig {
buffer_size: 1024,
max_parallel: 1024,
},
)
.subscribe_async::<Resp>(1024, Default::default())
.subscribe_async::<GetCount>(8, Default::default())
.done()
}
#[tokio::test]
async fn test_sync() {
let (b, poller) = Bus::build().add_module(module()).build();
let cnt = 4u32;
for i in 0..cnt {
for j in 0..32768 {
b.send(Req(i * 128 + j)).await.unwrap();
}
println!("{} sent", i);
}
println!("sent");
b.flush_all().await;
println!("flushed");
assert_eq!(
b.request_we::<_, CountResult, Error>(GetCount, Default::default())
.await
.unwrap()
.0,
cnt * 32768 - cnt * 256
);
b.close().await;
println!("closed");
poller.await;
}

32
tests/test_derive.rs Normal file
View File

@ -0,0 +1,32 @@
use messagebus::{
derive::{Error as MbError, Message},
error, Message, TypeTagged,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
#[namespace("api")]
pub struct Msg<F>(pub F);
#[derive(Debug, Clone, Message)]
#[type_tag("api::Query")]
pub struct Qqq<F, G, H>(pub F, pub G, pub H);
fn main() {
assert_eq!(
Qqq::<Msg<i32>, Msg<()>, u64>::type_tag_(),
"api::Query<api::Msg<i32>,api::Msg<()>,u64>"
);
}

71
tests/test_idle.rs Normal file
View File

@ -0,0 +1,71 @@
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error, receivers, AsyncHandler, Bus, Message,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
struct MsgF32(pub f32);
#[derive(Debug, Clone, Message)]
struct MsgF64(pub f64);
struct TmpReceiver;
#[async_trait]
impl AsyncHandler<MsgF64> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgF64, _bus: &Bus) -> Result<Self::Response, Self::Error> {
std::thread::sleep(std::time::Duration::from_millis(100));
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgF32> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: MsgF32, bus: &Bus) -> Result<Self::Response, Self::Error> {
bus.send(MsgF64(12.0)).await.unwrap();
bus.flush::<MsgF64>().await;
Ok(())
}
}
#[tokio::test]
async fn test_backpressure() {
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe_async::<MsgF32>(
1,
receivers::BufferUnorderedConfig {
buffer_size: 1,
max_parallel: 1,
},
)
.done()
.build();
b.send(MsgF32(10.0)).await.unwrap();
// b.idle_all().await;
b.flush_all().await;
b.close().await;
poller.await;
}

204
tests/test_relay.rs Normal file
View File

@ -0,0 +1,204 @@
use std::pin::Pin;
use async_trait::async_trait;
use futures::Stream;
use messagebus::{
derive::{Error as MbError, Message},
error::{self, GenericError},
receivers, Action, AsyncHandler, Bus, Event, Message, MessageBounds, ReciveUntypedReceiver,
SendUntypedReceiver, TypeTagAccept, TypeTagAcceptItem, TypeTagged,
};
use parking_lot::Mutex;
use thiserror::Error;
use tokio::sync::mpsc;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
pub struct Msg<F: MessageBounds + Clone>(pub F);
struct TmpReceiver;
#[async_trait]
impl AsyncHandler<Msg<i32>> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, msg: Msg<i32>, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("TmpReceiver::handle {:?}", msg);
Ok(())
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver::sync");
Ok(())
}
}
pub type TestRelayRxChannelCell =
Mutex<Option<mpsc::UnboundedReceiver<Event<Box<dyn Message>, GenericError>>>>;
pub type TestRelayRxStream =
Pin<Box<dyn Stream<Item = Event<Box<dyn Message>, error::GenericError>> + Send>>;
pub struct TestRelay {
stx: mpsc::UnboundedSender<Event<Box<dyn Message>, GenericError>>,
srx: TestRelayRxChannelCell,
}
impl TypeTagAccept for TestRelay {
fn accept_req(
&self,
msg: &messagebus::TypeTag,
resp: Option<&messagebus::TypeTag>,
_err: Option<&messagebus::TypeTag>,
) -> bool {
if msg.as_ref() == Msg::<i16>::type_tag_().as_ref() {
if let Some(resp) = resp {
if resp.as_ref() == Msg::<u8>::type_tag_().as_ref() {
return true;
}
} else {
return true;
}
}
if msg.as_ref() == Msg::<i32>::type_tag_().as_ref() {
if let Some(resp) = resp {
if resp.as_ref() == Msg::<u64>::type_tag_().as_ref() {
return true;
}
} else {
return true;
}
}
false
}
fn accept_msg(&self, msg: &messagebus::TypeTag) -> bool {
if msg.as_ref() == Msg::<i32>::type_tag_().as_ref() {
return true;
}
false
}
fn iter_types(&self) -> Box<dyn Iterator<Item = TypeTagAcceptItem>> {
Box::new(
std::iter::once((Msg::<i32>::type_tag_(), None))
.chain(std::iter::once((
Msg::<i32>::type_tag_(),
Some((Msg::<u64>::type_tag_(), GenericError::type_tag_())),
)))
.chain(std::iter::once((
Msg::<i16>::type_tag_(),
Some((Msg::<u8>::type_tag_(), GenericError::type_tag_())),
))),
)
}
}
impl SendUntypedReceiver for TestRelay {
fn send(&self, msg: Action, _bus: &Bus) -> Result<(), error::Error<Action>> {
match msg {
Action::Init(..) => {
self.stx.send(Event::Ready).unwrap();
}
Action::Close => {
self.stx.send(Event::Exited).unwrap();
}
Action::Flush => {
self.stx.send(Event::Flushed).unwrap();
}
Action::Sync => {
self.stx.send(Event::Synchronized(Ok(()))).unwrap();
}
_ => unimplemented!(),
}
println!("TestRelay::send {:?}", msg);
Ok(())
}
fn send_msg(
&self,
mid: u64,
msg: Box<dyn Message>,
req: bool,
_bus: &Bus,
) -> Result<(), error::Error<Box<dyn Message>>> {
println!("TestRelay::send_msg [{}] {:?}", mid, msg);
if msg.type_tag().as_ref() == Msg::<i16>::type_tag_().as_ref() {
self.stx
.send(Event::Response(mid, Ok(Box::new(Msg(9u8)))))
.unwrap();
} else if msg.type_tag().as_ref() == Msg::<i32>::type_tag_().as_ref() {
if req {
self.stx
.send(Event::Response(mid, Ok(Box::new(Msg(22u64)))))
.unwrap();
} else {
self.stx
.send(Event::Response(mid, Ok(Box::new(()))))
.unwrap();
}
} else {
panic!("unsupported message type {}", msg.type_tag());
}
Ok(())
}
}
impl ReciveUntypedReceiver for TestRelay {
type Stream = TestRelayRxStream;
fn event_stream(&self, _: Bus) -> Self::Stream {
let mut rx = self.srx.lock().take().unwrap();
Box::pin(futures::stream::poll_fn(move |cx| rx.poll_recv(cx)))
}
}
#[tokio::test]
async fn test_relay() {
let (stx, srx) = mpsc::unbounded_channel();
let relay = TestRelay {
stx,
srx: Mutex::new(Some(srx)),
};
let (b, poller) = Bus::build()
.register_relay(relay)
.register(TmpReceiver)
.subscribe_async::<Msg<i32>>(
1,
receivers::BufferUnorderedConfig {
buffer_size: 1,
max_parallel: 1,
},
)
.done()
.build();
b.send(Msg(32i32)).await.unwrap();
let res1: Msg<u8> = b.request(Msg(12i16), Default::default()).await.unwrap();
let res2: Msg<u64> = b.request(Msg(12i32), Default::default()).await.unwrap();
assert_eq!(res1.0, 9u8);
assert_eq!(res2.0, 22u64);
b.flush_all().await;
b.close().await;
poller.await;
}

246
tests/test_req_resp.rs Normal file
View File

@ -0,0 +1,246 @@
use core::f32;
use async_trait::async_trait;
use messagebus::{
derive::Message,
error::{self, StdSyncSendError},
AsyncHandler, Bus, Message,
};
use thiserror::Error;
#[derive(Debug, Error, messagebus::derive::Error)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message, E: StdSyncSendError> From<error::Error<M, E>> for Error {
fn from(err: error::Error<M, E>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgF64(pub f64);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgF32(pub f32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI32(pub i32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU32(pub u32);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU16(pub u16);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI16(pub i16);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgU8(pub u8);
#[derive(Debug, Clone, Message)]
#[message(clone)]
struct MsgI8(pub i8);
struct TmpReceiver1;
struct TmpReceiver2;
#[async_trait]
impl AsyncHandler<MsgI32> for TmpReceiver1 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgI32, bus: &Bus) -> Result<Self::Response, Self::Error> {
let resp1 = bus
.request::<_, MsgF32>(MsgI16(10i16), Default::default())
.await?;
let resp2 = bus
.request::<_, MsgF32>(MsgU16(20u16), Default::default())
.await?;
Ok(MsgF32(msg.0 as f32 + resp1.0 + resp2.0))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver1 i32: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU32> for TmpReceiver1 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgU32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(MsgF32(msg.0 as _))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver1 u32: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI16> for TmpReceiver1 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgI16, bus: &Bus) -> Result<Self::Response, Self::Error> {
let resp1 = bus
.request::<_, MsgF32>(MsgI8(1i8), Default::default())
.await?;
let resp2 = bus
.request::<_, MsgF32>(MsgU8(2u8), Default::default())
.await?;
Ok(MsgF32(msg.0 as f32 + resp1.0 + resp2.0))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver i16: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU16> for TmpReceiver1 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgU16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(MsgF32(msg.0 as _))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver i16: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgI8> for TmpReceiver1 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgI8, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(MsgF32(msg.0 as _))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver1 i8: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgU8> for TmpReceiver1 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgU8, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(MsgF32(msg.0 as _))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver1 u8: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgF64> for TmpReceiver2 {
type Error = Error;
type Response = MsgF64;
async fn handle(&self, msg: MsgF64, bus: &Bus) -> Result<Self::Response, Self::Error> {
let resp1 = bus
.request::<_, MsgF32>(MsgI32(100i32), Default::default())
.await?
.0 as f64;
let resp2 = bus
.request::<_, MsgF32>(MsgU32(200u32), Default::default())
.await?
.0 as f64;
let resp3 = bus
.request::<_, MsgF32>(MsgF32(300f32), Default::default())
.await?
.0 as f64;
Ok(MsgF64(msg.0 + resp1 + resp2 + resp3))
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver1 f64: sync");
Ok(())
}
}
#[async_trait]
impl AsyncHandler<MsgF32> for TmpReceiver2 {
type Error = Error;
type Response = MsgF32;
async fn handle(&self, msg: MsgF32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(msg)
}
async fn sync(&self, _bus: &Bus) -> Result<(), Self::Error> {
println!("TmpReceiver2: f32: sync");
Ok(())
}
}
#[tokio::test]
async fn test() {
let (b, poller) = Bus::build()
.register(TmpReceiver1)
.subscribe_async::<MsgI32>(8, Default::default())
.subscribe_async::<MsgU32>(8, Default::default())
.subscribe_async::<MsgI16>(8, Default::default())
.subscribe_async::<MsgU16>(8, Default::default())
.subscribe_async::<MsgI8>(8, Default::default())
.subscribe_async::<MsgU8>(8, Default::default())
.done()
.register(TmpReceiver2)
.subscribe_async::<MsgF32>(8, Default::default())
.subscribe_async::<MsgF64>(8, Default::default())
.done()
.build();
let we_res = b
.request_we::<_, MsgF64, Error>(MsgF64(1000f64), Default::default())
.await
.unwrap();
assert!((we_res.0 - 1633.0f64).abs() < f64::EPSILON);
let boxed_res = b
.request_boxed(Box::new(MsgF64(1000.)), Default::default())
.await
.unwrap();
let val = boxed_res.as_any_ref().downcast_ref::<MsgF64>().unwrap().0;
assert!((val - 1633.0f64).abs() < f64::EPSILON);
b.flush_all().await;
b.close().await;
poller.await;
}

85
tests/test_serde.rs Normal file
View File

@ -0,0 +1,85 @@
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error, AsyncHandler, Bus, Message, TypeTag,
};
use serde_derive::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Message)]
#[message(shared, clone)]
#[type_tag("Msg")]
struct Msg {
test1: u32,
test2: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, Message)]
#[message(shared, clone)]
#[type_tag("MsgResponse")]
struct MsgResponse {
test1: u32,
test2: String,
}
struct TmpReceiver;
#[async_trait]
impl AsyncHandler<Msg> for TmpReceiver {
type Error = Error;
type Response = MsgResponse;
async fn handle(&self, msg: Msg, _bus: &Bus) -> Result<Self::Response, Self::Error> {
Ok(MsgResponse {
test1: msg.test1 * 2,
test2: msg.test2 + ", World!",
})
}
}
#[tokio::test]
async fn test() {
let (b, poller) = Bus::build()
.register(TmpReceiver)
.subscribe_async::<Msg>(8, Default::default())
.done()
.build();
let type_tag: TypeTag = "Msg".into();
let message = br#"{"test1":12,"test2":"Hello"}"#;
let json = &mut serde_json::Deserializer::from_slice(message);
let mut de = <dyn erased_serde::Deserializer>::erase(json);
let val = b
.request_deserialize(type_tag, &mut de, Default::default())
.await
.unwrap();
let mut buff: Vec<u8> = Vec::new();
let json = &mut serde_json::Serializer::new(&mut buff);
let mut ser = <dyn erased_serde::Serializer>::erase(json);
val.as_shared_ref()
.unwrap()
.erased_serialize(&mut ser)
.unwrap();
assert_eq!(val.type_tag(), TypeTag::from("MsgResponse"));
assert_eq!(buff.as_slice(), br#"{"test1":24,"test2":"Hello, World!"}"#);
b.flush_all().await;
b.close().await;
poller.await;
}

91
tests/test_shared.rs Normal file
View File

@ -0,0 +1,91 @@
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
};
use async_trait::async_trait;
use messagebus::{
derive::{Error as MbError, Message},
error, AsyncHandler, Bus, Message,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, serde_derive::Serialize, serde_derive::Deserialize, Message)]
#[message(clone, shared)]
struct Msg;
#[derive(Debug, Clone, serde_derive::Serialize, serde_derive::Deserialize, Message)]
#[message(clone, shared)]
struct SharedMsg<T>(T);
struct TmpReceiverContext {
sync1: AtomicBool,
sync2: AtomicBool,
}
struct TmpReceiver {
ctx: Arc<TmpReceiverContext>,
}
#[async_trait]
impl AsyncHandler<SharedMsg<f32>> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(
&self,
_msg: SharedMsg<f32>,
_bus: &Bus,
) -> Result<Self::Response, Self::Error> {
self.ctx.sync1.store(true, Ordering::Relaxed);
Ok(())
}
}
#[async_trait]
impl AsyncHandler<Msg> for TmpReceiver {
type Error = Error;
type Response = ();
async fn handle(&self, _msg: Msg, _bus: &Bus) -> Result<Self::Response, Self::Error> {
self.ctx.sync2.store(false, Ordering::Relaxed);
Ok(())
}
}
#[tokio::test]
async fn test_shared() {
let ctx = Arc::new(TmpReceiverContext {
sync1: AtomicBool::new(false),
sync2: AtomicBool::new(false),
});
let (b, poller) = Bus::build()
.register(TmpReceiver { ctx: ctx.clone() })
.subscribe_async::<Msg>(8, Default::default())
.subscribe_async::<SharedMsg<f32>>(8, Default::default())
.done()
.build();
b.send_one(Msg).await.unwrap();
b.send_one(SharedMsg(0.0f32)).await.unwrap();
b.flush_all().await;
b.close().await;
poller.await;
assert!(ctx.sync1.load(Ordering::Relaxed));
assert!(!ctx.sync2.load(Ordering::Relaxed));
}

85
tests/test_sync.rs Normal file
View File

@ -0,0 +1,85 @@
use messagebus::{
derive::{Error as MbError, Message},
error, Bus, Handler, Message, Module,
};
use thiserror::Error;
#[derive(Debug, Error, MbError)]
enum Error {
#[error("Error({0})")]
Error(anyhow::Error),
}
impl<M: Message> From<error::Error<M>> for Error {
fn from(err: error::Error<M>) -> Self {
Self::Error(err.into())
}
}
#[derive(Debug, Clone, Message)]
struct MsgF32(pub f32);
#[derive(Debug, Clone, Message)]
struct MsgU32(pub u32);
#[derive(Debug, Clone, Message)]
struct MsgU16(pub u16);
struct TmpReceiver;
impl Handler<MsgF32> for TmpReceiver {
type Error = Error;
type Response = ();
fn handle(&self, msg: MsgF32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> f32 {:?}", msg);
std::thread::sleep(std::time::Duration::from_millis(100));
println!("done");
Ok(())
}
}
impl Handler<MsgU16> for TmpReceiver {
type Error = Error;
type Response = ();
fn handle(&self, msg: MsgU16, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> u16 {:?}", msg);
Ok(())
}
}
impl Handler<MsgU32> for TmpReceiver {
type Error = Error;
type Response = ();
fn handle(&self, msg: MsgU32, _bus: &Bus) -> Result<Self::Response, Self::Error> {
println!("---> u32 {:?}", msg);
Ok(())
}
}
fn module() -> Module {
Module::new()
.register(TmpReceiver)
.subscribe_sync::<MsgF32>(8, Default::default())
.subscribe_sync::<MsgU16>(8, Default::default())
.subscribe_sync::<MsgU32>(8, Default::default())
.done()
}
#[tokio::test]
async fn test_sync() {
let (b, poller) = Bus::build().add_module(module()).build();
b.send(MsgF32(32f32)).await.unwrap();
b.send(MsgU16(11u16)).await.unwrap();
b.send(MsgU32(32u32)).await.unwrap();
b.flush_and_sync_all(false).await;
b.close().await;
poller.await;
}