message_subscriber.rs 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. use async_std::sync::Mutex;
  2. use rand::Rng;
  3. use std::collections::HashMap;
  4. use std::sync::Arc;
  5. use crate::net::error::NetResult;
  6. use crate::net::messages::{Message, PacketType};
  7. pub type MessageSubscriberPtr = Arc<MessageSubscriber>;
  8. pub type MessageResult = NetResult<Arc<Message>>;
  9. pub type MessageSubscriptionID = u64;
  10. macro_rules! receive_message {
  11. ($sub:expr, $message_type:path) => {{
  12. let wrapped_message = owning_ref::OwningRef::new($sub.receive().await?);
  13. wrapped_message.map(|msg| match msg {
  14. $message_type(msg_detail) => msg_detail,
  15. _ => {
  16. panic!("Filter for receive sub invalid!");
  17. }
  18. })
  19. }};
  20. }
  21. pub struct MessageSubscription {
  22. id: MessageSubscriptionID,
  23. filter: PacketType,
  24. recv_queue: async_channel::Receiver<MessageResult>,
  25. parent: Arc<MessageSubscriber>,
  26. }
  27. impl MessageSubscription {
  28. fn is_relevant_message(&self, message_result: &MessageResult) -> bool {
  29. match message_result {
  30. Ok(message) => {
  31. let packet_type = message.packet_type();
  32. // Apply the filter
  33. packet_type == self.filter
  34. }
  35. Err(_) => {
  36. // Propagate all errors
  37. true
  38. }
  39. }
  40. }
  41. pub async fn receive(&self) -> MessageResult {
  42. loop {
  43. let message_result = self.recv_queue.recv().await;
  44. match message_result {
  45. Ok(message_result) => {
  46. if self.clone().is_relevant_message(&message_result) {
  47. return message_result;
  48. }
  49. }
  50. Err(err) => {
  51. panic!("MessageSubscription::receive() recv_queue failed! {}", err);
  52. }
  53. }
  54. }
  55. }
  56. // Must be called manually since async Drop is not possible in Rust
  57. pub async fn unsubscribe(&self) {
  58. self.parent.clone().unsubscribe(self.id).await
  59. }
  60. }
  61. pub struct MessageSubscriber {
  62. subs: Mutex<HashMap<MessageSubscriptionID, async_channel::Sender<MessageResult>>>,
  63. }
  64. impl MessageSubscriber {
  65. pub fn new() -> Arc<Self> {
  66. Arc::new(Self {
  67. subs: Mutex::new(HashMap::new()),
  68. })
  69. }
  70. pub fn random_id() -> MessageSubscriptionID {
  71. let mut rng = rand::thread_rng();
  72. rng.gen()
  73. }
  74. pub async fn subscribe(self: Arc<Self>, packet_type: PacketType) -> MessageSubscription {
  75. let (sender, recvr) = async_channel::unbounded();
  76. let sub_id = Self::random_id();
  77. self.subs.lock().await.insert(sub_id, sender);
  78. MessageSubscription {
  79. id: sub_id,
  80. filter: packet_type,
  81. recv_queue: recvr,
  82. parent: self.clone(),
  83. }
  84. }
  85. async fn unsubscribe(self: Arc<Self>, sub_id: MessageSubscriptionID) {
  86. self.subs.lock().await.remove(&sub_id);
  87. }
  88. pub async fn notify(&self, message_result: NetResult<Arc<Message>>) {
  89. let mut garbage_ids = Vec::new();
  90. for (sub_id, sub) in &*self.subs.lock().await {
  91. match sub.send(message_result.clone()).await {
  92. Ok(()) => {}
  93. Err(_err) => {
  94. // Automatically clean out closed channels
  95. garbage_ids.push(*sub_id);
  96. //panic!("Error returned sending message in notify() call! {}", err);
  97. }
  98. }
  99. }
  100. self.collect_garbage(garbage_ids).await;
  101. }
  102. async fn collect_garbage(&self, ids: Vec<MessageSubscriptionID>) {
  103. let mut subs = self.subs.lock().await;
  104. for id in &ids {
  105. subs.remove(id);
  106. }
  107. }
  108. }