use std::sync::Arc;
use sawtooth_sdk::messages::batch::BatchList;
use url::Url;
use crate::backend::{
BackendClient, BackendClientError, BatchStatuses, SubmitBatches, DEFAULT_TIME_OUT,
};
use crate::rest_api::resources::error::ErrorResponse;
use super::payloads::{BatchStatus, BatchStatusLink, BatchStatusResponse};
pub async fn submit_batches(
response_url: Url,
backend_client: Arc<dyn BackendClient>,
bytes: &[u8],
service_id: Option<String>,
) -> Result<BatchStatusLink, ErrorResponse> {
let batch_list: BatchList = match protobuf::Message::parse_from_bytes(bytes) {
Ok(batch_list) => batch_list,
Err(err) => {
return Err(ErrorResponse::new(
400,
&format!("Protobuf message was badly formatted. {}", err),
));
}
};
backend_client
.submit_batches(SubmitBatches {
batch_list,
response_url,
service_id,
})
.await
.map_err(|err| match err {
BackendClientError::BadRequestError(ref msg) => ErrorResponse::new(400, msg),
BackendClientError::ConnectionError(ref msg) => ErrorResponse::new(503, msg),
BackendClientError::InternalError(ref msg) => ErrorResponse::new(500, msg),
BackendClientError::ResourceTemporarilyUnavailableError(ref msg) => {
ErrorResponse::new(503, msg)
}
})
.map(BatchStatusLink::from)
}
pub async fn get_batch_statuses(
response_url: String,
backend_client: Arc<dyn BackendClient>,
ids: String,
wait: Option<String>,
service_id: Option<String>,
) -> Result<BatchStatusResponse, ErrorResponse> {
let batch_ids = ids.split(',').map(ToString::to_string).collect();
let max_wait_time = (DEFAULT_TIME_OUT * 95) / 100;
let wait = match wait {
Some(wait_time) => {
if wait_time == "false" {
None
} else {
match wait_time.parse::<u32>() {
Ok(wait_time) => {
if wait_time > max_wait_time {
Some(max_wait_time)
} else {
Some(wait_time)
}
}
Err(_) => {
return Err(ErrorResponse::new(
400,
&format!(
"Query wait has invalid value {}. \
It should set to false or a time in seconds to wait for the commit",
wait_time
),
));
}
}
}
}
None => Some(max_wait_time),
};
backend_client
.batch_status(BatchStatuses {
batch_ids,
wait,
service_id,
})
.await
.map_err(|err| match err {
BackendClientError::BadRequestError(ref msg) => ErrorResponse::new(400, msg),
BackendClientError::ConnectionError(ref msg) => ErrorResponse::new(503, msg),
BackendClientError::InternalError(ref msg) => ErrorResponse::new(500, msg),
BackendClientError::ResourceTemporarilyUnavailableError(ref msg) => {
ErrorResponse::new(500, msg)
}
})
.map(|batches| BatchStatusResponse {
data: batches.into_iter().map(BatchStatus::from).collect(),
link: response_url,
})
}