use crate::{Client, EngineError, data::DynamoDbClient};
use rusoto_core::RusotoError;
use rusoto_dynamodb::{BatchWriteItemError, BatchWriteItemInput, DynamoDb};
use std::{thread, time};
use rand::Rng;
const RETRY_BASE: u64 = 500;
const MAX_INTERVAL_LIMIT: u64 = 60_000;
const MAX_ELAPSED_TIME_MILLIS: u64 = 600_000;
pub fn get_date_time() -> String {
return chrono::Utc::now()
.format("%Y-%m-%dT%H:%M:%S.%3fZ")
.to_string();
}
pub fn get_table_name() -> Result<String, EngineError> {
match std::env::var("AWS_DYNAMODB_TABLE") {
Ok(val) => return Ok(val),
_ => {
return Err(EngineError::Manager(
"Missing AWS_DYNAMODB_TABLE env var".to_owned(),
))
}
}
}
pub fn make_hash(client: &Client) -> String {
format!(
"bot_id:{}#channel_id:{}#user_id:{}",
client.bot_id, client.channel_id, client.user_id
)
}
pub fn make_range(args: &[&str]) -> String {
let mut res = "".to_owned();
for arg in args.iter() {
if res.len() > 0 {
res = res + "#";
}
res = res + arg.to_owned();
}
res.to_owned()
}
pub fn execute_batch_write_query(db: &mut DynamoDbClient, input: BatchWriteItemInput) -> Result<(), RusotoError<BatchWriteItemError>> {
let mut retry_times = 1;
let mut rng = rand::thread_rng();
let now = time::Instant::now();
loop {
match db.runtime.block_on(db.client.batch_write_item(input.clone())) {
Ok(_) => return Ok(()),
Err(RusotoError::Service(BatchWriteItemError::ProvisionedThroughputExceeded(err))) => {
let interval = std::cmp::min(MAX_INTERVAL_LIMIT,RETRY_BASE * 2 * retry_times);
let interval_jitter = rng.gen_range(0,interval);
let duration = time::Duration::from_millis(interval_jitter);
thread::sleep(duration);
if now.elapsed() >= time::Duration::from_millis(MAX_ELAPSED_TIME_MILLIS) {
return Err(RusotoError::Service(BatchWriteItemError::ProvisionedThroughputExceeded(err)))
}
},
Err(err) => return Err(err)
}
retry_times += 1;
}
}