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