Converting an IInspectable to a RenderingEventArgs - rust

How do you convert an IInspectable reference to a RenderingEventArgs in the following taken from the full xaml_app code below?
CompositionTarget::Rendering(EventHandler::new(move |_, args: &Option<IInspectable>| {
let args: &IInspectable = args.as_ref().unwrap();
//let render_args = RenderingEventArgs::from(&args);
//let render_args: RenderingEventArgs = args.try_into()?;
Ok(())
}))?;
Full code listing follows for context:
#![windows_subsystem = "windows"]
#![allow(non_snake_case)]
use windows::{
core::{
IInspectable,
Result,
HSTRING,
implement,
},
ApplicationModel::Activation::LaunchActivatedEventArgs,
Win32::System::Com::{
CoInitializeEx,
COINIT_MULTITHREADED,
},
Foundation::EventHandler,
//Foundation::TypedEventHandler,
UI::{
Colors,
Xaml::{
Controls::{
TextBlock,
},
Application,
ApplicationInitializationCallback,
Window,
Media::{
FontFamily,
SolidColorBrush,
CompositionTarget,
RenderingEventArgs,
},
HorizontalAlignment,
VerticalAlignment,
FrameworkElement,
IApplicationOverrides,
IApplicationOverrides_Impl,
},
},
};
//use std::convert::TryInto;
#[implement(IApplicationOverrides)]
struct App();
impl IApplicationOverrides_Impl for App {
fn OnLaunched(&self, _: &Option<LaunchActivatedEventArgs>) -> Result<()> {
let block = TextBlock::new()?;
block.SetFontFamily(FontFamily::CreateInstanceWithName(HSTRING::from("Segoe UI Semibold"))?)?;
block.SetFontSize(72.0)?;
block.SetForeground(SolidColorBrush::CreateInstanceWithColor(Colors::Orange()?)?)?;
let fe = FrameworkElement::from(&block);
fe.SetHorizontalAlignment(HorizontalAlignment::Center)?;
fe.SetVerticalAlignment(VerticalAlignment::Center)?;
let window = Window::Current()?;
window.SetContent(&block)?;
window.Activate()?;
CompositionTarget::Rendering(EventHandler::new(move |_, args: &Option<IInspectable>| {
let args: &IInspectable = args.as_ref().unwrap();
//let render_args = RenderingEventArgs::from(&args);
//let render_args: RenderingEventArgs = args.try_into()?;
Ok(())
}))?;
Ok(())
}
}
fn main() -> Result<()> {
unsafe {
CoInitializeEx(std::ptr::null(), COINIT_MULTITHREADED)?;
}
Application::Start(ApplicationInitializationCallback::new(|_| {
Application::compose(App())?;
Ok(())
}))
}
[package]
name = "expanding_text"
version = "0.0.0"
edition = "2018"
[dependencies]
futures = "0.3"
[dependencies.windows]
version = "0.36"
features = [
"implement",
"ApplicationModel_Activation",
"Win32_System_Com",
"UI_Xaml_Controls",
"UI_Xaml",
"UI_Xaml_Media",
"UI",
"Storage_Pickers",
"Foundation_Collections",
"Storage",
"Foundation",
"Storage_Streams",
"Graphics_Imaging",
"Media_Ocr",
"ApplicationModel_Core",
"UI_Core",
]

The following line appears to make the conversion and builds:
let render_args: RenderingEventArgs = args.cast()?;

Related

How to create other threads in main function

