Add an Update Note API

From @jayair on Mon Apr 10 2017 01:00:17 GMT+0000 (UTC)

Link to chapter - http://serverless-stack.com/chapters/add-an-update-note-api.html

Copied from original issue: https://github.com/AnomalyInnovations/serverless-stack-com/issues/26

From @oluckyman on Sun Apr 16 2017 00:22:39 GMT+0000 (UTC)

why use
ReturnValues: 'ALL_NEW',
if the response returns success: true only?

From @fwang on Sun Apr 16 2017 16:48:52 GMT+0000 (UTC)

You are totally right. We are not using the results any where in the code. It is in there in case users want to inspect the return value just for learning purposes.

Feel free to set ReturnValues to ‘NONE’ or remove the line.

From @oluckyman on Sun Apr 16 2017 19:00:41 GMT+0000 (UTC)

cool, thanks!
and thanks for the content, great material and easy to read. I like how you
balance explaining things and avoiding rabbit holes, without overwhelming
with too much information

From @walshe on Wed Jan 17 2018 03:07:39 GMT+0000 (UTC)

wouldn’t it be a good idea to use a ‘version’ field for an optimistic locking approach ?

From @jayair on Fri Jan 19 2018 01:13:37 GMT+0000 (UTC)

@walshe Do you mean a version to keep track of the edits made to a note? You can definitely do that! We are just keeping it fairly simple in the tutorial.

From @walshe on Fri Jan 19 2018 01:29:01 GMT+0000 (UTC)

@jayair not exactly, I am talking about handling concurrent updates, so that if an entity has changed between the time it takes someone to read and update the entity then the update would fail similar to an ‘update x set a=, b=,c= where version=’

From @jayair on Fri Jan 19 2018 22:29:37 GMT+0000 (UTC)

@walshe Oh yeah I see what you are saying. That is definitely a good idea. I think we could cover it in an advanced chapter maybe?

For anybody else reading this; if two users are editing the same note, one could overwrite the other since we simply update the note with the passed in content. By adding a version field we can ensure that the note we are editing is the current version of it (as opposed to one that has already been updated in Dynamo).

From @walshe on Sat Jan 20 2018 02:57:47 GMT+0000 (UTC)

yeah I think you just need a condition expression in the update

From @allasandeep on Sat Mar 24 2018 23:26:54 GMT+0000 (UTC)

I am getting this error, can anyone help me?

serverless invoke local --function update --path mocks/update-event.json

  Y A M L Exception --------------------------------------

  duplicated mapping key in "C:\Users\gayat\Desktop\project-app-api\serverless.yml" at line 75, column 5:
        handler: update.main
        ^

     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Forums:        forum.serverless.com
     Chat:          gitter.im/serverless/serverless

  Your Environment Information -----------------------------
     OS:                     win32
     Node Version:           8.10.0
     Serverless Version:     1.26.1

Shouldn’t the Update Note API use POST instead of PUT. PUT creates a new note if the ID is not present already.

Not necessarily but there isn’t a super strict rule here. You could use PUT and POST to create if you wanted to. The rule we typically follow is to use PUT for idempotent actions.

I have an issue where my code is just creating new entries instead of updating an existing entry. All code has been copied from the tutorial pages, however I have replaced the wording ‘notes’ with ‘dockets’ and ‘noteId’ with ‘docketId’

Are you trying to update the docketId? Usually it creates new entires if you are updating the primary key.

I discovered my problem, when I was invoking the serverless command I wasn’t changing the function I was using, woops!

1 Like

Not sure is is a bug or just DynamoDB feature, but when you use some random non-existing id in pathParameters/id a record will be created anyway. Although its attribute createdAt will be empty.

2 Likes

Hi y’all I’m getting internal server error when trying to update an item (error 500). I’ve tried looking around but can’t figure out what system will actually tell me what the problem is, where, and ideally what to do about it.

export async function main (event, context) {
  const data = JSON.parse(event.body)
  const params = {
    TableName: process.env.tableName,
    Key: {
      userId: {"S": event.requestContext.identity.cognitoIdentityId},
      nodeId: {"S": event.pathParameters.id}
    },
    UpdateExpression: "SET content = :content, attachment = :attachment",
    ExpressionAttributeValues: {
      ":attachment": {"S":data.attachment || null},
      ":content": {"S": data.content || null}
    },
    ReturnValues: "ALL_NEW"
  }
  try {
    await dynamoDbLib.call('update', params)
    return (success({ status:true }))
  } catch (e) {
    return failure({ status: false, params:JSON.stringify(params) })
  }
}

Make sure to console.log(e) before we the return failure line.

I was concerned about this in my app too. You can add a ConditionExpression to your params, either of the below should work. See https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html#Expressions.ConditionExpressions.PreventingOverwrites

ConditionExpression: 'attribute_exists(plantId)'

OR

ConditionExpression: 'plantId = :plantIdVal'
1 Like

You can add the following entry to your params object:

ConditionExpression: 'attribute_exists(noteId)',

However the HTTP response will have an odd error message:

{
    "statusCode": 500,
    "body": "{\"error\":\"The conditional request failed\"}",
    "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Credentials": true
    }
}
1 Like