15 changed files with 137 additions and 147 deletions
@ -0,0 +1,13 @@ |
|||||||
|
use tracing_unwrap::ResultExt; |
||||||
|
use crate::constants; |
||||||
|
|
||||||
|
pub fn get_aws_credential() -> (String, String, String) { |
||||||
|
let access_key = crate::env::get(constants::ENV_AWS_ACCESS_KEY) |
||||||
|
.expect_or_log("env not found: AWS_ACCESS_KEY"); |
||||||
|
let secret_key = crate::env::get(constants::ENV_AWS_SECRET_KEY) |
||||||
|
.expect_or_log("env not found: AWS_SECRET_KEY"); |
||||||
|
let region = crate::env::get(constants::ENV_AWS_REGION) |
||||||
|
.expect_or_log("env not found: AWS_REGION"); |
||||||
|
|
||||||
|
(access_key, secret_key, region) |
||||||
|
} |
||||||
@ -0,0 +1,4 @@ |
|||||||
|
pub mod s3; |
||||||
|
pub mod kinesis; |
||||||
|
pub mod parameter_store; |
||||||
|
mod credential; |
||||||
@ -0,0 +1,84 @@ |
|||||||
|
use std::sync::Arc; |
||||||
|
use aws_config::meta::region::RegionProviderChain; |
||||||
|
use aws_credential_types::Credentials; |
||||||
|
use aws_types::region::Region; |
||||||
|
use bytes::Bytes; |
||||||
|
use tokio::sync::OnceCell; |
||||||
|
use tracing::info; |
||||||
|
use crate::model::error::DeviceError; |
||||||
|
|
||||||
|
static AWS_S3_CLIENT: OnceCell<Arc<aws_sdk_s3::Client>> = OnceCell::const_new(); |
||||||
|
|
||||||
|
async fn initialize_data() -> Arc<aws_sdk_s3::Client> { |
||||||
|
let (access_key, secret_key, region) = crate::aws::credential::get_aws_credential(); |
||||||
|
|
||||||
|
let region_provider = RegionProviderChain::default_provider().or_else(Region::new(region)); |
||||||
|
let region = region_provider.region().await.unwrap(); |
||||||
|
|
||||||
|
let credentials = Credentials::from_keys( |
||||||
|
access_key, |
||||||
|
secret_key, |
||||||
|
None, |
||||||
|
); |
||||||
|
|
||||||
|
let config = aws_config::defaults(aws_config::BehaviorVersion::latest()) |
||||||
|
.region(region) |
||||||
|
.credentials_provider(credentials) |
||||||
|
.load() |
||||||
|
.await; |
||||||
|
|
||||||
|
Arc::new(aws_sdk_s3::Client::new(&config)) |
||||||
|
} |
||||||
|
|
||||||
|
async fn get_client() -> Arc<aws_sdk_s3::Client> { |
||||||
|
AWS_S3_CLIENT.get_or_init(initialize_data) |
||||||
|
.await |
||||||
|
.clone() |
||||||
|
} |
||||||
|
|
||||||
|
pub async fn read_file(bucket: &str, key: &str) -> Result<String, DeviceError> { |
||||||
|
let client = get_client().await; |
||||||
|
|
||||||
|
let res = client |
||||||
|
.get_object() |
||||||
|
.bucket(bucket) |
||||||
|
.key(key) |
||||||
|
.send() |
||||||
|
.await?; |
||||||
|
|
||||||
|
let data = res |
||||||
|
.body |
||||||
|
.collect() |
||||||
|
.await?; |
||||||
|
|
||||||
|
let data: Bytes = data.into_bytes(); |
||||||
|
|
||||||
|
if data.is_empty() { |
||||||
|
return Err(DeviceError::GeneralError("length".to_string())) |
||||||
|
} |
||||||
|
|
||||||
|
Ok(String::from_utf8_lossy(&data).into_owned()) |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
use serial_test::serial; |
||||||
|
use crate::constants; |
||||||
|
|
||||||
|
fn setup() { |
||||||
|
crate::env::set(constants::ENV_AWS_ACCESS_KEY, "AKIA32XY6L3KQA4QDIAP"); |
||||||
|
crate::env::set(constants::ENV_AWS_SECRET_KEY, "oZGcPvKUdMh1CmbDy1HM6iHZno8c+Ya/CRxNfeAU"); |
||||||
|
crate::env::set(constants::ENV_AWS_REGION, "ap-northeast-2"); |
||||||
|
} |
||||||
|
|
||||||
|
fn teardown() {} |
||||||
|
|
||||||
|
#[tokio::test] |
||||||
|
#[serial] |
||||||
|
async fn test_read_file() { |
||||||
|
setup(); |
||||||
|
assert!(read_file("apm-bigdata", "flower-device/test.csv").await.is_ok()); |
||||||
|
teardown(); |
||||||
|
} |
||||||
|
} |
||||||
@ -1,52 +0,0 @@ |
|||||||
use std::mem::size_of; |
|
||||||
use serde::{Deserialize, Serialize}; |
|
||||||
|
|
||||||
#[repr(u8)] |
|
||||||
#[derive(Debug, PartialEq)] |
|
||||||
pub enum KinesisMessageType { |
|
||||||
DeviceUpsert = 0x01 |
|
||||||
} |
|
||||||
|
|
||||||
#[repr(C)] |
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)] |
|
||||||
pub struct KinesisMessage { |
|
||||||
pub action: u8, // data type
|
|
||||||
pub size: i32, // data size
|
|
||||||
pub data: Vec<u8> // data
|
|
||||||
} |
|
||||||
|
|
||||||
impl KinesisMessage { |
|
||||||
pub fn new(action: u8, size: i32, data: Vec<u8>) -> KinesisMessage { |
|
||||||
KinesisMessage { |
|
||||||
action, |
|
||||||
size, |
|
||||||
data, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
pub fn encode(&self) -> Vec<u8> { |
|
||||||
let mut bin = Vec::new(); |
|
||||||
bin.push(self.action); |
|
||||||
bin.extend_from_slice(&self.size.to_ne_bytes()); |
|
||||||
bin.extend_from_slice(&self.data); |
|
||||||
bin |
|
||||||
} |
|
||||||
|
|
||||||
pub fn decode(encoded: Vec<u8>) -> KinesisMessage { |
|
||||||
let mut current_index = 0; |
|
||||||
let action = encoded[current_index]; |
|
||||||
current_index = current_index + size_of::<u8>(); |
|
||||||
|
|
||||||
let size_vec = encoded.get(current_index..current_index + size_of::<i32>()).unwrap().try_into().unwrap(); |
|
||||||
let size = i32::from_ne_bytes(size_vec); |
|
||||||
current_index = current_index + size_of::<i32>(); |
|
||||||
|
|
||||||
let data = encoded[current_index..current_index + size as usize].to_vec(); |
|
||||||
|
|
||||||
KinesisMessage { |
|
||||||
action, |
|
||||||
size, |
|
||||||
data, |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
@ -1,41 +0,0 @@ |
|||||||
use serde::{Deserialize, Serialize}; |
|
||||||
|
|
||||||
pub trait KinesisMessageDetail<T> { |
|
||||||
fn encode(&self) -> Vec<u8>; |
|
||||||
fn decode(encoded: Vec<u8>) -> T; |
|
||||||
} |
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, PartialEq, Debug)] |
|
||||||
#[repr(C)] |
|
||||||
pub struct UpsertKinesisMessageDetail { |
|
||||||
pub finger_print: String, |
|
||||||
pub so_id: String, |
|
||||||
pub uuid: String, |
|
||||||
pub use_personalized_ad: bool, |
|
||||||
pub test: Option<bool>, |
|
||||||
pub zip_code: Option<String>, |
|
||||||
pub free_storage: i64, |
|
||||||
pub used_storage: i64, |
|
||||||
pub cached_storage: i64, |
|
||||||
pub model_name: String, |
|
||||||
pub firmware_build_date: Option<String>, |
|
||||||
pub firmware_ver: Option<String>, |
|
||||||
pub full_firmware_ver: Option<String>, |
|
||||||
pub app_version: String, |
|
||||||
pub platform_ad_id: Option<String>, |
|
||||||
pub a_key: Option<String>, |
|
||||||
pub is_exist: bool, |
|
||||||
pub device_id: i64 |
|
||||||
} |
|
||||||
|
|
||||||
impl<T> KinesisMessageDetail<T> for UpsertKinesisMessageDetail |
|
||||||
where |
|
||||||
T: Serialize + serde::de::DeserializeOwned,{ |
|
||||||
fn encode(&self) -> Vec<u8> { |
|
||||||
bincode::serialize(&self).unwrap() |
|
||||||
} |
|
||||||
|
|
||||||
fn decode(encoded: Vec<u8>) -> T { |
|
||||||
bincode::deserialize(&encoded).unwrap() |
|
||||||
} |
|
||||||
} |
|
||||||
Loading…
Reference in new issue