0

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.

varVal
  • 27
  • 7

1 Answers1

0

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

Jim Xu
  • 21,610
  • 2
  • 19
  • 39
  • Hello, thank you for the suggestion, as I don't need to replace I cannot use insertOrReplace as we want to keep a sort of records of what's happening. With your code will insert the entity if does not exists, otherwise will just skip it I guess. Can I add something to retry with a different rowkey? – varVal May 28 '21 at 07:58
  • @varVal You can add insert operation into code `if (error.code == "EntityAlreadyExists") { context.log(error); }` – Jim Xu May 28 '21 at 08:04
  • @varVal For example `if (error.code == "EntityAlreadyExists") { context.log(error); task = { PartitionKey: entGen.String(partkey), RowKey: entGen.String(), description: entGen.String("take out the trash"), }; await insert("test", task);` – Jim Xu May 28 '21 at 08:06