1#[cfg(feature = "_hidden")]
2use crate::client::Connect;
3use crate::{
4 api::{AccountClient, BaseClient, BasinClient},
5 error::{AppendError, ReadError, RequestError},
6 producer::{Producer, ProducerConfig},
7 session::{
8 self, AppendSession, AppendSessionConfig, ReadSession, ReadSessionError, StreamHeaders,
9 },
10 types::{
11 AccessTokenId, AccessTokenInfo, AppendAck, AppendInput, BasinConfig, BasinInfo, BasinName,
12 CreateBasinInput, CreateStreamInput, DeleteBasinInput, DeleteStreamInput, EncryptionKey,
13 EnsureBasinInput, EnsureOutput, EnsureStreamInput, GetAccountMetricsInput,
14 GetBasinMetricsInput, GetStreamMetricsInput, IssueAccessTokenInput, ListAccessTokensInput,
15 ListAllAccessTokensInput, ListAllBasinsInput, ListAllStreamsInput, ListBasinsInput,
16 ListStreamsInput, LocationInfo, LocationName, Metric, Page, ReadBatch, ReadInput,
17 ReadSessionConfig, ReconfigureBasinInput, ReconfigureStreamInput, S2Config, StreamConfig,
18 StreamInfo, StreamName, StreamPosition, Streaming,
19 },
20};
21
22#[derive(Debug, Clone)]
23pub struct S2 {
25 client: AccountClient,
26}
27
28impl S2 {
29 pub fn new(config: S2Config) -> Result<Self, RequestError> {
31 let base_client = BaseClient::init(&config)?;
32 Ok(Self {
33 client: AccountClient::init(config, base_client),
34 })
35 }
36
37 #[doc(hidden)]
38 #[cfg(feature = "_hidden")]
39 pub fn new_with_connector<C>(config: S2Config, connector: C) -> Result<Self, RequestError>
40 where
41 C: Connect + Clone + Send + Sync + 'static,
42 {
43 let base_client = BaseClient::init_with_connector(&config, connector)?;
44 Ok(Self {
45 client: AccountClient::init(config, base_client),
46 })
47 }
48
49 pub fn basin(&self, name: BasinName) -> S2Basin {
51 S2Basin {
52 client: self.client.basin_client(name),
53 }
54 }
55
56 pub async fn list_basins(
60 &self,
61 input: ListBasinsInput,
62 ) -> Result<Page<BasinInfo>, RequestError> {
63 let response = self.client.list_basins(input.into()).await?;
64 Ok(Page::new(
65 response
66 .basins
67 .into_iter()
68 .map(TryInto::try_into)
69 .collect::<Result<Vec<_>, _>>()?,
70 response.has_more,
71 ))
72 }
73
74 pub fn list_all_basins(&self, input: ListAllBasinsInput) -> Streaming<BasinInfo> {
76 let s2 = self.clone();
77 let prefix = input.prefix;
78 let start_after = input.start_after;
79 let include_deleted = input.include_deleted;
80 let mut input = ListBasinsInput::new()
81 .with_prefix(prefix)
82 .with_start_after(start_after);
83 Box::pin(async_stream::try_stream! {
84 loop {
85 let page = s2.list_basins(input.clone()).await?;
86 let start_after = page.values.last().map(|info| info.name.clone().into());
87
88 for info in page.values {
89 if !include_deleted && info.deleted_at.is_some() {
90 continue;
91 }
92 yield info;
93 }
94
95 if page.has_more && let Some(start_after) = start_after {
96 input = input.with_start_after(start_after);
97 } else {
98 break;
99 }
100 }
101 })
102 }
103
104 pub async fn create_basin(&self, input: CreateBasinInput) -> Result<BasinInfo, RequestError> {
106 let (request, idempotency_token) = input.into();
107 let info = self.client.create_basin(request, idempotency_token).await?;
108 Ok(info.try_into()?)
109 }
110
111 pub async fn ensure_basin(
119 &self,
120 input: EnsureBasinInput,
121 ) -> Result<EnsureOutput<BasinInfo>, RequestError> {
122 let (name, request) = input.into();
123 Ok(self
124 .client
125 .ensure_basin(name, request)
126 .await?
127 .try_map(BasinInfo::try_from)?
128 .into())
129 }
130
131 pub async fn get_basin_config(&self, name: BasinName) -> Result<BasinConfig, RequestError> {
133 let config = self.client.get_basin_config(name).await?;
134 Ok(config.into())
135 }
136
137 #[doc(hidden)]
138 #[cfg(feature = "_hidden")]
139 pub async fn get_basin_config_api(
140 &self,
141 name: BasinName,
142 ) -> Result<s2_api::v1::config::BasinConfig, RequestError> {
143 Ok(self.client.get_basin_config(name).await?)
144 }
145
146 pub async fn delete_basin(&self, input: DeleteBasinInput) -> Result<(), RequestError> {
148 Ok(self
149 .client
150 .delete_basin(input.name, input.ignore_not_found)
151 .await?)
152 }
153
154 pub async fn reconfigure_basin(
156 &self,
157 input: ReconfigureBasinInput,
158 ) -> Result<BasinConfig, RequestError> {
159 let config = self
160 .client
161 .reconfigure_basin(input.name, input.config.into())
162 .await?;
163 Ok(config.into())
164 }
165
166 pub async fn list_access_tokens(
170 &self,
171 input: ListAccessTokensInput,
172 ) -> Result<Page<AccessTokenInfo>, RequestError> {
173 let response = self.client.list_access_tokens(input.into()).await?;
174 Ok(Page::new(
175 response
176 .access_tokens
177 .into_iter()
178 .map(TryInto::try_into)
179 .collect::<Result<Vec<_>, _>>()?,
180 response.has_more,
181 ))
182 }
183
184 #[doc(hidden)]
185 #[cfg(feature = "_hidden")]
186 pub async fn list_access_tokens_api(
187 &self,
188 input: ListAccessTokensInput,
189 ) -> Result<s2_api::v1::access::ListAccessTokensResponse, RequestError> {
190 Ok(self.client.list_access_tokens(input.into()).await?)
191 }
192
193 pub fn list_all_access_tokens(
195 &self,
196 input: ListAllAccessTokensInput,
197 ) -> Streaming<AccessTokenInfo> {
198 let s2 = self.clone();
199 let prefix = input.prefix;
200 let start_after = input.start_after;
201 let mut input = ListAccessTokensInput::new()
202 .with_prefix(prefix)
203 .with_start_after(start_after);
204 Box::pin(async_stream::try_stream! {
205 loop {
206 let page = s2.list_access_tokens(input.clone()).await?;
207
208 let start_after = page.values.last().map(|info| info.id.clone().into());
209 for info in page.values {
210 yield info;
211 }
212
213 if page.has_more && let Some(start_after) = start_after {
214 input = input.with_start_after(start_after);
215 } else {
216 break;
217 }
218 }
219 })
220 }
221
222 pub async fn issue_access_token(
224 &self,
225 input: IssueAccessTokenInput,
226 ) -> Result<String, RequestError> {
227 let response = self.client.issue_access_token(input.into()).await?;
228 Ok(response.access_token)
229 }
230
231 pub async fn revoke_access_token(&self, id: AccessTokenId) -> Result<(), RequestError> {
233 Ok(self.client.revoke_access_token(id).await?)
234 }
235
236 pub async fn list_locations(&self) -> Result<Vec<LocationInfo>, RequestError> {
238 let response = self.client.list_locations().await?;
239 Ok(response.into_iter().map(Into::into).collect())
240 }
241
242 pub async fn get_default_location(&self) -> Result<LocationInfo, RequestError> {
244 Ok(self.client.get_default_location().await?.into())
245 }
246
247 pub async fn set_default_location(
249 &self,
250 location: LocationName,
251 ) -> Result<LocationInfo, RequestError> {
252 Ok(self.client.set_default_location(location).await?.into())
253 }
254
255 pub async fn get_account_metrics(
257 &self,
258 input: GetAccountMetricsInput,
259 ) -> Result<Vec<Metric>, RequestError> {
260 let response = self.client.get_account_metrics(input.into()).await?;
261 Ok(response.values.into_iter().map(Into::into).collect())
262 }
263
264 pub async fn get_basin_metrics(
266 &self,
267 input: GetBasinMetricsInput,
268 ) -> Result<Vec<Metric>, RequestError> {
269 let (name, request) = input.into();
270 let response = self.client.get_basin_metrics(name, request).await?;
271 Ok(response.values.into_iter().map(Into::into).collect())
272 }
273
274 pub async fn get_stream_metrics(
276 &self,
277 input: GetStreamMetricsInput,
278 ) -> Result<Vec<Metric>, RequestError> {
279 let (basin_name, stream_name, request) = input.into();
280 let response = self
281 .client
282 .get_stream_metrics(basin_name, stream_name, request)
283 .await?;
284 Ok(response.values.into_iter().map(Into::into).collect())
285 }
286}
287
288#[derive(Debug, Clone)]
289pub struct S2Basin {
293 client: BasinClient,
294}
295
296impl S2Basin {
297 pub fn stream(&self, name: StreamName) -> S2Stream {
299 S2Stream {
300 client: self.client.clone(),
301 name,
302 encryption: None,
303 }
304 }
305
306 pub async fn list_streams(
310 &self,
311 input: ListStreamsInput,
312 ) -> Result<Page<StreamInfo>, RequestError> {
313 let response = self.client.list_streams(input.into()).await?;
314 Ok(Page::new(
315 response
316 .streams
317 .into_iter()
318 .map(TryInto::try_into)
319 .collect::<Result<Vec<_>, _>>()?,
320 response.has_more,
321 ))
322 }
323
324 pub fn list_all_streams(&self, input: ListAllStreamsInput) -> Streaming<StreamInfo> {
326 let basin = self.clone();
327 let prefix = input.prefix;
328 let start_after = input.start_after;
329 let include_deleted = input.include_deleted;
330 let mut input = ListStreamsInput::new()
331 .with_prefix(prefix)
332 .with_start_after(start_after);
333 Box::pin(async_stream::try_stream! {
334 loop {
335 let page = basin.list_streams(input.clone()).await?;
336 let start_after = page.values.last().map(|info| info.name.clone().into());
337
338 for info in page.values {
339 if !include_deleted && info.deleted_at.is_some() {
340 continue;
341 }
342 yield info;
343 }
344
345 if page.has_more && let Some(start_after) = start_after {
346 input = input.with_start_after(start_after);
347 } else {
348 break;
349 }
350 }
351 })
352 }
353
354 pub async fn create_stream(
356 &self,
357 input: CreateStreamInput,
358 ) -> Result<StreamInfo, RequestError> {
359 let (request, idempotency_token) = input.into();
360 let info = self
361 .client
362 .create_stream(request, idempotency_token)
363 .await?;
364 Ok(info.try_into()?)
365 }
366
367 pub async fn ensure_stream(
375 &self,
376 input: EnsureStreamInput,
377 ) -> Result<EnsureOutput<StreamInfo>, RequestError> {
378 let (name, config) = input.into();
379 Ok(self
380 .client
381 .ensure_stream(name, config)
382 .await?
383 .try_map(StreamInfo::try_from)?
384 .into())
385 }
386
387 pub async fn get_stream_config(&self, name: StreamName) -> Result<StreamConfig, RequestError> {
389 let config = self.client.get_stream_config(name).await?;
390 Ok(config.into())
391 }
392
393 #[doc(hidden)]
394 #[cfg(feature = "_hidden")]
395 pub async fn get_stream_config_api(
396 &self,
397 name: StreamName,
398 ) -> Result<s2_api::v1::config::StreamConfig, RequestError> {
399 Ok(self.client.get_stream_config(name).await?)
400 }
401
402 pub async fn delete_stream(&self, input: DeleteStreamInput) -> Result<(), RequestError> {
404 Ok(self
405 .client
406 .delete_stream(input.name, input.ignore_not_found)
407 .await?)
408 }
409
410 pub async fn reconfigure_stream(
412 &self,
413 input: ReconfigureStreamInput,
414 ) -> Result<StreamConfig, RequestError> {
415 let config = self
416 .client
417 .reconfigure_stream(input.name, input.config.into())
418 .await?;
419 Ok(config.into())
420 }
421}
422
423#[derive(Debug, Clone)]
424pub struct S2Stream {
428 client: BasinClient,
429 name: StreamName,
430 encryption: Option<EncryptionKey>,
431}
432
433impl S2Stream {
434 pub fn with_encryption_key(self, encryption: EncryptionKey) -> Self {
436 Self {
437 encryption: Some(encryption),
438 ..self
439 }
440 }
441
442 fn headers(&self, stream_config: Option<&StreamConfig>) -> StreamHeaders {
443 StreamHeaders {
444 encryption: self.encryption.clone(),
445 stream_config: stream_config.cloned().map(Into::into),
446 }
447 }
448
449 pub async fn check_tail(&self) -> Result<StreamPosition, ReadError> {
451 let response = self.client.check_tail(&self.name).await?;
452 Ok(response.tail.into())
453 }
454
455 pub async fn append(&self, mut input: AppendInput) -> Result<AppendAck, AppendError> {
457 let stream_config = input
458 .stream_config
459 .take()
460 .map(s2_api::v1::config::StreamConfig::from);
461 let ack = self
462 .client
463 .append(
464 &self.name,
465 input.into(),
466 self.encryption.as_ref(),
467 stream_config.as_ref(),
468 self.client.config.retry.append_retry_policy,
469 )
470 .await?;
471 Ok(ack.into())
472 }
473
474 pub async fn read(&self, input: ReadInput) -> Result<ReadBatch, ReadError> {
476 let stream_config = input
477 .stream_config
478 .map(s2_api::v1::config::StreamConfig::from);
479 let batch = self
480 .client
481 .read(
482 &self.name,
483 input.start.into(),
484 input.stop.into(),
485 self.encryption.as_ref(),
486 stream_config.as_ref(),
487 )
488 .await?;
489 let mut batch = ReadBatch::from_api(batch);
490 if input.ignore_command_records {
491 batch.records.retain(|r| !r.is_command_record());
492 }
493 Ok(batch)
494 }
495
496 pub fn append_session(&self, config: AppendSessionConfig) -> AppendSession {
498 AppendSession::new(
499 self.client.clone(),
500 self.name.clone(),
501 self.headers(config.stream_config()),
502 config,
503 )
504 }
505
506 pub fn producer(&self, config: ProducerConfig) -> Producer {
508 Producer::new(
509 self.client.clone(),
510 self.name.clone(),
511 self.headers(config.stream_config()),
512 config,
513 )
514 }
515
516 pub async fn read_session(
518 &self,
519 input: ReadInput,
520 config: ReadSessionConfig,
521 ) -> Result<ReadSession, ReadSessionError> {
522 session::read_session(
523 self.client.clone(),
524 self.name.clone(),
525 self.headers(input.stream_config.as_ref()),
526 input,
527 config,
528 )
529 .await
530 }
531}