1use std::error::Error;
14use std::fmt;
15
16use async_trait::async_trait;
17use rusoto_core::credential::ProvideAwsCredentials;
18use rusoto_core::region;
19use rusoto_core::request::{BufferedHttpResponse, DispatchSignedRequest};
20use rusoto_core::{Client, RusotoError};
21
22use rusoto_core::proto;
23use rusoto_core::request::HttpResponse;
24use rusoto_core::signature::SignedRequest;
25#[allow(unused_imports)]
26use serde::{Deserialize, Serialize};
27
28impl QldbSessionClient {
29 fn new_signed_request(&self, http_method: &str, request_uri: &str) -> SignedRequest {
30 let mut request = SignedRequest::new(http_method, "qldb", &self.region, request_uri);
31 request.set_endpoint_prefix("session.qldb".to_string());
32
33 request.set_content_type("application/x-amz-json-1.0".to_owned());
34
35 request
36 }
37
38 async fn sign_and_dispatch<E>(
39 &self,
40 request: SignedRequest,
41 from_response: fn(BufferedHttpResponse) -> RusotoError<E>,
42 ) -> Result<HttpResponse, RusotoError<E>> {
43 let mut response = self.client.sign_and_dispatch(request).await?;
44 if !response.status.is_success() {
45 let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
46 return Err(from_response(response));
47 }
48
49 Ok(response)
50 }
51}
52
53use serde_json;
54#[derive(Clone, Debug, Default, PartialEq, Serialize)]
56#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
57pub struct AbortTransactionRequest {}
58
59#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
61#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
62pub struct AbortTransactionResult {}
63
64#[derive(Clone, Debug, Default, PartialEq, Serialize)]
66#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
67pub struct CommitTransactionRequest {
68 #[serde(rename = "CommitDigest")]
70 #[serde(
71 deserialize_with = "::rusoto_core::serialization::SerdeBlob::deserialize_blob",
72 serialize_with = "::rusoto_core::serialization::SerdeBlob::serialize_blob",
73 default
74 )]
75 pub commit_digest: bytes::Bytes,
76 #[serde(rename = "TransactionId")]
78 pub transaction_id: String,
79}
80
81#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
83#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
84pub struct CommitTransactionResult {
85 #[serde(rename = "CommitDigest")]
87 #[serde(
88 deserialize_with = "::rusoto_core::serialization::SerdeBlob::deserialize_blob",
89 serialize_with = "::rusoto_core::serialization::SerdeBlob::serialize_blob",
90 default
91 )]
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub commit_digest: Option<bytes::Bytes>,
94 #[serde(rename = "TransactionId")]
96 #[serde(skip_serializing_if = "Option::is_none")]
97 pub transaction_id: Option<String>,
98}
99
100#[derive(Clone, Debug, Default, PartialEq, Serialize)]
102#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
103pub struct EndSessionRequest {}
104
105#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
107#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
108pub struct EndSessionResult {}
109
110#[derive(Clone, Debug, Default, PartialEq, Serialize)]
112#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
113pub struct ExecuteStatementRequest {
114 #[serde(rename = "Parameters")]
116 #[serde(skip_serializing_if = "Option::is_none")]
117 pub parameters: Option<Vec<ValueHolder>>,
118 #[serde(rename = "Statement")]
120 pub statement: String,
121 #[serde(rename = "TransactionId")]
123 pub transaction_id: String,
124}
125
126#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
128#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
129pub struct ExecuteStatementResult {
130 #[serde(rename = "FirstPage")]
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub first_page: Option<Page>,
134}
135
136#[derive(Clone, Debug, Default, PartialEq, Serialize)]
138#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
139pub struct FetchPageRequest {
140 #[serde(rename = "NextPageToken")]
142 pub next_page_token: String,
143 #[serde(rename = "TransactionId")]
145 pub transaction_id: String,
146}
147
148#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
150#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
151pub struct FetchPageResult {
152 #[serde(rename = "Page")]
154 #[serde(skip_serializing_if = "Option::is_none")]
155 pub page: Option<Page>,
156}
157
158#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
160#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
161pub struct Page {
162 #[serde(rename = "NextPageToken")]
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub next_page_token: Option<String>,
166 #[serde(rename = "Values")]
168 #[serde(skip_serializing_if = "Option::is_none")]
169 pub values: Option<Vec<ValueHolder>>,
170}
171
172#[derive(Clone, Debug, Default, PartialEq, Serialize)]
173#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
174pub struct SendCommandRequest {
175 #[serde(rename = "AbortTransaction")]
177 #[serde(skip_serializing_if = "Option::is_none")]
178 pub abort_transaction: Option<AbortTransactionRequest>,
179 #[serde(rename = "CommitTransaction")]
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub commit_transaction: Option<CommitTransactionRequest>,
183 #[serde(rename = "EndSession")]
185 #[serde(skip_serializing_if = "Option::is_none")]
186 pub end_session: Option<EndSessionRequest>,
187 #[serde(rename = "ExecuteStatement")]
189 #[serde(skip_serializing_if = "Option::is_none")]
190 pub execute_statement: Option<ExecuteStatementRequest>,
191 #[serde(rename = "FetchPage")]
193 #[serde(skip_serializing_if = "Option::is_none")]
194 pub fetch_page: Option<FetchPageRequest>,
195 #[serde(rename = "SessionToken")]
197 #[serde(skip_serializing_if = "Option::is_none")]
198 pub session_token: Option<String>,
199 #[serde(rename = "StartSession")]
201 #[serde(skip_serializing_if = "Option::is_none")]
202 pub start_session: Option<StartSessionRequest>,
203 #[serde(rename = "StartTransaction")]
205 #[serde(skip_serializing_if = "Option::is_none")]
206 pub start_transaction: Option<StartTransactionRequest>,
207}
208
209#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
210#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
211pub struct SendCommandResult {
212 #[serde(rename = "AbortTransaction")]
214 #[serde(skip_serializing_if = "Option::is_none")]
215 pub abort_transaction: Option<AbortTransactionResult>,
216 #[serde(rename = "CommitTransaction")]
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub commit_transaction: Option<CommitTransactionResult>,
220 #[serde(rename = "EndSession")]
222 #[serde(skip_serializing_if = "Option::is_none")]
223 pub end_session: Option<EndSessionResult>,
224 #[serde(rename = "ExecuteStatement")]
226 #[serde(skip_serializing_if = "Option::is_none")]
227 pub execute_statement: Option<ExecuteStatementResult>,
228 #[serde(rename = "FetchPage")]
230 #[serde(skip_serializing_if = "Option::is_none")]
231 pub fetch_page: Option<FetchPageResult>,
232 #[serde(rename = "StartSession")]
234 #[serde(skip_serializing_if = "Option::is_none")]
235 pub start_session: Option<StartSessionResult>,
236 #[serde(rename = "StartTransaction")]
238 #[serde(skip_serializing_if = "Option::is_none")]
239 pub start_transaction: Option<StartTransactionResult>,
240}
241
242#[derive(Clone, Debug, Default, PartialEq, Serialize)]
244#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
245pub struct StartSessionRequest {
246 #[serde(rename = "LedgerName")]
248 pub ledger_name: String,
249}
250
251#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
253#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
254pub struct StartSessionResult {
255 #[serde(rename = "SessionToken")]
257 #[serde(skip_serializing_if = "Option::is_none")]
258 pub session_token: Option<String>,
259}
260
261#[derive(Clone, Debug, Default, PartialEq, Serialize)]
263#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))]
264pub struct StartTransactionRequest {}
265
266#[derive(Clone, Debug, Default, Deserialize, PartialEq)]
268#[cfg_attr(any(test, feature = "serialize_structs"), derive(Serialize))]
269pub struct StartTransactionResult {
270 #[serde(rename = "TransactionId")]
272 #[serde(skip_serializing_if = "Option::is_none")]
273 pub transaction_id: Option<String>,
274}
275
276#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
278pub struct ValueHolder {
279 #[serde(rename = "IonBinary")]
281 #[serde(
282 deserialize_with = "::rusoto_core::serialization::SerdeBlob::deserialize_blob",
283 serialize_with = "::rusoto_core::serialization::SerdeBlob::serialize_blob",
284 default
285 )]
286 #[serde(skip_serializing_if = "Option::is_none")]
287 pub ion_binary: Option<bytes::Bytes>,
288 #[serde(rename = "IonText")]
290 #[serde(skip_serializing_if = "Option::is_none")]
291 pub ion_text: Option<String>,
292}
293
294#[derive(Debug, PartialEq)]
296pub enum SendCommandError {
297 BadRequest(String),
299 InvalidSession(String),
301 LimitExceeded(String),
303 OccConflict(String),
305 RateExceeded(String),
307}
308
309impl SendCommandError {
310 pub fn from_response(res: BufferedHttpResponse) -> RusotoError<SendCommandError> {
311 if let Some(err) = proto::json::Error::parse(&res) {
312 match err.typ.as_str() {
313 "BadRequestException" => {
314 return RusotoError::Service(SendCommandError::BadRequest(err.msg))
315 }
316 "InvalidSessionException" => {
317 return RusotoError::Service(SendCommandError::InvalidSession(err.msg))
318 }
319 "LimitExceededException" => {
320 return RusotoError::Service(SendCommandError::LimitExceeded(err.msg))
321 }
322 "OccConflictException" => {
323 return RusotoError::Service(SendCommandError::OccConflict(err.msg))
324 }
325 "RateExceededException" => {
326 return RusotoError::Service(SendCommandError::RateExceeded(err.msg))
327 }
328 "ValidationException" => return RusotoError::Validation(err.msg),
329 _ => {}
330 }
331 }
332 RusotoError::Unknown(res)
333 }
334}
335impl fmt::Display for SendCommandError {
336 #[allow(unused_variables)]
337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
338 match *self {
339 SendCommandError::BadRequest(ref cause) => write!(f, "{}", cause),
340 SendCommandError::InvalidSession(ref cause) => write!(f, "{}", cause),
341 SendCommandError::LimitExceeded(ref cause) => write!(f, "{}", cause),
342 SendCommandError::OccConflict(ref cause) => write!(f, "{}", cause),
343 SendCommandError::RateExceeded(ref cause) => write!(f, "{}", cause),
344 }
345 }
346}
347impl Error for SendCommandError {}
348#[async_trait]
350pub trait QldbSession {
351 async fn send_command(
353 &self,
354 input: SendCommandRequest,
355 ) -> Result<SendCommandResult, RusotoError<SendCommandError>>;
356}
357#[derive(Clone)]
359pub struct QldbSessionClient {
360 client: Client,
361 region: region::Region,
362}
363
364impl QldbSessionClient {
365 pub fn new(region: region::Region) -> QldbSessionClient {
369 QldbSessionClient {
370 client: Client::shared(),
371 region,
372 }
373 }
374
375 pub fn new_with<P, D>(
376 request_dispatcher: D,
377 credentials_provider: P,
378 region: region::Region,
379 ) -> QldbSessionClient
380 where
381 P: ProvideAwsCredentials + Send + Sync + 'static,
382 D: DispatchSignedRequest + Send + Sync + 'static,
383 {
384 QldbSessionClient {
385 client: Client::new_with(credentials_provider, request_dispatcher),
386 region,
387 }
388 }
389
390 pub fn new_with_client(client: Client, region: region::Region) -> QldbSessionClient {
391 QldbSessionClient { client, region }
392 }
393}
394
395#[async_trait]
396impl QldbSession for QldbSessionClient {
397 async fn send_command(
399 &self,
400 input: SendCommandRequest,
401 ) -> Result<SendCommandResult, RusotoError<SendCommandError>> {
402 let mut request = self.new_signed_request("POST", "/");
403 request.add_header("x-amz-target", "QLDBSession.SendCommand");
404 let encoded = serde_json::to_string(&input).unwrap();
405 request.set_payload(Some(encoded));
406
407 let response = self
408 .sign_and_dispatch(request, SendCommandError::from_response)
409 .await?;
410 let mut response = response;
411 let response = response.buffer().await.map_err(RusotoError::HttpDispatch)?;
412 proto::json::ResponsePayload::new(&response).deserialize::<SendCommandResult, _>()
413 }
414}