ruststream_gcp_pubsub/
publisher.rs1use google_cloud_pubsub::client::Publisher as GcpPublisher;
4use ruststream::{OutgoingMessage, PairError, PublishPolicy, Publisher};
5
6use crate::broker::{ConnectedPubSubBroker, Core, CoreCell};
7use crate::error::{PubSubError, box_err};
8use crate::message::to_gcp_message;
9
10#[derive(Clone)]
18pub struct PubSubPublisher {
19 cell: CoreCell,
20}
21
22impl std::fmt::Debug for PubSubPublisher {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 f.debug_struct("PubSubPublisher").finish_non_exhaustive()
25 }
26}
27
28impl PubSubPublisher {
29 pub(crate) fn new(cell: CoreCell) -> Self {
30 Self { cell }
31 }
32
33 fn core(&self) -> Result<&Core, PubSubError> {
34 let core = self.cell.get().ok_or(PubSubError::NotConnected)?;
35 core.ensure_open()?;
36 Ok(core)
37 }
38
39 async fn publisher_for(&self, core: &Core, topic: &str) -> GcpPublisher {
41 let name = core.topic_name(topic);
42 let mut publishers = core.publishers.lock().await;
43 if let Some(publisher) = publishers.get(&name) {
44 return publisher.clone();
45 }
46 let publisher = core.base_publisher.publisher(name.clone()).build();
49 publishers.insert(name, publisher.clone());
50 publisher
51 }
52}
53
54impl Publisher for PubSubPublisher {
55 type Error = PubSubError;
56
57 async fn publish(&self, msg: OutgoingMessage<'_>) -> Result<(), Self::Error> {
58 let core = self.core()?;
59 let publisher = self.publisher_for(core, msg.name()).await;
60 let (message, ordering_key) = to_gcp_message(&msg);
61 match publisher.publish(message).await {
62 Ok(_message_id) => Ok(()),
63 Err(err) => {
64 if !ordering_key.is_empty() {
67 publisher.resume_publish(ordering_key);
68 }
69 Err(PubSubError::Publish {
70 topic: core.topic_name(msg.name()),
71 source: box_err(err),
72 })
73 }
74 }
75 }
76}
77
78#[derive(Debug, Clone, Copy, Default)]
90#[must_use]
91pub struct PubSubPublish;
92
93impl PublishPolicy<ConnectedPubSubBroker> for PubSubPublish {
94 type Live = PubSubPublisher;
95
96 async fn pair(self, connected: &ConnectedPubSubBroker) -> Result<Self::Live, PairError> {
97 Ok(connected.publisher())
98 }
99}