We use DynamoDB UpdateItem.
This acts as an "upsert" as we can learn from the documentation
Edits an existing item's attributes, or adds a new item to the table if it does not already exist. [...]
When we make a request, to determine if an item was created or an existing item was updated, we request ALL_OLD. This works great and allows us to differentiate between update and create.
As an additional requirement we also want to return ALL_NEW, but still know the type of operation that was performed.
Question: Is this possible to do in a single request or do we have to make a second (get) request?
By default this is not supported in DynamoDB, there is no ALL or NEW_AND_OLD_IMAGES as there is in DynamoDB streams, but you can always go DIY.
When you do the UpdateItem call, you have the UpdateExpression, which is basically the list of changes to apply to the item. Given that you told DynamoDB to return the item as it looked like before that operation, you can construct the new state locally.
Just create a copy of the ALL_OLD response and locally apply the changes from the UpdateExpression to it. That's definitely faster than two API calls at the cost of a slightly more complex implementation.
Related
I am using AWS proxy with AWS API Gateway to interact with a DynamoDB table. I have an API resource, under which I have a GET method with the below configuration:
The API uses the Scan action as seen above to fetch all the items from the DynamoDB table. I also have the following request integration mapping template;
{
"TableName": tableName
}
Its really simple. But my problem is that I would like to add another GET method to get each item by their id, which will be supplied in the URL as a param. However, since I have already setup one GET method, I am not able to setup another to fetch only a single item. I am aware I can use mapping templates and Scan as given in the docs to conditionally fetch items if a param is given, but that would mean scanning the entire table, which is a waste each time I want to fetch a single item.
Is there any other way to do this?
I am trying to get the list of attributes that were overwritten in a DynamoDB batch operation, but it doesn't have this information in the response.
Is there anyway to get list of items that were overwritten when using batch write?
No: The API docs clearly list which information is returned and that's not among them.
If you need the before state, you have to do individual PutItem requests with the ReturnValues parameter set to ALL_OLD - docs.
With respect to AWS AppSync Is there a way of subscribing to an element in an array , eg:
onSendMessage(recipientIds:[myID,otherPotentiallyRandomAndUnknownIds]) {
}
I have tried simply adding the element I'm looking for, however it doesn't trigger a subscription if I'm missing the other elements (and in order too)
Unfortunately this is something that can't be done trivially. Also the as you noted the order matters because in GraphQL it should viewed as a List (which is ordered). So the subscription triggers expecting the order you provided on the schema. It also expects the exact arguments you provide in the list because a GraphQL Schema is essentially viewed as a contract by clients so if the contract dictates that the subscription is on a List with these elements in this order - then it will initiate the subscription based on that.
Now what you could do is set up a dynamo stream (assuming DynamoDB as your data source) that feeds any changes on the table into a lambda from where you can make a mutation on AppSync (depending on if a change to was made to an element in the array) to trigger a subscription (set up simple mutation/subscriptions for this use case only). This is sort of a hack-y workaround, and there may be other novel solutions you can explore.
We have a service which inserts into dynamodb certain values. For sake of this question let's say its key:value pair i.e., customer_id:customer_email. The inserts don't happen that frequently and once the inserts are done, that specific key doesn't get updated.
What we have done is create a client library which, provided with customer_id will fetch customer_email from dynamodb.
Given that customer_id data is static, what we were thinking is to add cache to the table but one thing which we are not sure that what will happen in the following use-case
client_1 uses our library to fetch customer_email for customer_id = 2.
The customer doesn't exist so API Gateway returns not found
APIGateway will cache this response
For any subsequent calls, this cached response will be sent
Now another system inserts customer_id = 2 with its email id. This system doesn't know if this response has been cached previously or not. It doesn't even know that any other system has fetched this specific data. How can we invalidate cache for this specific customer_id when it gets inserted into dynamodb
You can send a request to the API endpoint with a Cache-Control: max-age=0 header which will cause it to refresh.
This could open your application up to attack as a bad actor can simply flood an expensive endpoint with lots of traffic and buckle your servers/database. In order to safeguard against that it's best to use a signed request.
In case it's useful to people, here's .NET code to create the signed request:
https://gist.github.com/secretorange/905b4811300d7c96c71fa9c6d115ee24
We've built a Lambda which takes care of re-filling cache with updated results. It's a quite manual process, with very little re-usable code, but it works.
Lambda is triggered by the application itself following application needs. For example, in CRUD operations the Lambda is triggered upon successful execution of POST, PATCH and DELETE on a specific resource, in order to clear the general GET request (i.e. clear GET /books whenever POST /book succeeded).
Unfortunately, if you have a View with a server-side paginated table you are going to face all sorts of issues because invalidating /books is not enough since you actually may have /books?page=2, /books?page=3 and so on....a nightmare!
I believe APIG should allow for more granular control of cache entries, otherwise many use cases aren't covered. It would be enough if they would allow to choose a root cache group for each request, so that we could manage cache entries by group rather than by single request (which, imho, is also less common).
Did you look at this https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-caching.html ?
There is way to invalidate entire cache or a particular cache entry
I am using watchQuery to get data from the backend and subscribe to the observable. I need to change the data returned from the backend, but they are all read-only property. How can I modify the data?
If you have a subscription on an observable you might want to use the updateQuery functionality. Example in the docu.
There you see that you can update the store using the subscribeToMore functionality of your query. Therein you add the updateQuery function which gives you the result of the subscription. Now you can copy the result of the subscription update it accordingly and return the updated query.