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}