-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* faet: Add transact write foundation * feat: TxWrite minimum example works * feat: Add condition * feat: Add error convertor * spec: Add test
- Loading branch information
Showing
11 changed files
with
315 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ dynamo: | |
node setup | ||
|
||
test: | ||
make dynamo | ||
cargo test -- --test-threads=1 | ||
|
||
lint: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,3 +89,4 @@ pub struct GetItemInput { | |
pub table_name: String, | ||
} | ||
*/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
use crate::rename::*; | ||
use quote::*; | ||
|
||
pub(crate) fn expand_transact_write( | ||
struct_name: &proc_macro2::Ident, | ||
fields: &syn::FieldsNamed, | ||
rename_all_type: crate::rename::RenameAllType, | ||
table_name: &str, | ||
) -> proc_macro2::TokenStream { | ||
let item_input_name = format_ident!("{}PutItemInput", struct_name); | ||
// let item_output_name = format_ident!("{}PutItemOutput", struct_name); | ||
let put_builder = format_ident!("{}TransactPutItemBuilder", struct_name); | ||
let condition_token_name = format_ident!("{}ConditionToken", struct_name); | ||
|
||
// let output_values = fields.named.iter().map(|f| { | ||
// let ident = &f.ident.clone().unwrap(); | ||
// let renamed = crate::finder::find_rename_value(&f.attrs); | ||
// let attr_key = create_renamed(ident.to_string(), renamed, rename_all_type); | ||
// if crate::finder::include_unary_attr(&f.attrs, "uuid") { | ||
// quote! { | ||
// #ident: uuid_map.get(#attr_key).cloned().unwrap().into(), | ||
// } | ||
// } else { | ||
// quote! { | ||
// #ident: item.#ident, | ||
// } | ||
// } | ||
// }); | ||
|
||
let input_items = { | ||
let insertion = fields.named.iter().map(|f| { | ||
let ident = &f.ident.clone().unwrap(); | ||
let renamed = crate::finder::find_rename_value(&f.attrs); | ||
let attr_key = create_renamed(ident.to_string(), renamed, rename_all_type); | ||
if crate::finder::include_unary_attr(&f.attrs, "uuid") { | ||
quote! { | ||
let id = #struct_name::gen(); | ||
input_item.insert( | ||
#attr_key.to_string(), | ||
id.clone().into_attr(), | ||
); | ||
uuid_map.insert( | ||
#attr_key.to_string(), | ||
id, | ||
); | ||
} | ||
} else { | ||
quote! { | ||
input_item.insert( | ||
#attr_key.to_string(), | ||
item.#ident.clone().into_attr(), | ||
); | ||
} | ||
} | ||
}); | ||
|
||
quote! { | ||
let mut input_item: std::collections::HashMap<String, raiden::AttributeValue> = std::collections::HashMap::new(); | ||
#(#insertion)* | ||
} | ||
}; | ||
|
||
quote! { | ||
impl #struct_name { | ||
pub fn put(item: #item_input_name) -> #put_builder { | ||
let mut input = ::raiden::Put::default(); | ||
let mut attribute_names: std::collections::HashMap<String, String> = std::collections::HashMap::new(); | ||
let mut attribute_values: std::collections::HashMap<String, raiden::AttributeValue> = std::collections::HashMap::new(); | ||
let mut uuid_map: std::collections::HashMap<String, String> = std::collections::HashMap::new(); | ||
|
||
#input_items | ||
|
||
// let output_item = #item_output_name { | ||
// #(#output_values)* | ||
// }; | ||
input.item = input_item; | ||
input.table_name = #table_name.to_owned(); | ||
#put_builder { | ||
input, | ||
// item: output_item, | ||
} | ||
} | ||
} | ||
|
||
pub struct #put_builder { | ||
pub input: ::raiden::Put, | ||
} | ||
|
||
impl ::raiden::TransactWritePutBuilder for #put_builder { | ||
fn build(self) -> ::raiden::Put { | ||
self.input | ||
} | ||
} | ||
|
||
impl #put_builder { | ||
fn condition(mut self, cond: impl ::raiden::condition::ConditionBuilder<#condition_token_name>) -> Self { | ||
let (cond_str, attr_names, attr_values) = cond.build(); | ||
if !attr_names.is_empty() { | ||
self.input.expression_attribute_names = Some(attr_names); | ||
} | ||
if !attr_values.is_empty() { | ||
self.input.expression_attribute_values = Some(attr_values); | ||
} | ||
self.input.condition_expression = Some(cond_str); | ||
self | ||
} | ||
} | ||
} | ||
} | ||
|
||
/* | ||
#[derive(Default, Debug, Clone, PartialEq, Serialize)] | ||
#[cfg_attr(feature = "deserialize_structs", derive(Deserialize))] | ||
pub struct Put { | ||
/// <p>A condition that must be satisfied in order for a conditional update to succeed.</p> | ||
#[serde(rename = "ConditionExpression")] | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub condition_expression: Option<String>, | ||
/// <p>One or more substitution tokens for attribute names in an expression.</p> | ||
#[serde(rename = "ExpressionAttributeNames")] | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub expression_attribute_names: Option<::std::collections::HashMap<String, String>>, | ||
/// <p>One or more values that can be substituted in an expression.</p> | ||
#[serde(rename = "ExpressionAttributeValues")] | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub expression_attribute_values: Option<::std::collections::HashMap<String, AttributeValue>>, | ||
/// <p>A map of attribute name to attribute values, representing the primary key of the item to be written by <code>PutItem</code>. All of the table's primary key attributes must be specified, and their data types must match those of the table's key schema. If any attributes are present in the item that are part of an index key schema for the table, their types must match the index key schema. </p> | ||
#[serde(rename = "Item")] | ||
pub item: ::std::collections::HashMap<String, AttributeValue>, | ||
/// <p>Use <code>ReturnValuesOnConditionCheckFailure</code> to get the item attributes if the <code>Put</code> condition fails. For <code>ReturnValuesOnConditionCheckFailure</code>, the valid values are: NONE and ALL_OLD.</p> | ||
#[serde(rename = "ReturnValuesOnConditionCheckFailure")] | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub return_values_on_condition_check_failure: Option<String>, | ||
/// <p>Name of the table in which to write the item.</p> | ||
#[serde(rename = "TableName")] | ||
pub table_name: String, | ||
}*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
use raiden::*; | ||
|
||
#[derive(Raiden)] | ||
#[raiden(table_name = "user")] | ||
pub struct User { | ||
#[raiden(partition_key)] | ||
id: String, | ||
name: String, | ||
} | ||
|
||
fn main() { | ||
let mut rt = tokio::runtime::Runtime::new().unwrap(); | ||
async fn example() { | ||
let mut tx = ::raiden::WriteTx::new(Region::Custom { | ||
endpoint: "http://localhost:8000".into(), | ||
name: "ap-northeast-1".into(), | ||
}); | ||
let cond = User::condition().attr_not_exists(UserAttrNames::Id); | ||
let input = User::put_item_builder() | ||
.id("testId".to_owned()) | ||
.name("bokuweb".to_owned()) | ||
.build() | ||
.unwrap(); | ||
let input2 = User::put_item_builder() | ||
.id("testId2".to_owned()) | ||
.name("bokuweb".to_owned()) | ||
.build() | ||
.unwrap(); | ||
tx.put(User::put(input).condition(cond)) | ||
.put(User::put(input2)) | ||
.run() | ||
.await | ||
.unwrap(); | ||
} | ||
rt.block_on(example()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
pub mod get; | ||
pub mod put; | ||
pub mod query; | ||
pub mod transact_write; | ||
|
||
pub use transact_write::*; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
use crate::{DynamoDb, TransactWriteItem}; | ||
|
||
pub struct WriteTx { | ||
items: Vec<crate::TransactWriteItem>, | ||
client: crate::DynamoDbClient, | ||
} | ||
impl WriteTx { | ||
pub fn new(region: crate::Region) -> Self { | ||
let client = crate::DynamoDbClient::new(region); | ||
Self { | ||
items: vec![], | ||
client, | ||
} | ||
} | ||
|
||
pub fn put(mut self, builder: impl TransactWritePutBuilder) -> Self { | ||
self.items.push(TransactWriteItem { | ||
condition_check: None, | ||
delete: None, | ||
update: None, | ||
put: Some(builder.build()), | ||
}); | ||
self | ||
} | ||
|
||
pub async fn run(self) -> Result<(), crate::RaidenError> { | ||
let _res = self | ||
.client | ||
.transact_write_items(crate::TransactWriteItemsInput { | ||
client_request_token: None, | ||
return_consumed_capacity: None, | ||
return_item_collection_metrics: None, | ||
transact_items: self.items, | ||
}) | ||
.await?; | ||
// TODO: ADD Response later | ||
Ok(()) | ||
} | ||
} | ||
|
||
pub trait TransactWritePutBuilder { | ||
fn build(self) -> crate::Put; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#[cfg(test)] | ||
mod tests { | ||
|
||
#[cfg(test)] | ||
use pretty_assertions::assert_eq; | ||
use raiden::*; | ||
|
||
#[derive(Raiden)] | ||
#[raiden(table_name = "user")] | ||
#[derive(Debug, Clone)] | ||
pub struct User { | ||
#[raiden(partition_key)] | ||
id: String, | ||
name: String, | ||
} | ||
|
||
#[test] | ||
fn test_minimum_transact_write() { | ||
let tx = ::raiden::WriteTx::new(Region::Custom { | ||
endpoint: "http://localhost:8000".into(), | ||
name: "ap-northeast-1".into(), | ||
}); | ||
let cond = User::condition().attr_not_exists(UserAttrNames::Id); | ||
let input = User::put_item_builder() | ||
.id("testId".to_owned()) | ||
.name("bokuweb".to_owned()) | ||
.build() | ||
.unwrap(); | ||
let input2 = User::put_item_builder() | ||
.id("testId2".to_owned()) | ||
.name("bokuweb".to_owned()) | ||
.build() | ||
.unwrap(); | ||
assert_eq( | ||
tx.put(User::put(input).condition(cond)) | ||
.put(User::put(input2)) | ||
.run() | ||
.await | ||
.is_ok(), | ||
true, | ||
) | ||
} | ||
} |