node.jsaws-lambdaaws-appsyncgraphql-jsdynamodb-queries

Why AWS Appsync failed to query the updated DynamoDB table with graphql


I created a lambda function that check the existence of an item in the table and create a new item if it doesn't exist.

In the first run, it worked as expected, checked the existence of the item and performed a mutation to create one as it doesn't exist. I go to DynamoDB and verified that the item is created successfully. After that, I test the lambda again, but the query doesn't return the item I just created, so it created the item again. The interesting part is, if I upload the same code stored in S3 and test the lambda again, it works. The query returns every item I created in the past.

Here is the code of my lambda.

index.js

export async function handler(event, context) {
    console.log("List item in DB");
    var items = await getItems(event.iccid, event.imei);

    if (items.length == 0) {
        console.log("No item found");
        await createItem (event);
    } else {
        console.log("Item already exist");
        console.log(items[0]);
    }
}

async function getItems(iccid, imei) {
    const queryObj = getItemObj;

    const variables = {
        filter: {
            imei: { eq: imei },
            iccid: { eq: iccid },
            _deleted: { ne: true },
        },
    };

    try {
        const { data } = await client.query({
            query: queryObj,
            variables: variables,
        });
        console.log("(Query): Retrieving Data ----------->", data.listItems.items);
        return data.listItems.items;
    } catch (error) {
        console.error("Error!", error);
        throw error;
    }
}

async function createItem(event) {
    console.log("creating");

    const mutationObj = createItemObj;

    const variables = {
        iccid: event.iccid,
        imei: event.imei,
        _version: 1,
    };

  try {
      const { data } = await client.mutate({
          mutation: mutationObj,
          variables: { input: variables },
      });

      console.log("(Mutate): Creating Data ----------->", data);
  } catch (error) {
      console.error("Error!", error);
      throw error;
  }
}

query.js

import gql from "graphql-tag";
import "cross-fetch/dist/node-polyfill.js";

var getItemObj = gql(`query listItems($filter: ModelItemFilterInput!) {
    listItems(filter: $filter) {
        items {
            id
            iccid
            imei
            _deleted
            _version
        }
    }
}`);

export default getItemObj;

What am I missing?


Solution

  • After days of debugging, I finally find the solution. The problem could be caused by the caching feature of DynamoDB. It reuses the stored data to reduce the time taken for content served to the user. To avoid this, I added await client.clearStore() to force it to clear the cache before calling getItem so that the query returns the most updated items stored in the db.

    export async function handler(event, context) {
        console.log("List item in DB");
        await client.clearStore();
        var items = await getItems(event.iccid, event.imei);
    
        if (items.length == 0) {
            console.log("No item found");
            await createItem (event);
        } else {
            console.log("Item already exist");
            console.log(items[0]);
        }
    }
    
    async function getItems(iccid, imei) {
        const queryObj = getItemObj;
    
        const variables = {
            filter: {
                imei: { eq: imei },
                iccid: { eq: iccid },
                _deleted: { ne: true },
            },
        };
    
        try {
            const { data } = await client.query({
                query: queryObj,
                variables: variables,
            });
            console.log("(Query): Retrieving Data ----------->", data.listItems.items);
            return data.listItems.items;
        } catch (error) {
            console.error("Error!", error);
            throw error;
        }
    }
    
    async function createItem(event) {
        console.log("creating");
    
        const mutationObj = createItemObj;
    
        const variables = {
            iccid: event.iccid,
            imei: event.imei,
            _version: 1,
        };
    
      try {
          const { data } = await client.mutate({
              mutation: mutationObj,
              variables: { input: variables },
          });
    
          console.log("(Mutate): Creating Data ----------->", data);
      } catch (error) {
          console.error("Error!", error);
          throw error;
      }
    }