I am using the stream function of redis in actix-web 4, I want to create the consumer in the main function, this is my current code
[dependencies]
actix-web = "4"
tokio = { version = "1", features = ["full"] }
redis = { version = "0.21", features = [
# "cluster",
"tokio-comp",
"tokio-native-tls-comp",
] }
#[actix_web::main]
async fn main() -> std::io::Result<()> {
utils::init::init_envfile();
env_logger::init_from_env(env_logger::Env::new());
let redis_pool = utils::init::init_redis_pool();
let mysql_pool = utils::init::init_mysql_pool();
let redist_stream_consumer = web::block(redis_stream_group);
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(redis_pool.clone()))
.app_data(web::Data::new(mysql_pool.clone()))
.service(web::scope("/api").configure(controller::api::config))
})
.bind(("0.0.0.0", 7777))?
.run()
.await?;
redist_stream_consumer.await.unwrap();
Ok(())
}
fn redis_stream_group() {
let client = redis::Client::open("redis://127.0.0.1/").expect("client");
let mut con = client.get_connection().expect("con");
let key = "s.order";
let group_name = "g1";
let consumer_name = "c1";
let _: Result<(), _> = con.xgroup_create_mkstream(key, group_name, "$");
let opts = StreamReadOptions::default()
.group(group_name, consumer_name)
.count(1)
.block(0);
loop {
let read_reply: StreamReadReply =
con.xread_options(&[key], &[">"], &opts).expect("read err");
for StreamKey { key, ids } in read_reply.keys {
for StreamId { id, map } in &ids {
log::info!("id:{} | key:{} | data:{:?}", id, key, map);
}
let id_strs: Vec<&String> = ids.iter().map(|StreamId { id, map: _ }| id).collect();
let _: usize = con.xack(key, group_name, &id_strs).expect("ack err");
}
}
}
When I use cargo r, I can run the program normally and get the sent messages, but when I execute ctrl+c, I can't exit the program.
Also I'm not sure if using web::block in the main function is correct and if there is a better way to run child threads
UPDATE: Tried using tokio::spawn, seems to work
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let redis_pool = utils::init::init_redis_pool();
let mysql_pool = utils::init::init_mysql_pool();
for consumer_index in 1..=2 {
let c_redis_pool = redis_pool.clone();
tokio::spawn(async move {
let mut con = c_redis_pool.get().await.unwrap();
let key = "s.order";
let group_name = "g1";
let consumer_name = &format!("c{consumer_index}");
let _: Result<(), _> = con.xgroup_create_mkstream(key, group_name, "$").await;
let opts = StreamReadOptions::default()
.group(group_name, consumer_name)
.count(1)
.block(5000);
loop {
let read_reply: StreamReadReply = con
.xread_options(&[key], &[">"], &opts)
.await
.expect("err");
for StreamKey { key, ids } in read_reply.keys {
for StreamId { id, map } in &ids {
log::info!(
"consumer: {} | id:{} | key:{} | data:{:?}",
consumer_name,
id,
key,
map
);
}
let id_strs: Vec<&String> =
ids.iter().map(|StreamId { id, map: _ }| id).collect();
let _: usize = con
.xack(key, group_name, &id_strs)
.await
.expect("ack err");
}
}
});
}
let serve = HttpServer::new(move || {
...
}
This can be done with the standard library by useing std::thread and then creating the thread and whatever you want the other thread to do in a closure
fn main() {
thread::spawn(|| {
println!("doing things in the thread!");
});
println!("doing things outside the thread.... how boring");
}
if you want to pass data between them, you can use std::sync::mpsc to transfer data between the threads safely and quickly, using let (item_one,item_two) = mpsc::channel();, like so
fn main() {
let (sender,receiver) = mpsc::channel();
thread::spawn(move || {
let message = String::from("This message is from the thread");
sender.send(message).unwrap();
});
let letter = receiver.recv().unwrap();
note that the main thread proceeds as normal until it comes to the .recv(), at which it either receives the data from the thread, or waits until the other thread is done.
in your example you could do something like
use std::sync::mpsc;
use std::thread;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
utils::init::init_envfile();
env_logger::init_from_env(env_logger::Env::new());
let port = get_env!("ACTIX_PORT", u16);
log::info!(
"starting HTTP server at http://{}:{}",
local_ipaddress::get().unwrap_or("localhost".to_string()),
port
);
let redis_pool = utils::init::init_redis_pool();
let mysql_pool = utils::init::init_mysql_pool();
let (consumer_sender,consumer_listener) = mpsc::channel();
thread::spawn(move || {
consumer_sender.send(redis_stream_group()).expect("You probably want to handle this case, but I'm too lazy");
});
let serve = HttpServer::new(move || {
let app_state = utils::init::AppState {
app_name: get_env!("APP_NAME", String),
pwd_secret: get_env!("PWD_SECRET", String),
jwt_secret: get_env!("JWT_SECRET", String),
jwt_exp: get_env!("JWT_EXP", i64),
};
App::new()
.app_data(web::Data::new(awc::Client::default()))
.app_data(web::Data::new(app_state))
.app_data(web::Data::new(redis_pool.clone()))
.app_data(web::Data::new(mysql_pool.clone()))
.wrap(actix_cors::Cors::default().allowed_origin_fn(|_, _| true))
.service(web::scope("/chat").configure(controller::chat::config))
.service(web::scope("/ws").configure(controller::ws::config))
.service(web::scope("/api").configure(controller::api::config))
});
if cfg!(debug_assertions) {
serve.bind(("0.0.0.0", port))?
} else {
let p = format!("/tmp/{}.socket", get_env!("APP_NAME", String));
let r = serve.bind_uds(&p)?;
let mut perms = std::fs::metadata(&p)?.permissions();
perms.set_readonly(false);
std::fs::set_permissions(&p, perms)?;
r
}
.run()
.await?;
let consumer = consumer_listener.recv().unwrap();
//then put things to do with the consumer here, or not idc
Ok(())
}
fn redis_stream_group() {
let client = redis::Client::open("redis://127.0.0.1/").expect("client");
let mut con = client.get_connection().expect("con");
let key = "s.order";
let group_name = "g1";
let consumer_name = "c1";
let _: Result<(), _> = con.xgroup_create_mkstream(key, group_name, "$");
let opts = StreamReadOptions::default()
.group(group_name, consumer_name)
.count(1)
.block(0);
loop {
let read_reply: StreamReadReply =
con.xread_options(&[key], &[">"], &opts).expect("read err");
for StreamKey { key, ids } in read_reply.keys {
for StreamId { id, map } in &ids {
log::info!("id:{} | key:{} | data:{:?}", id, key, map);
}
let id_strs: Vec<&String> = ids.iter().map(|StreamId { id, map: _ }| id).collect();
let _: usize = con.xack(key, group_name, &id_strs).expect("ack err");
}
}
}

Get a raw vec with field names of any struct with a custom derive macro in Rust

I am trying to write some code that could be able to write a method that returns me a Vec with the names of the fields of a struct.
Code snippet below:
# Don't forget about dependencies if you try to reproduce this on local
use proc_macro2::{Span, Ident};
use quote::quote;
use syn::{
punctuated::Punctuated, token::Comma, Attribute, DeriveInput, Fields, Meta, NestedMeta,
Variant, Visibility,
};
#[proc_macro_derive(StructFieldNames, attributes(struct_field_names))]
pub fn derive_field_names(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let ast: DeriveInput = syn::parse(input).unwrap();
let (vis, ty, generics) = (&ast.vis, &ast.ident, &ast.generics);
let names_struct_ident = Ident::new(&(ty.to_string() + "FieldStaticStr"), Span::call_site());
let fields = filter_fields(match ast.data {
syn::Data::Struct(ref s) => &s.fields,
_ => panic!("FieldNames can only be derived for structs"),
});
let names_struct_fields = fields.iter().map(|(vis, ident)| {
quote! {
#vis #ident: &'static str
}
});
let mut vec_fields: Vec<String> = Vec::new();
let names_const_fields = fields.iter().map(|(_vis, ident)| {
let ident_name = ident.to_string();
vec_fields.push(ident_name);
quote! {
#vis #ident: -
}
});
let names_const_fields_as_vec = fields.iter().map(|(_vis, ident)| {
let ident_name = ident.to_string();
// vec_fields.push(ident_name)
});
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
let tokens = quote! {
#[derive(Debug)]
#vis struct #names_struct_ident {
#(#names_struct_fields),*
}
impl #impl_generics #ty #ty_generics
#where_clause
{
#vis fn get_field_names() -> &'static str {
// stringify!(
[ #(#vec_fields),* ]
.map( |s| s.to_string())
.collect()
// )
}
}
};
tokens.into()
}
fn filter_fields(fields: &Fields) -> Vec<(Visibility, Ident)> {
fields
.iter()
.filter_map(|field| {
if field
.attrs
.iter()
.find(|attr| has_skip_attr(attr, "struct_field_names"))
.is_none()
&& field.ident.is_some()
{
let field_vis = field.vis.clone();
let field_ident = field.ident.as_ref().unwrap().clone();
Some((field_vis, field_ident))
} else {
None
}
})
.collect::<Vec<_>>()
}
const ATTR_META_SKIP: &'static str = "skip";
fn has_skip_attr(attr: &Attribute, path: &'static str) -> bool {
if let Ok(Meta::List(meta_list)) = attr.parse_meta() {
if meta_list.path.is_ident(path) {
for nested_item in meta_list.nested.iter() {
if let NestedMeta::Meta(Meta::Path(path)) = nested_item {
if path.is_ident(ATTR_META_SKIP) {
return true;
}
}
}
}
}
false
}
The code it's taken from here. Basically I just want to get those values as a String, and not to access them via Foo::FIELD_NAMES.some_random_field, because I need them for another process.
How can I achieve that?
Thanks

