message_subscriber.rs 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. use async_std::sync::Mutex;
  2. use async_trait::async_trait;
  3. use log::*;
  4. use rand::Rng;
  5. use std::any::Any;
  6. use std::collections::HashMap;
  7. use std::io;
  8. use std::io::Cursor;
  9. use std::sync::Arc;
  10. use crate::error::{Error, Result};
  11. use crate::net::messages::Message;
  12. use crate::serial::{Decodable, Encodable};
  13. /// 64bit identifier for message subscription.
  14. pub type MessageSubscriptionId = u64;
  15. type MessageResult<M> = Result<Arc<M>>;
  16. /// Handles message subscriptions through a subscription ID and a receiver
  17. /// channel.
  18. pub struct MessageSubscription<M: Message> {
  19. id: MessageSubscriptionId,
  20. recv_queue: async_channel::Receiver<MessageResult<M>>,
  21. parent: Arc<MessageDispatcher<M>>,
  22. }
  23. impl<M: Message> MessageSubscription<M> {
  24. /// Start receiving messages.
  25. pub async fn receive(&self) -> MessageResult<M> {
  26. match self.recv_queue.recv().await {
  27. Ok(message) => message,
  28. Err(err) => {
  29. panic!("MessageSubscription::receive() recv_queue failed! {}", err);
  30. }
  31. }
  32. }
  33. /// Unsubscribe from a message subscription. Must be called manually.
  34. pub async fn unsubscribe(&self) {
  35. self.parent.clone().unsubscribe(self.id).await
  36. }
  37. }
  38. #[async_trait]
  39. /// Generic interface for message dispatcher.
  40. trait MessageDispatcherInterface: Send + Sync {
  41. async fn trigger(&self, payload: Vec<u8>);
  42. async fn trigger_error(&self, err: Error);
  43. fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
  44. }
  45. /// Maintains a list of active subscribers and handles sending messages across
  46. /// subscriptions.
  47. struct MessageDispatcher<M: Message> {
  48. subs: Mutex<HashMap<MessageSubscriptionId, async_channel::Sender<MessageResult<M>>>>,
  49. }
  50. impl<M: Message> MessageDispatcher<M> {
  51. /// Create a new message dispatcher.
  52. fn new() -> Self {
  53. MessageDispatcher {
  54. subs: Mutex::new(HashMap::new()),
  55. }
  56. }
  57. /// Create a random ID.
  58. fn random_id() -> MessageSubscriptionId {
  59. let mut rng = rand::thread_rng();
  60. rng.gen()
  61. }
  62. /// Subscribe to a channel. Assigns a new ID and adds it to the list of
  63. /// subscribers.
  64. pub async fn subscribe(self: Arc<Self>) -> MessageSubscription<M> {
  65. let (sender, recvr) = async_channel::unbounded();
  66. let sub_id = Self::random_id();
  67. self.subs.lock().await.insert(sub_id, sender);
  68. MessageSubscription {
  69. id: sub_id,
  70. recv_queue: recvr,
  71. parent: self,
  72. }
  73. }
  74. /// Unsubcribe from a channel. Removes the associated ID from the subscriber
  75. /// list.
  76. async fn unsubscribe(&self, sub_id: MessageSubscriptionId) {
  77. self.subs.lock().await.remove(&sub_id);
  78. }
  79. /// Send a message to all subscriber channels. Automatically clear inactive
  80. /// channels.
  81. async fn trigger_all(&self, message: MessageResult<M>) {
  82. debug!(
  83. "MessageDispatcher<M={}>::trigger_all({}) [START, subs={}]",
  84. M::name(),
  85. if message.is_ok() { "msg" } else { "err" },
  86. self.subs.lock().await.len()
  87. );
  88. let mut garbage_ids = Vec::new();
  89. for (sub_id, sub) in &*self.subs.lock().await {
  90. match sub.send(message.clone()).await {
  91. Ok(()) => {}
  92. Err(_err) => {
  93. // Automatically clean out closed channels
  94. garbage_ids.push(*sub_id);
  95. // panic!("Error returned sending message in notify() call!
  96. // {}", err);
  97. }
  98. }
  99. }
  100. self.collect_garbage(garbage_ids).await;
  101. debug!(
  102. "MessageDispatcher<M={}>::trigger_all({}) [END, subs={}]",
  103. M::name(),
  104. if message.is_ok() { "msg" } else { "err" },
  105. self.subs.lock().await.len()
  106. );
  107. }
  108. /// Remove inactive channels.
  109. async fn collect_garbage(&self, ids: Vec<MessageSubscriptionId>) {
  110. let mut subs = self.subs.lock().await;
  111. for id in &ids {
  112. subs.remove(id);
  113. }
  114. }
  115. }
  116. #[async_trait]
  117. // Local implementation of the Message Dispatcher Interface.
  118. impl<M: Message> MessageDispatcherInterface for MessageDispatcher<M> {
  119. /// Deserialize data into a message type.
  120. async fn trigger(&self, payload: Vec<u8>) {
  121. // deserialize data into type
  122. // send down the pipes
  123. let cursor = Cursor::new(payload);
  124. match M::decode(cursor) {
  125. Ok(message) => {
  126. let message = Ok(Arc::new(message));
  127. self.trigger_all(message).await
  128. }
  129. Err(err) => {
  130. error!("Unable to decode data. Dropping...: {}", err);
  131. }
  132. }
  133. }
  134. /// Sends a message to all subscriber channels. Clears any inactive
  135. /// channels.
  136. async fn trigger_error(&self, err: Error) {
  137. self.trigger_all(Err(err)).await;
  138. }
  139. /// Converts to Any trait. Enables the dynamic modification of static types.
  140. fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync> {
  141. self
  142. }
  143. }
  144. /// Publish/subscribe class that can dispatch any kind of message to a
  145. /// list of dispatchers.
  146. pub struct MessageSubsystem {
  147. dispatchers: Mutex<HashMap<&'static str, Arc<dyn MessageDispatcherInterface>>>,
  148. }
  149. impl MessageSubsystem {
  150. /// Create a new message subsystem.
  151. pub fn new() -> Self {
  152. MessageSubsystem {
  153. dispatchers: Mutex::new(HashMap::new()),
  154. }
  155. }
  156. /// Add a new message dispatcher.
  157. pub async fn add_dispatch<M: Message>(&self) {
  158. self.dispatchers
  159. .lock()
  160. .await
  161. .insert(M::name(), Arc::new(MessageDispatcher::<M>::new()));
  162. }
  163. /// Add a dispatcher to the list of subscribers.
  164. pub async fn subscribe<M: Message>(&self) -> Result<MessageSubscription<M>> {
  165. let dispatcher = self.dispatchers.lock().await.get(M::name()).cloned();
  166. let sub = match dispatcher {
  167. Some(dispatcher) => {
  168. let dispatcher: Arc<MessageDispatcher<M>> = dispatcher
  169. .as_any()
  170. .downcast::<MessageDispatcher<M>>()
  171. .expect("Multiple messages registered with different names");
  172. dispatcher.subscribe().await
  173. }
  174. None => {
  175. // normall return failure here
  176. // for now panic
  177. return Err(Error::OperationFailed);
  178. }
  179. };
  180. Ok(sub)
  181. }
  182. /// Sends a message out to subscribers. Returns an error if the message
  183. /// doesn't send.
  184. pub async fn notify(&self, command: &str, payload: Vec<u8>) {
  185. let dispatcher = self.dispatchers.lock().await.get(command).cloned();
  186. match dispatcher {
  187. Some(dispatcher) => {
  188. dispatcher.trigger(payload).await;
  189. }
  190. None => {
  191. warn!(
  192. "MessageSubsystem::notify(\"{}\", payload) did not find a dispatcher",
  193. command
  194. );
  195. }
  196. }
  197. }
  198. /// Send a message to all subscriber channels. Clear any inactive channels.
  199. pub async fn trigger_error(&self, err: Error) {
  200. // TODO: this could be parallelized
  201. for dispatcher in self.dispatchers.lock().await.values() {
  202. dispatcher.trigger_error(err.clone()).await;
  203. }
  204. }
  205. }
  206. /// Test functions for message subsystem.
  207. // This is a test function for the message subsystem code above
  208. // Normall we would use the #[test] macro but cannot since it is async code
  209. // Instead we call it using smol::block_on() in the unit test code after this
  210. // func
  211. async fn _do_message_subscriber_test() {
  212. struct MyVersionMessage {
  213. x: u32,
  214. }
  215. impl Message for MyVersionMessage {
  216. fn name() -> &'static str {
  217. "verver"
  218. }
  219. }
  220. impl Encodable for MyVersionMessage {
  221. fn encode<S: io::Write>(&self, mut s: S) -> Result<usize> {
  222. let mut len = 0;
  223. len += self.x.encode(&mut s)?;
  224. Ok(len)
  225. }
  226. }
  227. impl Decodable for MyVersionMessage {
  228. fn decode<D: io::Read>(mut d: D) -> Result<Self> {
  229. Ok(Self {
  230. x: Decodable::decode(&mut d)?,
  231. })
  232. }
  233. }
  234. println!("hello");
  235. let subsystem = MessageSubsystem::new();
  236. subsystem.add_dispatch::<MyVersionMessage>().await;
  237. // subscribe
  238. // 1. get dispatcher
  239. // 2. cast to specific type
  240. // 3. do sub, return sub
  241. let sub = subsystem.subscribe::<MyVersionMessage>().await.unwrap();
  242. let msg = MyVersionMessage { x: 110 };
  243. let mut payload = Vec::new();
  244. msg.encode(&mut payload).unwrap();
  245. // receive message and publish
  246. // 1. based on string, lookup relevant dispatcher interface
  247. // 2. publish data there
  248. subsystem.notify("verver", payload).await;
  249. // receive
  250. // 1. do a get easy
  251. let msg2 = sub.receive().await.unwrap();
  252. assert_eq!(msg2.x, 110);
  253. println!("{}", msg2.x);
  254. subsystem.trigger_error(Error::ChannelStopped).await;
  255. let msg2 = sub.receive().await;
  256. assert!(msg2.is_err());
  257. sub.unsubscribe().await;
  258. }
  259. #[cfg(test)]
  260. mod tests {
  261. use super::*;
  262. #[test]
  263. fn test_message_subscriber() {
  264. smol::block_on(_do_message_subscriber_test());
  265. }
  266. }