I have a method in an AWS Lambda which receives a completed list of items. It processes those items and then inserts them into a Dynamo DB table. Order of processing or inserting into the DB does not matter.
I'm looking for the most thread-safe, yet easy to understand manner in which to make this run faster; Either by using async await
or something other (likely parallel?) operations.
I was thinking Parallel.ForEach()
but that seems a bit heavy. Is there a simpler, more obvious way?
private async Task<int> LoadAutocomplete(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
foreach (var item in resp)
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "LANGUAGE", new AttributeValue { S = item.LANGUAGE }},
{ "COUNTRY", new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
System.Threading.Thread.Sleep(100);
}
}
Option 1
private async Task<int> LoadAutocomplete(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
Parallel.ForEach(resp, async item =>
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "LANGUAGE", new AttributeValue { S = item.LANGUAGE }},
{ "COUNTRY", new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
}
}
Option 2 causes the compiler to complain that the LoadAutoComplete method "lacks await operators and will run synchronously".
Option 2 As suggested by @jamesfaix
private async Task<int> LoadAutocomplete(IList<Item> resp)
{
var client = new AmazonDynamoDBClient();
var tasks = items.Select(x => DoSomethingAsync(client, x)).ToList();
await Task.WhenAll(tasks);
}
private DoSomething(AmazonDynamoDBClient client, Item item)
{
var request = new PutItemRequest
{
TableName = EnvironmentHelper.DynamoTableName,
Item = new Dictionary<string, AttributeValue>()
{
{ "LANGUAGE", new AttributeValue { S = item.LANGUAGE }},
{ "COUNTRY", new AttributeValue { S = item.COUNTRY }}
}
};
await client.PutItemAsync(request);
}
Options + Suggested by @martin
The post "Use Parallel.For in batches in dotnet core" does respond to my question, but I've chosen the answer posted by @jamesfaix because it has improved my code so much.