Actix web - sqlx - juniper: I got 'Tried to resolve async field users on type Some("Query") with a sync resolver'

I'm trying to use Actix-SQLx-Juniper in my Rust project. I've followed and combined any tutorial that I've found, it successfully compiled and run. But when I try to post a query, I got this error in terminal:
thread 'actix-web' panicked at 'Tried to resolve async field users on type Some("Query") with a sync resolver', src/graphql.rs:15:1
and my GraphiQL shows "Thread pool is gone"
this is the src/graphql.rs:
#[derive(Clone, Debug)]
pub struct Context {
pub pool: PgPool,
}
impl juniper::Context for Context {}
pub struct Query;
#[graphql_object(Context = Context)] // this is line 15
impl Query {
fn apiVersion() -> &str {
"1.0"
}
#[graphql(description = "Hello")]
pub async fn users(ctx: &Context) -> FieldResult<Vec<User>> {
println!("{:#?}", ctx);
sqlx::query_as::<_, User>("SELECT * FROM users")
.fetch_all(&ctx.pool)
.await
.map_err(|e| e.into())
}
}
pub type Schema = RootNode<'static, Query, EmptyMutation<Context>, EmptySubscription<Context>>;
pub fn create_schema() -> Schema {
Schema::new(Query {}, EmptyMutation::new(), EmptySubscription::new())
}
But after I trace the error, it panicked when I tried to use execute_sync in my src/handler.rs:
pub fn graphql_handlers(config: &mut ServiceConfig) {
config
.data(create_schema())
.route("/graphql", web::get().to(graphql_playground))
.route("/graphql", web::post().to(graphql));
}
...
...
async fn graphql(
pool: web::Data<PgPool>,
schema: web::Data<Schema>,
data: web::Json<GraphQLRequest>,
) -> Result<HttpResponse, Error> {
let ctx = Context {
pool: pool.get_ref().to_owned(),
};
let res = block(move || {
let res = data.execute_sync(&schema, &ctx);
Ok::<_, serde_json::error::Error>(serde_json::to_string(&res)?)
})
.await
.map_err(Error::from)?;
Ok(HttpResponse::Ok()
.content_type("application/json")
.body(res))
}
I've tried to find the solution or boilerplate code but still couldn't find it.
Here's my main.rs:
#[actix_web::main]
async fn main() -> Result<()> {
let pool = create_pool().await.expect("Failed connecting to postgres");
HttpServer::new(move || {
App::new()
.data(pool.clone())
.wrap(Logger::default())
.configure(graphql_handlers)
})
.bind("127.0.0.1:8000")?
.run()
.await
}
Here's my dependencies:
actix-web = "3"
juniper = "0.15"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.64"
uuid = { version = "0.8", features = [ "serde", "v4"] }
sqlx = { version = "0.4", features = [ "runtime-actix-rustls", "postgres", "uuid" ] }

