google_cloud_pubsub/publisher/
client.rs

1// Copyright 2025 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::publisher::publisher::PublisherBuilder;
16
17/// Creates [`Publisher`](super::publisher::Publisher) instances.
18///
19/// This is the main entry point for the publisher API. A single `Client`
20/// can be used to create multiple `Publisher` clients for different topics.
21/// It manages the underlying gRPC connection and authentication.
22///
23/// # Example
24///
25/// ```
26/// # async fn sample() -> anyhow::Result<()> {
27/// # use google_cloud_pubsub::client::Client;
28/// # use google_cloud_pubsub::model::PubsubMessage;
29///
30/// // Create a client.
31/// let client = Client::builder().build().await?;
32///
33/// // Create a publisher for a specific topic.
34/// let publisher = client.publisher("projects/my-project/topics/my-topic").build();
35///
36/// // Publish a message.
37/// let handle = publisher.publish(PubsubMessage::new().set_data("hello world"));
38/// let message_id = handle.await?;
39/// println!("Message sent with ID: {}", message_id);
40/// # Ok(())
41/// # }
42/// ```
43#[derive(Clone, Debug)]
44pub struct Client {
45    pub(crate) inner: crate::generated::gapic_dataplane::client::Publisher,
46}
47
48/// A builder for [Client].
49///
50/// ```
51/// # async fn sample() -> anyhow::Result<()> {
52/// # use google_cloud_pubsub::*;
53/// # use builder::publisher::ClientBuilder;
54/// # use client::Client;
55/// let builder: ClientBuilder = Client::builder();
56/// let client = builder
57///     .with_endpoint("https://pubsub.googleapis.com")
58///     .build().await?;
59/// # Ok(()) }
60/// ```
61pub type ClientBuilder =
62    gax::client_builder::ClientBuilder<client_builder::Factory, gaxi::options::Credentials>;
63
64pub(crate) mod client_builder {
65    use super::Client;
66
67    pub struct Factory;
68    impl gax::client_builder::internal::ClientFactory for Factory {
69        type Client = Client;
70        type Credentials = gaxi::options::Credentials;
71        #[allow(unused_mut)]
72        async fn build(
73            self,
74            mut config: gaxi::options::ClientConfig,
75        ) -> gax::client_builder::Result<Self::Client> {
76            // TODO(#3019): Pubsub default retry policy goes here.
77            Self::Client::new(config).await
78        }
79    }
80}
81
82impl Client {
83    /// Returns a builder for [Client].
84    ///
85    /// ```no_run
86    /// # tokio_test::block_on(async {
87    /// # use google_cloud_pubsub::client::Client;
88    /// let client = Client::builder().build().await?;
89    /// # gax::client_builder::Result::<()>::Ok(()) });
90    /// ```
91    pub fn builder() -> ClientBuilder {
92        gax::client_builder::internal::new_builder(client_builder::Factory)
93    }
94
95    /// Creates a new Pub/Sub publisher client with the given configuration.
96    pub(crate) async fn new(
97        config: gaxi::options::ClientConfig,
98    ) -> Result<Self, gax::client_builder::Error> {
99        let inner = crate::generated::gapic_dataplane::client::Publisher::new(config).await?;
100        std::result::Result::Ok(Self { inner })
101    }
102
103    /// Creates a new `Publisher` for a given topic.
104    ///
105    /// ```
106    /// # async fn sample() -> anyhow::Result<()> {
107    /// # use google_cloud_pubsub::*;
108    /// # use builder::publisher::ClientBuilder;
109    /// # use client::Client;
110    /// # use model::PubsubMessage;
111    /// let client = Client::builder().build().await?;
112    /// let publisher = client.publisher("projects/my-project/topics/my-topic").build();
113    /// let message_id = publisher.publish(PubsubMessage::new().set_data("Hello, World")).await?;
114    /// # Ok(()) }
115    /// ```
116    pub fn publisher<T>(&self, topic: T) -> PublisherBuilder
117    where
118        T: Into<String>,
119    {
120        PublisherBuilder::new(self.inner.clone(), topic.into())
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use super::Client;
127
128    #[tokio::test]
129    async fn builder() -> anyhow::Result<()> {
130        let client = Client::builder()
131            .with_credentials(auth::credentials::anonymous::Builder::new().build())
132            .build()
133            .await?;
134        let _ = client.publisher("projects/my-project/topics/my-topic".to_string());
135        Ok(())
136    }
137}