假设您有一个使用表存储的Azure函数(v2),可以运行,但是存在SomePartitionKey / SomeRowKey的实体存在(例如,您两次运行以下内容):
[FunctionName("SomeEntity")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "someentity")] HttpRequest req,
[Table("SomeEntities")] IAsyncCollector<SomeEntity> collector,
ILogger logger)
{
try
{
SomeEntity se = new SomeEntity()
{
PartitionKey = "SomePartitionKey",
RowKey = "SomeRowKey"
};
await collector.AddAsync(se);
await collector.FlushAsync();
return new OkResult();
}
catch (Microsoft.WindowsAzure.Storage.StorageException e)
{
logger.LogError("There was an error processing the request.", e);
return new StatusCodeResult(409);
}
}
当此方法运行并且该实体已经存在时,如预期的那样,它将引发StorageException。我的问题是,即使我捕获到异常并尝试返回StatusCodeResult(409)
实际发送给客户端的响应,始终是内部服务器错误(500)。
我的问题是:
a)这是否是函数的清除逻辑尝试FlushAsync()
再次在收集器上调用的结果,导致未处理的StorageException导致内部服务器错误(500)。b)如果a)是,是否可以防止这种情况?
c)除了首先检查实体是否存在之外,此场景是否有最佳实践?
关于Azure Functions NuGet软件包的一大优点是它们启用了源链接。确保已Enable Source Link support
签入Visual Studio选项,并且您将能够准确看到他们的代码在做什么。一旦功能应用程序运行,您就可以选择在引发任何CLR异常时中断。
如果执行此操作,您将看到异常从抛出FlushAsync
,您的代码正在捕获该异常,并返回409结果。然后,在函数返回之后,将再次引发相同的异常(因为FlushAsync
在函数外部再次调用了该异常),并捕获了该异常Error while handling parameter collector after function returned
,并在message中引发了包装异常,而该异常又被捕获,并在消息中引发了包装异常Exception while executing function: SomeEntity
,而该错误又被捕获,并且只会向客户端返回一个简单的旧500错误。
所以:
a)这是否是该函数的清理逻辑的结果,该逻辑试图再次在收集器上调用FlushAsync(),导致未处理的StorageException导致内部服务器错误(500)。
是。如果启用“源链接”支持和“抛出时断开”,则可以直接通过Azure Functions运行时进行调试,并观察到这种情况。
b)如果a)是,是否可以防止这种情况?
c)除了首先检查实体是否存在之外,此场景是否有最佳实践?
我不建议先检查然后插入。您最终将面临比赛条件。
从文档:
此输出绑定不支持更新现有实体。使用
TableOperation.Replace
Azure存储SDK中的操作来更新现有实体。
通常,任何给定服务的Azure Functions绑定都是针对简单用例的。对于Azure存储表,简单的用例只是插入实体。
但是,您始终可以自己使用Storage SDK。无论如何,这几乎就是绑定为您所做的。该绑定也进行了一些批处理,但是如果需要的话,实现起来并不难。
您还可以执行“半路”:将Tables绑定绑定到CloudTable
而不是IAsyncCollector<SomeEntity>
。这样,您将自动使用适当的连接字符串。您只需要编写自己的TableOperation.InsertOrReplace
代码即可。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句