Skip to content

Commit bd8723c

Browse files
authored
rust(chore): Adds additional docs and examples (#448)
1 parent 8b9718a commit bd8723c

27 files changed

Lines changed: 2170 additions & 205 deletions

File tree

python/docs/examples/ingestion.ipynb

Lines changed: 386 additions & 113 deletions
Large diffs are not rendered by default.

rust/crates/sift_connect/src/grpc/config.rs

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,62 @@ use toml::{Table, Value};
44
/// The expected name of the config file.
55
pub const SIFT_CONFIG_NAME: &str = "sift.toml";
66

7-
/// Specifies source of credentials. If `Profile` is used, then the provided string will be used to
8-
/// query the corresponding table from [`SIFT_CONFIG_NAME`] located at
9-
/// [these locations](https://docs.rs/dirs/6.0.0/dirs/fn.config_local_dir.html)
10-
/// depending on your operating system. If `None` is provided, then the top-level table is used.
7+
/// Specifies the source of credentials for connecting to Sift.
8+
///
9+
/// Credentials can be provided either directly via `Config` or loaded from a
10+
/// configuration file using `Profile`.
11+
///
12+
/// # Profile-based Credentials
13+
///
14+
/// If `Profile` is used, the provided string will be used to query the corresponding
15+
/// table from [`SIFT_CONFIG_NAME`] located at [these locations](https://docs.rs/dirs/6.0.0/dirs/fn.config_local_dir.html)
16+
/// depending on your operating system. If `None` is provided, then the top-level
17+
/// table is used.
18+
///
19+
/// Example `sift.toml` file:
20+
///
21+
/// ```toml
22+
/// uri = "https://api.siftstack.com"
23+
/// apikey = "default-api-key"
24+
///
25+
/// [production]
26+
/// uri = "https://api.siftstack.com"
27+
/// apikey = "production-api-key"
28+
/// ```
29+
///
30+
/// # Direct Credentials
31+
///
32+
/// The `Config` variant allows you to provide credentials directly without
33+
/// requiring a configuration file.
34+
///
35+
/// # Example
36+
///
37+
/// ```no_run
38+
/// use sift_connect::Credentials;
39+
///
40+
/// // Direct credentials
41+
/// let creds = Credentials::Config {
42+
/// uri: "https://api.siftstack.com".to_string(),
43+
/// apikey: "your-api-key".to_string(),
44+
/// };
45+
///
46+
/// // Profile-based credentials (default profile)
47+
/// let default_profile = Credentials::Profile(None);
48+
///
49+
/// // Profile-based credentials (named profile)
50+
/// let prod_profile = Credentials::Profile(Some("production".to_string()));
51+
/// ```
1152
#[derive(Debug, Clone)]
1253
pub enum Credentials {
54+
/// Load credentials from a named profile in the configuration file.
55+
///
56+
/// If `None`, uses the default (top-level) profile.
1357
Profile(Option<String>),
58+
/// Provide credentials directly.
59+
///
60+
/// Fields:
61+
/// - `uri`: The Sift API endpoint URI
62+
/// - `apikey`: The API key for authentication
1463
Config { uri: String, apikey: String },
1564
}
1665

rust/crates/sift_connect/src/grpc/interceptor.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
use std::str::FromStr;
22
use tonic::{Request, Status, metadata::MetadataValue, service::Interceptor};
33

4+
/// Interceptor that adds authentication headers to gRPC requests.
5+
///
6+
/// This interceptor automatically adds a `Bearer` token authorization header
7+
/// to all outgoing gRPC requests using the provided API key.
8+
///
9+
/// # Example
10+
///
11+
/// ```
12+
/// use sift_connect::grpc::AuthInterceptor;
13+
///
14+
/// let interceptor = AuthInterceptor {
15+
/// apikey: "your-api-key".to_string(),
16+
/// };
17+
/// ```
418
#[derive(Clone)]
519
pub struct AuthInterceptor {
20+
/// The API key to use for authentication.
621
pub apikey: String,
722
}
823

rust/crates/sift_connect/src/grpc/mod.rs

Lines changed: 216 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,52 @@ pub mod interceptor;
1818
pub use interceptor::AuthInterceptor;
1919

2020
/// A pre-configured gRPC channel to conveniently establish a connection to Sift's gRPC API.
21+
///
22+
/// This is a type alias for a gRPC channel that has been configured with authentication
23+
/// via [`AuthInterceptor`]. The channel is lazy and won't actually connect until the
24+
/// first RPC call is made.
25+
///
26+
/// # Example
27+
///
28+
/// ```no_run
29+
/// use sift_connect::{Credentials, SiftChannelBuilder};
30+
/// use std::env;
31+
///
32+
/// let credentials = Credentials::Config {
33+
/// uri: env::var("SIFT_URI").unwrap(),
34+
/// apikey: env::var("SIFT_API_KEY").unwrap(),
35+
/// };
36+
///
37+
/// let channel: sift_connect::SiftChannel = SiftChannelBuilder::new(credentials)
38+
/// .build()
39+
/// .unwrap();
40+
/// ```
2141
pub type SiftChannel = InterceptedService<Channel, AuthInterceptor>;
2242

2343
/// Used to build an instance of [SiftChannel].
44+
///
45+
/// This builder provides a fluent API for configuring a gRPC channel connection
46+
/// to Sift's API. It supports custom credentials, TLS configuration, and HTTP/2
47+
/// keep-alive settings.
48+
///
49+
/// # Example
50+
///
51+
/// ```no_run
52+
/// use sift_connect::{Credentials, SiftChannelBuilder};
53+
/// use std::env;
54+
/// use std::time::Duration;
55+
///
56+
/// let credentials = Credentials::Config {
57+
/// uri: env::var("SIFT_URI").unwrap(),
58+
/// apikey: env::var("SIFT_API_KEY").unwrap(),
59+
/// };
60+
///
61+
/// let channel = SiftChannelBuilder::new(credentials)
62+
/// .use_tls(true)
63+
/// .keep_alive_timeout(Duration::from_secs(30))
64+
/// .build()
65+
/// .unwrap();
66+
/// ```
2467
pub struct SiftChannelBuilder {
2568
credentials: Credentials,
2669
use_tls: bool,
@@ -32,6 +75,30 @@ pub struct SiftChannelBuilder {
3275

3376
impl SiftChannelBuilder {
3477
/// Initializes a new [SiftChannelBuilder] with sane defaults.
78+
///
79+
/// Default settings:
80+
/// - TLS enabled
81+
/// - Keep-alive while idle enabled
82+
/// - Keep-alive timeout: 20 seconds
83+
/// - Keep-alive interval: 20 seconds
84+
/// - User agent: crate name and version
85+
///
86+
/// # Arguments
87+
///
88+
/// * `credentials` - The credentials to use for authentication
89+
///
90+
/// # Example
91+
///
92+
/// ```no_run
93+
/// use sift_connect::{Credentials, SiftChannelBuilder};
94+
///
95+
/// let credentials = Credentials::Config {
96+
/// uri: "https://api.siftstack.com".to_string(),
97+
/// apikey: "your-api-key".to_string(),
98+
/// };
99+
///
100+
/// let builder = SiftChannelBuilder::new(credentials);
101+
/// ```
35102
pub fn new(credentials: Credentials) -> Self {
36103
let crate_name = env!("CARGO_PKG_NAME");
37104
let crate_version = env!("CARGO_PKG_VERSION");
@@ -47,8 +114,37 @@ impl SiftChannelBuilder {
47114
}
48115
}
49116

50-
/// Consume [SiftChannelBuilder] and return a [SiftChannel]. The [SiftChannel] is lazy and
51-
/// won't actually connect to Sift until the first RPC is made.
117+
/// Consume [SiftChannelBuilder] and return a [SiftChannel].
118+
///
119+
/// The [SiftChannel] is lazy and won't actually connect to Sift until the first
120+
/// RPC is made. This allows you to create the channel early without incurring
121+
/// connection overhead until it's needed.
122+
///
123+
/// # Returns
124+
///
125+
/// A configured [SiftChannel] ready for use with gRPC clients.
126+
///
127+
/// # Errors
128+
///
129+
/// Returns an error if:
130+
/// - The URI is invalid
131+
/// - Credentials cannot be loaded (for profile-based credentials)
132+
/// - TLS configuration fails
133+
///
134+
/// # Example
135+
///
136+
/// ```no_run
137+
/// use sift_connect::{Credentials, SiftChannelBuilder};
138+
///
139+
/// let credentials = Credentials::Config {
140+
/// uri: "https://api.siftstack.com".to_string(),
141+
/// apikey: "your-api-key".to_string(),
142+
/// };
143+
///
144+
/// let channel = SiftChannelBuilder::new(credentials)
145+
/// .build()
146+
/// .expect("failed to create channel");
147+
/// ```
52148
pub fn build(self) -> Result<SiftChannel> {
53149
let config::SiftChannelConfig { uri, apikey } =
54150
config::SiftChannelConfig::try_from(self.credentials)?;
@@ -81,41 +177,151 @@ impl SiftChannelBuilder {
81177
Ok(intercepted_channel)
82178
}
83179

84-
/// Override the default user-agent which is the name of the crate. Do note that the
85-
/// application firewall is sensitive to certain user-agents so if you experience any issues
86-
/// connecting to Sift, please notify the team to ascertain if it's related to a bad
87-
/// user-agent.
180+
/// Override the default user-agent which is the name of the crate.
181+
///
182+
/// The default user-agent is set to `{crate_name}/{crate_version}`. This method
183+
/// allows you to customize it.
184+
///
185+
/// # Note
186+
///
187+
/// The application firewall is sensitive to certain user-agents. If you experience
188+
/// any issues connecting to Sift, please notify the team to ascertain if it's related
189+
/// to a bad user-agent.
190+
///
191+
/// # Arguments
192+
///
193+
/// * `user_agent` - The custom user-agent string to use
194+
///
195+
/// # Example
196+
///
197+
/// ```no_run
198+
/// use sift_connect::{Credentials, SiftChannelBuilder};
199+
///
200+
/// let credentials = Credentials::Config {
201+
/// uri: "https://api.siftstack.com".to_string(),
202+
/// apikey: "your-api-key".to_string(),
203+
/// };
204+
///
205+
/// let builder = SiftChannelBuilder::new(credentials)
206+
/// .user_agent("MyApp/1.0");
207+
/// ```
88208
pub fn user_agent<S: AsRef<str>>(mut self, user_agent: S) -> Self {
89209
self.user_agent = user_agent.as_ref().to_string();
90210
self
91211
}
92212

93-
/// Enables/disables TLS. In production, TLS should only ever be enabled. For mocking/testing
213+
/// Enables or disables TLS.
214+
///
215+
/// # Warning
216+
///
217+
/// In production, TLS should only ever be enabled. For mocking/testing
94218
/// purposes, TLS may be disabled.
219+
///
220+
/// # Arguments
221+
///
222+
/// * `use_tls` - Whether to enable TLS encryption
223+
///
224+
/// # Example
225+
///
226+
/// ```no_run
227+
/// use sift_connect::{Credentials, SiftChannelBuilder};
228+
///
229+
/// let credentials = Credentials::Config {
230+
/// uri: "https://api.siftstack.com".to_string(),
231+
/// apikey: "your-api-key".to_string(),
232+
/// };
233+
///
234+
/// // Production use - TLS enabled (default)
235+
/// let builder = SiftChannelBuilder::new(credentials.clone())
236+
/// .use_tls(true);
237+
///
238+
/// // Testing use - TLS disabled
239+
/// let test_builder = SiftChannelBuilder::new(credentials)
240+
/// .use_tls(false);
241+
/// ```
95242
pub fn use_tls(mut self, use_tls: bool) -> Self {
96243
self.use_tls = use_tls;
97244
self
98245
}
99246

100-
/// See [`hyper documentation`].
247+
/// Configures whether to send keep-alive pings while the connection is idle.
248+
///
249+
/// See [`hyper documentation`] for detailed information.
101250
///
102251
/// [`hyper documentation`]: https://docs.rs/hyper/latest/hyper/client/conn/http2/struct.Builder.html#method.keep_alive_while_idle
252+
///
253+
/// # Arguments
254+
///
255+
/// * `keep_alive_while_idle` - Whether to send keep-alive pings while idle
256+
///
257+
/// # Example
258+
///
259+
/// ```no_run
260+
/// use sift_connect::{Credentials, SiftChannelBuilder};
261+
///
262+
/// # let credentials = Credentials::Config {
263+
/// # uri: "https://api.siftstack.com".to_string(),
264+
/// # apikey: "your-api-key".to_string(),
265+
/// # };
266+
/// let builder = SiftChannelBuilder::new(credentials)
267+
/// .keep_alive_while_idle(true);
268+
/// ```
103269
pub fn keep_alive_while_idle(mut self, keep_alive_while_idle: bool) -> Self {
104270
self.keep_alive_while_idle = keep_alive_while_idle;
105271
self
106272
}
107273

108-
/// See [`hyper documentation`].
274+
/// Configures the timeout for keep-alive pings.
275+
///
276+
/// See [`hyper documentation`] for detailed information.
109277
///
110278
/// [`hyper documentation`]: https://docs.rs/hyper/latest/hyper/client/conn/http2/struct.Builder.html#method.keep_alive_timeout
279+
///
280+
/// # Arguments
281+
///
282+
/// * `keep_alive_timeout` - The timeout duration for keep-alive pings
283+
///
284+
/// # Example
285+
///
286+
/// ```no_run
287+
/// use sift_connect::{Credentials, SiftChannelBuilder};
288+
/// use std::time::Duration;
289+
///
290+
/// # let credentials = Credentials::Config {
291+
/// # uri: "https://api.siftstack.com".to_string(),
292+
/// # apikey: "your-api-key".to_string(),
293+
/// # };
294+
/// let builder = SiftChannelBuilder::new(credentials)
295+
/// .keep_alive_timeout(Duration::from_secs(30));
296+
/// ```
111297
pub fn keep_alive_timeout(mut self, keep_alive_timeout: Duration) -> Self {
112298
self.keep_alive_timeout = keep_alive_timeout;
113299
self
114300
}
115301

116-
/// See [`hyper documentation`].
302+
/// Configures the interval between keep-alive pings.
303+
///
304+
/// See [`hyper documentation`] for detailed information.
117305
///
118306
/// [`hyper documentation`]: https://docs.rs/hyper/latest/hyper/client/conn/http2/struct.Builder.html#method.keep_alive_interval
307+
///
308+
/// # Arguments
309+
///
310+
/// * `keep_alive_interval` - The interval duration between keep-alive pings
311+
///
312+
/// # Example
313+
///
314+
/// ```no_run
315+
/// use sift_connect::{Credentials, SiftChannelBuilder};
316+
/// use std::time::Duration;
317+
///
318+
/// # let credentials = Credentials::Config {
319+
/// # uri: "https://api.siftstack.com".to_string(),
320+
/// # apikey: "your-api-key".to_string(),
321+
/// # };
322+
/// let builder = SiftChannelBuilder::new(credentials)
323+
/// .keep_alive_interval(Duration::from_secs(30));
324+
/// ```
119325
pub fn keep_alive_interval(mut self, keep_alive_interval: Duration) -> Self {
120326
self.keep_alive_interval = keep_alive_interval;
121327
self

0 commit comments

Comments
 (0)