Azure function and Azure storage - Entity already exists - nodeJS

537 Views Asked by At

I'm aware of the different methods to insert an entity in an azure storage table but I Cannot find a solution for this:

Although my function is triggered by a queue, looks like that sometimes the entity that is trying to insert already exists in my table.

The RowKey is generated using two math-random with numbers of 4 digits, I understand this might not be ideal because the same number can occur multiple time but how do you manage this kind of execption?

I use output binding to send data to the table and although this binding should try 5 times before killing the function process, I'm getting only 1 try. (Do I need to check any configuration?)

Is it possible to catch the error when happen and increment the rowkey by 1 or more before resubmitting? If yes do you have any example for me to follow?

it does not matter if this is done with the output binding or the JS sdk.

Edit: I did some tests: This is kind of working, but it is legit?

var azure = require('azure-storage');
var tableSvc = azure.createTableService(process.env.AzureWebJobsStorage);

module.exports = async function (context, myQueueItem) {
    context.log('JavaScript queue trigger function processed work item', myQueueItem);

    var partkey = "Test"
    var rokey = 39


    try {
        context.bindings.outputTable = [];
        context.bindings.outputTable.push({

            PartitionKey: partkey,
            RowKey: rokey,
            Name: "Test"
        });
    } finally {
        context.bindings.outputTable = [];
        context.bindings.outputTable.push({

            PartitionKey: partkey,
            RowKey: rokey + 1,
            Name: "Test"
        });
    }
}

Now 40 exists, if I run again the same will stop on the finally again because will not loop till is resolved.

Should I instead query the table (that has a large number of entry) to check if the key exist before entering the new entity? will this not take long time?

Thank you very much for your help

edit1: I've been reading that I cannot really catch the output binding errors on the exection, so I've tried with tableservice (node js sdk)

var azure = require('azure-storage');
var tableSvc = azure.createTableService(process.env.AzureWebJobsStorage);

module.exports = async function (context, myQueueItem) {
    context.log('JavaScript queue trigger function processed work item', myQueueItem);

    var partkey = "Test"
    var rokey = "39"

var a = {
    PartitionKey: partkey,
    RowKey: rokey,
    Name: "ZuzzuS!"
};


tableSvc.insertEntity('TestTable', a, function(error, result, response) {
    if(error) {
        // Insert table entity error
        context.log.error("There was an error!")
    } else {
        // Insert table entity successfully
    }
});

}

This should give error because the entity exists, instead the function go ahead and complete without doing nothing.

1

There are 1 best solutions below

3
On

Regarding the issue, you can use the method insertOrMergeEntity. If the entity does not exist, the method will insert the entity. Otherwise, the method will update the entity within a table by merging new property values into the entity. For more details, please refer to here.

Besides, if you just want to do insert operations, please refer to the following code

var azure = require("azure-storage");
var accountName = "andyprivate";
var accountKey =
  "h4pP1fe76m8hdksFW3TvkO6hgw09Mjue7yJOnULPI/g2eU8LGJ+a6k6SrU6dUkOU77waZfU8CacyVMlTWAUA5A==";
var tableSvc = azure.createTableService(accountName, accountKey);

var entGen = azure.TableUtilities.entityGenerator;
module.exports = async function (context, myQueueItem) {
  context.log(
    "JavaScript queue trigger function processed work item",
    myQueueItem
  );

  var partkey = "Test";
  var rokey = 29;
  var task = {
    PartitionKey: entGen.String(partkey),
    RowKey: entGen.String(String(rokey)),
    description: entGen.String("take out the trash"),
  };

  try {
    const r = await insert("test", task);
  } catch (error) {
    if (error.code == "EntityAlreadyExists") {
      context.log(error);
     // insert 
    }
  }
};

async function insert(tableName, entity) {
  return new Promise((resolve, reject) => {
    tableSvc.insertEntity(tableName, entity, (error, result) => {
      if (error) {
        reject(error);
      } else {
        resolve("OK");
      }
    });
  });
}

enter image description here