lib.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. use std::sync::RwLock;
  2. use bytes::Bytes;
  3. use lazy_static::lazy_static;
  4. use lib_dispatch::prelude::ToBytes;
  5. use crate::entities::SubscribeObject;
  6. pub mod entities;
  7. mod protobuf;
  8. lazy_static! {
  9. static ref NOTIFICATION_SENDER: RwLock<Vec<Box<dyn NotificationSender>>> = RwLock::new(vec![]);
  10. }
  11. /// Register a notification sender. The sender will be alive until the process exits.
  12. /// Flutter integration test or Tauri hot reload might cause register multiple times.
  13. /// So before register a new sender, you might need to unregister the old one. Currently,
  14. /// Just remove all senders by calling `unregister_all_notification_sender`.
  15. pub fn register_notification_sender<T: NotificationSender>(sender: T) {
  16. let box_sender = Box::new(sender);
  17. match NOTIFICATION_SENDER.write() {
  18. Ok(mut write_guard) => write_guard.push(box_sender),
  19. Err(err) => tracing::error!("Failed to push notification sender: {:?}", err),
  20. }
  21. }
  22. pub fn unregister_all_notification_sender() {
  23. match NOTIFICATION_SENDER.write() {
  24. Ok(mut write_guard) => write_guard.clear(),
  25. Err(err) => tracing::error!("Failed to remove all notification senders: {:?}", err),
  26. }
  27. }
  28. pub trait NotificationSender: Send + Sync + 'static {
  29. fn send_subject(&self, subject: SubscribeObject) -> Result<(), String>;
  30. }
  31. pub struct NotificationBuilder {
  32. id: String,
  33. payload: Option<Bytes>,
  34. error: Option<Bytes>,
  35. source: String,
  36. ty: i32,
  37. }
  38. impl NotificationBuilder {
  39. pub fn new<T: Into<i32>>(id: &str, ty: T, source: &str) -> Self {
  40. Self {
  41. id: id.to_owned(),
  42. ty: ty.into(),
  43. payload: None,
  44. error: None,
  45. source: source.to_owned(),
  46. }
  47. }
  48. pub fn payload<T>(mut self, payload: T) -> Self
  49. where
  50. T: ToBytes,
  51. {
  52. match payload.into_bytes() {
  53. Ok(bytes) => self.payload = Some(bytes),
  54. Err(e) => {
  55. tracing::error!("Set observable payload failed: {:?}", e);
  56. },
  57. }
  58. self
  59. }
  60. pub fn error<T>(mut self, error: T) -> Self
  61. where
  62. T: ToBytes,
  63. {
  64. match error.into_bytes() {
  65. Ok(bytes) => self.error = Some(bytes),
  66. Err(e) => {
  67. tracing::error!("Set observable error failed: {:?}", e);
  68. },
  69. }
  70. self
  71. }
  72. pub fn send(self) {
  73. let payload = self.payload.map(|bytes| bytes.to_vec());
  74. let error = self.error.map(|bytes| bytes.to_vec());
  75. let subject = SubscribeObject {
  76. source: self.source,
  77. ty: self.ty,
  78. id: self.id,
  79. payload,
  80. error,
  81. };
  82. match NOTIFICATION_SENDER.read() {
  83. Ok(read_guard) => read_guard.iter().for_each(|sender| {
  84. if let Err(e) = sender.send_subject(subject.clone()) {
  85. tracing::error!("Post notification failed: {}", e);
  86. }
  87. }),
  88. Err(err) => {
  89. tracing::error!("Read notification sender failed: {}", err);
  90. },
  91. }
  92. }
  93. }