Caching sqlx Pool causes overrun in file handles

I plan to have a application which uses Sqlite databases as data files.
Because different files can be opended more often, I want to cache the connections.
I'm very new to Rust; this is my first project...
My problem is: Somewhen I run out of file handles, and I cannot create new database files.
What I tried so far:
test1(), will only work, if I implement Drop for MyPool. Drop will close the connection-pool. By doing this, I'm sure the file handles gets free again.
test2(), is the async version which I would need for my project (it will be a Rocket app). Here I'm not successful at all.
If you run the code, you would have to delete all db.* files afterwards.
// Cargo.toml
// tokio = { version = "1", features = ["rt-multi-thread", "macros" ] }
// futures = "0.3"
// sqlx = { version = "0.5", features = [ "runtime-tokio-native-tls", "sqlite", "migrate" ] }
use sqlx::{migrate::MigrateDatabase, sqlite::SqlitePoolOptions, Pool, Sqlite};
use futures::executor::block_on;
use std::sync::{Arc, Mutex};
#[derive(Clone)]
struct MyPool(Pool<Sqlite>);
impl Drop for MyPool {
fn drop(&mut self) {
println!("**** drop");
block_on(
self.0.close()
);
}
}
#[tokio::main]
async fn main() {
test1().await;
//test2().await;
}
async fn test1() {
let mut pool: Vec<MyPool> = Vec::new();
for i in 1..1000 {
let db_name = format!("./db.{}.db", i);
Sqlite::create_database(&db_name)
.await.expect(format!("create {} failed", i).as_str());
let conn = SqlitePoolOptions::new()
.max_connections(5)
.connect(&db_name).await.expect(format!("connect {} failed", i).as_str());
if pool.len() == 10 {
println!("Clenup");
pool.clear();
}
println!("{}", i);
pool.push(MyPool(conn));
}
}
async fn test2() {
let pool: Arc<Mutex<Vec<MyPool>>> = Arc::new(Mutex::new(Vec::new()));
let tasks: Vec<_> = (0..1000)
.map(|i| {
let my_pool = pool.clone();
tokio::spawn(async move {
let db_name = format!("./db.{}.db", i);
Sqlite::create_database(&db_name)
.await.expect(format!("create {} failed", i).as_str());
let conn = SqlitePoolOptions::new()
.max_connections(5)
.connect(&db_name).await.expect(format!("connect {} failed", i).as_str());
{
let mut locked_pool = my_pool.lock().expect("locked");
if locked_pool.len() == 10 {
println!("Clenup");
locked_pool.clear();
}
println!("{}", i);
locked_pool.push(MyPool(conn));
}
})
}).collect();
// Wait for all tasks to complete.
futures::future::join_all(tasks).await;
}

