google_cloud_bigquery/write/client_builder.rs
1// Copyright 2026 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::ClientBuilderResult as BuilderResult;
16use crate::client::Write;
17use gaxi::options::ClientConfig;
18use google_cloud_auth::credentials::Credentials;
19
20/// A builder for [Write].
21///
22/// # Example
23/// ```
24/// # use google_cloud_bigquery::client::Write;
25/// # async fn sample() -> anyhow::Result<()> {
26/// let builder = Write::builder();
27/// let client = builder
28/// .with_endpoint("https://bigquerystoragewrite.googleapis.com")
29/// .build()
30/// .await?;
31/// # Ok(()) }
32/// ```
33#[derive(Debug)]
34pub struct ClientBuilder {
35 pub(super) config: ClientConfig,
36}
37
38impl ClientBuilder {
39 pub(super) fn new() -> Self {
40 Self {
41 config: ClientConfig::default(),
42 }
43 }
44
45 /// Creates a new client.
46 ///
47 /// # Example
48 /// ```
49 /// # use google_cloud_bigquery::client::Write;
50 /// # async fn sample() -> anyhow::Result<()> {
51 /// let client = Write::builder().build().await?;
52 /// # Ok(()) }
53 /// ```
54 pub async fn build(self) -> BuilderResult<Write> {
55 Write::new(self).await
56 }
57
58 /// Sets the endpoint.
59 ///
60 /// # Example
61 /// ```
62 /// # use google_cloud_bigquery::client::Write;
63 /// # async fn sample() -> anyhow::Result<()> {
64 /// let client = Write::builder()
65 /// .with_endpoint("https://private.googleapis.com")
66 /// .build()
67 /// .await?;
68 /// # Ok(()) }
69 /// ```
70 pub fn with_endpoint<V: Into<String>>(mut self, v: V) -> Self {
71 self.config.endpoint = Some(v.into());
72 self
73 }
74
75 /// Configure the universe domain.
76 ///
77 /// The universe domain is the default service domain for a given cloud universe.
78 /// The default value is "googleapis.com".
79 ///
80 /// # Example
81 /// ```
82 /// # use google_cloud_bigquery::client::Write;
83 /// # async fn sample() -> anyhow::Result<()> {
84 /// let client = Write::builder()
85 /// .with_universe_domain("googleapis.com")
86 /// .build()
87 /// .await?;
88 /// # Ok(()) }
89 /// ```
90 pub fn with_universe_domain<V: Into<String>>(mut self, v: V) -> Self {
91 self.config.universe_domain = Some(v.into());
92 self
93 }
94
95 /// Configures the authentication credentials.
96 ///
97 /// More information about valid credentials types can be found in the
98 /// [google-cloud-auth] crate documentation.
99 ///
100 /// # Example
101 /// ```
102 /// # use google_cloud_bigquery::client::Write;
103 /// # async fn sample() -> anyhow::Result<()> {
104 /// use google_cloud_auth::credentials::mds;
105 /// let client = Write::builder()
106 /// .with_credentials(
107 /// mds::Builder::default()
108 /// .with_scopes(["https://www.googleapis.com/auth/cloud-platform.read-only"])
109 /// .build()?)
110 /// .build()
111 /// .await?;
112 /// # Ok(()) }
113 /// ```
114 ///
115 /// [google-cloud-auth]: https://docs.rs/google-cloud-auth
116 pub fn with_credentials<V: Into<Credentials>>(mut self, v: V) -> Self {
117 self.config.cred = Some(v.into());
118 self
119 }
120
121 /// Configure the number of subchannels used by the client.
122 ///
123 /// # Example
124 /// ```
125 /// # use google_cloud_bigquery::client::Write;
126 /// # async fn sample() -> anyhow::Result<()> {
127 /// let count = std::thread::available_parallelism()?.get();
128 /// let client = Write::builder()
129 /// .with_grpc_subchannel_count(count)
130 /// .build()
131 /// .await?;
132 /// # Ok(()) }
133 /// ```
134 ///
135 /// gRPC-based clients may exhibit high latency if many requests need to be
136 /// demuxed over a single HTTP/2 connection (often called a *subchannel* in
137 /// gRPC).
138 ///
139 /// Consider using more subchannels if your application creates many
140 /// writers. Consider using fewer subchannels if your application needs the
141 /// file descriptors for other purposes.
142 pub fn with_grpc_subchannel_count(mut self, v: usize) -> Self {
143 self.config.grpc_subchannel_count = Some(v);
144 self
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use google_cloud_auth::credentials::anonymous::Builder as Anonymous;
152
153 #[test]
154 fn defaults() {
155 let builder = ClientBuilder::new();
156 assert!(builder.config.endpoint.is_none(), "{:?}", builder.config);
157 assert!(builder.config.cred.is_none(), "{:?}", builder.config);
158 assert!(
159 builder.config.universe_domain.is_none(),
160 "{:?}",
161 builder.config
162 );
163 assert!(
164 builder.config.grpc_subchannel_count.is_none(),
165 "{:?}",
166 builder.config
167 );
168 }
169
170 #[test]
171 fn setters() {
172 let builder = ClientBuilder::new()
173 .with_endpoint("test-endpoint.com")
174 .with_universe_domain("test-ud.com")
175 .with_credentials(Anonymous::new().build())
176 .with_grpc_subchannel_count(16);
177 assert_eq!(
178 builder.config.endpoint,
179 Some("test-endpoint.com".to_string())
180 );
181 assert_eq!(
182 builder.config.universe_domain,
183 Some("test-ud.com".to_string())
184 );
185 assert!(builder.config.cred.is_some(), "{:?}", builder.config);
186 assert_eq!(builder.config.grpc_subchannel_count, Some(16));
187 }
188}