ruststream_gcp_pubsub/
subscriber.rs1use futures::Stream;
10
11use google_cloud_pubsub::subscriber::{MessageStream, ShutdownToken};
12use ruststream::Subscriber;
13use tokio::sync::mpsc;
14
15use crate::broker::Core;
16use crate::error::{PubSubError, box_err};
17use crate::message::PubSubMessage;
18use crate::subscription::PubSubSubscription;
19
20const CHANNEL_CAPACITY: usize = 16;
23
24pub struct PubSubSubscriber {
29 subscription: String,
30 rx: mpsc::Receiver<Result<PubSubMessage, PubSubError>>,
31 shutdown: ShutdownToken,
32}
33
34impl std::fmt::Debug for PubSubSubscriber {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 f.debug_struct("PubSubSubscriber")
37 .field("subscription", &self.subscription)
38 .finish_non_exhaustive()
39 }
40}
41
42impl PubSubSubscriber {
43 #[must_use]
45 pub fn subscription(&self) -> &str {
46 &self.subscription
47 }
48
49 pub(crate) fn open(core: &Core, descriptor: &PubSubSubscription) -> Self {
51 let name = core.subscription_name(descriptor.subscription());
52 let mut builder = core.subscriber.subscribe(name.clone());
53 if let Some(messages) = descriptor.max_outstanding_value() {
54 builder = builder.set_max_outstanding_messages(messages);
55 }
56 if let Some(extension) = descriptor.ack_extension_value() {
57 builder = builder.set_max_lease_extension(extension);
58 }
59 let stream = builder.build();
60 let shutdown = stream.shutdown_token();
61
62 let (tx, rx) = mpsc::channel(CHANNEL_CAPACITY);
63 tokio::spawn(pump(stream, tx, name.clone()));
64
65 Self {
66 subscription: name,
67 rx,
68 shutdown,
69 }
70 }
71}
72
73impl Drop for PubSubSubscriber {
74 fn drop(&mut self) {
75 let token = self.shutdown.clone();
79 if let Ok(handle) = tokio::runtime::Handle::try_current() {
80 handle.spawn(async move {
81 token.shutdown().await;
82 });
83 }
84 }
85}
86
87impl Subscriber for PubSubSubscriber {
88 type Message = PubSubMessage;
89 type Error = PubSubError;
90
91 fn stream(&mut self) -> impl Stream<Item = Result<PubSubMessage, PubSubError>> + Send + '_ {
92 futures::stream::poll_fn(move |cx| self.rx.poll_recv(cx))
96 }
97}
98
99async fn pump(
100 mut stream: MessageStream,
101 out: mpsc::Sender<Result<PubSubMessage, PubSubError>>,
102 subscription: String,
103) {
104 while let Some(item) = stream.next().await {
105 match item {
106 Ok((message, handler)) => {
107 if out
108 .send(Ok(PubSubMessage::new(message, handler)))
109 .await
110 .is_err()
111 {
112 break;
114 }
115 }
116 Err(err) => {
117 let _ = out
120 .send(Err(PubSubError::Receive {
121 subscription: subscription.clone(),
122 source: box_err(err),
123 }))
124 .await;
125 break;
126 }
127 }
128 }
129}