Как перехватить исключение таблицы Azure в асинхронной функции Azure, запускаемой по протоколу HTTP

У меня есть функция Azure, активируемая 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 два вызова зависимости таблицы на запрос (не должно происходить, в документации говорится, что таблица не имеет автоматического повтора)

Вы не перехватываете все типы исключений, поэтому, конечно, исключение может просочиться. Вы на 100% уверены, что не пропустили исключение из-за отсутствия общего блока system.exception catch?

Charleh 23.02.2019 10:52

Также возможно, но он сказал, что поток входит в блок catch и все равно сообщает 500.

kamil-mrzyglod 23.02.2019 14:38

@Charleh Я уже проводил эксперименты, прежде чем пришел сюда, чтобы спросить, и перехват Exception просто не работает. Предоставленный код является минимальной версией для воспроизведения проблемы, это не то, что я написал в реальном проекте.

Jamesits 23.02.2019 14:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
904
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ваш блок try/catch должен выглядеть следующим образом, чтобы перехватывать все ошибки.

try
{

}
catch (StorageException)
{
    return new OkObjectResult("This passes test");
}
catch (Exception ex)
{
    // return different error code
}

Предоставленный код является лишь минимальной версией для воспроизведения проблемы. В моем собственном коде я пробовал несколько способов, включая перехват общего исключения, и у меня есть обширное ведение журнала, поэтому я почти уверен, что StorageException является единственным типом исключения.

Jamesits 23.02.2019 14:42
Ответ принят как подходящий

Я думаю, что использование IAsyncCollector<> здесь все ломает. Если вы хотите избежать подобных проблем, попробуйте поменять следующую привязку:

[Table("Debug")] IAsyncCollector<Entry> tableBinding

к:

[Table("Debug")] CloudTable tableBinding

Затем вместо использования tableBinding.AddAsync() используйте следующий фрагмент:

var op = TableOperation.Insert(new Entry());
await tableBinding.ExecuteAsync(op);

При таком подходе вы должны иметь возможность перехватывать исключение, не пропуская его в среду выполнения функций.

Это работает для меня. Примечание: класс Entry должен реализовать TableEntity.

Jamesits 23.02.2019 15:15

Другие вопросы по теме