linq2dynamodb
linq2dynamodb copied to clipboard
Add support for optimistic concurrency
DataContext.SubmitChanges() should fail, if there's a newer version of an entity in DynamoDB and/or in cache.
This looks like it could be the answer to https://github.com/scale-tone/linq2dynamodb/issues/21, and something i was looking for as well...
Would you accept PR for this? And if so have you thought yet about how you would like to implement it?
hmmm doesn't look like this will be possible with your current update implementation. At least not if you wanted to leverage built-in dynamodb SDK's support for document versioning.
BatchWrites don't support DynamoDBVersion attributes in batched entities.
Would it be a good idea to internally fork between batched ops and DataContext.Save/Delete depending on whether the document type in question is versioned?
Hi Andy!
You're absolutely welcome to send a PR for that, I'd really appreciate your help!
For the implementation, I'd propose to keep being consistent with AWS Object Persistence Model. We could just start respecting the DynamoDBVersion attribute, in a way that if the entity type does have a property marked with that attribute, we do a conditional update. If no such properties exist in the type - we fall back to existing "last writer wins" implementation.
Yes, BatchWrites do not seem to support conditional expressions or anything. Yes, it makes perfect sense to do multiple parallel PutItem operations with properly configured PutItemOperationConfig.Expected values instead.
What I wouldn't recommend is to try using DynamoDBContext.Save() for implementing this. First, because it would be hard to do (note: in ExecuteUpdateBatchAsync() you only have Documents, not entities). And second, because we generally strive not to build on top of AWS Object Persistence. We can re-use attributes from it (to look consistent) but not utilize it's functionality.
so something like this for use of PutItem?
table.PutItem(document, new PutItemOperationConfig()
{
Expected = new Document(new Dictionary<string, DynamoDBEntry>
{
// In reality, we'd get "VersionNumber" from a previous check for any [Versioned]
// members of the original entity (before Document conversion?)
{ "Version", document["VersionNumber"] }
})
});
questions:
- Why not use
UpdateItemapi? - "do multiple parallel PutItem operations": This seems like it needs unpacking.... you mean just an unlimited amount of
PutItemAsynccalls in parallel andTask.WaitAllthe results? Seems like performance and error handling would both be very tough there, no?
Why not use UpdateItem api?
Well, just to be consistent with what BatchWrite operation currently does. It would be confusing, if in one case items are replaced and in other case they're amended.
just an unlimited amount of PutItemAsync calls in parallel and Task.WaitAll the results?
Something like that, except not Task.WaitAll(), but Task.WhenAll().
Seems like performance and error handling would both be very tough there, no?
Well, the performance definitely would be lower compared to what we have with BatchWrite (my experiments show it would be 5-10 times slower). But there're no other options, as we just can't use BatchWrite. Maybe just fine-tuning the task scheduler for those tasks (not in first version obviously).
Error handling should be OK. If any PUT fails, there'll be an exception, and the cache will be cleared. Some items yes, might be written to DynamoDB successfully, but that's the same thing, as we have with BatchWrite now (upon getting an exception the consumer is supposed to implement retries or whatever).