Как перехватить исключительную ситуацию по таблице Azure в асинхронной функции Azure HTTP
У меня есть триггерная функция Azure Function HTTP, которая пишет в таблицу Azure, которая может заканчиваться дублированием записей. Я заметил, что даже если я попытаюсь / поймать всю функцию, все равно будет исключение, "просочившееся" исполнителю функции, таким образом возвращая HTTP 500. Есть ли способ перехватить такого рода исключения?
Вот сокращенная версия кода:
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.WindowsAzure.Storage;
namespace FunctionTest
{
public class Entry
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
}
public static class Debug
{
[FunctionName("Debug")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)]
HttpRequest req,
[Table("Debug")]
IAsyncCollector<Entry> tableBinding,
ILogger log)
{
try
{
await tableBinding.AddAsync(new Entry()
{
PartitionKey = "1111",
RowKey = "1111",
});
await tableBinding.FlushAsync();
}
catch (StorageException)
{
// we expect an Exception "The specified entity already exists"
return new OkObjectResult("This passes test");
}
return new OkObjectResult("This passes test too");
}
}
}
Код написан в среде исполнения функций Azure 2.0 (.NET Core).
Спусковой крючок /api/debug
дважды или больше, и вы увидите:
- HTTP 500
catch{}
код введен и все еще возвращает HTTP 500(!)- В Application Insights два вызова зависимости таблицы на запрос (не должно происходить, в документации сказано, что в таблице нет автоматического повтора)
2 ответа
Я думаю, что с помощью IAsyncCollector<>
ломает вещи здесь. Если вы хотите избежать подобных проблем, попробуйте заменить следующую привязку:
[Table("Debug")] IAsyncCollector<Entry> tableBinding
чтобы:
[Table("Debug")] CloudTable tableBinding
Тогда вместо использования tableBinding.AddAsync()
используйте следующий фрагмент:
var op = TableOperation.Insert(new Entry());
await tableBinding.ExecuteAsync(op);
При таком подходе вы сможете перехватить исключение, не передавая его в среду выполнения функций.
Ваш блок try/catch должен выглядеть следующим образом, чтобы перехватить все ошибки
try
{
}
catch (StorageException)
{
return new OkObjectResult("This passes test");
}
catch (Exception ex)
{
// return different error code
}