Tokio core.run can't compile. got error: the trait `futures::future::Future` is not implemented for `impl futures::Future`

I am learning the Rust and Rusoto with this example https://www.rusoto.org/futures.html
And I found many of the code are outdated. So I changed the code like this:
use rusoto_core::{Region, RusotoError};
use rusoto_dynamodb::{
AttributeDefinition, AttributeValue, CreateTableError, CreateTableInput, CreateTableOutput,
DynamoDb, DynamoDbClient, GetItemError, GetItemInput, GetItemOutput, KeySchemaElement,
UpdateItemError, UpdateItemInput, UpdateItemOutput,
};
use std::collections::HashMap;
use std::error::Error;
use tokio_core::reactor::Core;
fn main() {
let item = make_item();
let client = get_dynamodb_local_client();
let mut core = Core::new().unwrap();
let chained_future = chain_futures(&client, &item);
let item_from_dynamo = match core.run(chained_future) {
Ok(item) => item,
Err(e) => panic!("Error completing futures: {}", e),
};
println!("item: {:?}", item_from_dynamo);
}
async fn chain_futures(
client: &DynamoDbClient,
item: &HashMap<String, AttributeValue>,
) -> Result<GetItemOutput, RusotoError<impl Error>> {
let _ = make_create_table_future(client).await;
let _ = make_upsert_item_future(client, item).await;
make_get_item_future(client, item).await
}
async fn make_create_table_future(
client: &DynamoDbClient,
) -> Result<CreateTableOutput, RusotoError<CreateTableError>> {
let attribute_def = AttributeDefinition {
attribute_name: "foo_name".to_string(),
attribute_type: "S".to_string(),
};
let k_schema = KeySchemaElement {
attribute_name: "foo_name".to_string(),
key_type: "HASH".to_string(), // case sensitive
};
let make_table_request = CreateTableInput {
table_name: "a-testing-table".to_string(),
attribute_definitions: vec![attribute_def],
key_schema: vec![k_schema],
..Default::default()
};
client.create_table(make_table_request).await
}
async fn make_upsert_item_future(
client: &DynamoDbClient,
item: &HashMap<String, AttributeValue>,
) -> Result<UpdateItemOutput, RusotoError<UpdateItemError>> {
let add_item = UpdateItemInput {
key: item.clone(),
table_name: "a-testing-table".to_string(),
..Default::default()
};
client.update_item(add_item).await
}
async fn make_get_item_future(
client: &DynamoDbClient,
item: &HashMap<String, AttributeValue>,
) -> Result<GetItemOutput, RusotoError<GetItemError>> {
// future for getting the entry
let get_item_request = GetItemInput {
key: item.clone(),
table_name: "a-testing-table".to_string(),
..Default::default()
};
client.get_item(get_item_request).await
}
fn make_item() -> HashMap<String, AttributeValue> {
let item_key = "foo_name";
let mut item = HashMap::new();
item.insert(
item_key.to_string(),
AttributeValue {
s: Some("baz".to_string()),
..Default::default()
},
);
item
}
fn get_dynamodb_local_client() -> DynamoDbClient {
// Create custom Region
let region = Region::Custom {
name: "us-east-1".to_owned(),
endpoint: "http://localhost:8000".to_owned(),
};
DynamoDbClient::new(region)
}
Then I found this compile error:
error[E0277]: the trait bound `impl std::future::Future: futures::future::Future` is not satisfied
--> cmd/src/main.rs:18:43
|
18 | let item_from_dynamo = match core.run(chained_future) {
| ^^^^^^^^^^^^^^ the trait `futures::future::Future` is not implemented for `impl std::future::Future`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0277`.
error: could not compile `cmd`.
To learn more, run the command again with --verbose.
make: *** [run] Error 101
Can anyone explain the error? What's the difference of those 2 Future traits? And what the code should be look like?
This is my cargo dependencies:
[dependencies]
rusoto_core = "0.44"
rusoto_dynamodb = "0.44"
futures = "0.3"
tokio = { version = "0.2", features = ["full"] }
tokio-core = "0.1"
Thanks
Bruce
Instead of using tokio_core::reactor::Core, I used tokio::runtime::Runtime and block_on
Working code:
extern crate futures;
extern crate rusoto_core;
extern crate rusoto_dynamodb;
extern crate tokio_core;
use futures::future::FutureExt;
use rusoto_core::{Region, RusotoError};
use rusoto_dynamodb::{
AttributeDefinition, AttributeValue, CreateTableError, CreateTableInput, CreateTableOutput,
DynamoDb, DynamoDbClient, GetItemError, GetItemInput, GetItemOutput, KeySchemaElement,
UpdateItemError, UpdateItemInput, UpdateItemOutput,
};
use std::collections::HashMap;
fn main() {
let item = make_item();
let client = get_dynamodb_local_client();
let mut core = tokio::runtime::Runtime::new().unwrap();
let create_table_future = make_create_table_future(&client);
let upsert_item_future = make_upsert_item_future(&client, &item);
let item_from_dynamo_future = make_get_item_future(&client, &item);
let chained_futures = create_table_future
.then(|_| upsert_item_future)
.then(|_| item_from_dynamo_future);
let item_from_dynamo = match core.block_on(chained_futures) {
Ok(item) => item,
Err(e) => panic!("Error completing futures: {}", e),
};
println!("item: {:?}", item_from_dynamo);
}
async fn make_create_table_future(
client: &DynamoDbClient,
) -> Result<CreateTableOutput, RusotoError<CreateTableError>> {
let attribute_def = AttributeDefinition {
attribute_name: "foo_name".to_string(),
attribute_type: "S".to_string(),
};
let k_schema = KeySchemaElement {
attribute_name: "foo_name".to_string(),
key_type: "HASH".to_string(), // case sensitive
};
let make_table_request = CreateTableInput {
table_name: "a-testing-table".to_string(),
attribute_definitions: vec![attribute_def],
key_schema: vec![k_schema],
..Default::default()
};
client.create_table(make_table_request).await
}
async fn make_upsert_item_future(
client: &DynamoDbClient,
item: &HashMap<String, AttributeValue>,
) -> Result<UpdateItemOutput, RusotoError<UpdateItemError>> {
let add_item = UpdateItemInput {
key: item.clone(),
table_name: "a-testing-table".to_string(),
..Default::default()
};
client.update_item(add_item).await
}
async fn make_get_item_future(
client: &DynamoDbClient,
item: &HashMap<String, AttributeValue>,
) -> Result<GetItemOutput, RusotoError<GetItemError>> {
// future for getting the entry
let get_item_request = GetItemInput {
key: item.clone(),
table_name: "a-testing-table".to_string(),
..Default::default()
};
client.get_item(get_item_request).await
}
fn make_item() -> HashMap<String, AttributeValue> {
let item_key = "foo_name";
let mut item = HashMap::new();
item.insert(
item_key.to_string(),
AttributeValue {
s: Some("baz".to_string()),
..Default::default()
},
);
item
}
fn get_dynamodb_local_client() -> DynamoDbClient {
// Create custom Region
let region = Region::Custom {
name: "us-east-1".to_owned(),
endpoint: "http://localhost:8000".to_owned(),
};
DynamoDbClient::new(region)
}

Resources