在Azure Functions中修改CosmosDb文档会触发无限循环

问题描述 投票:0回答:2

插入/更新CosmosDB文档时,我尝试更新Azure函数中的文档。

但是,当我更新函数内部的文档时,该函数再次被触发并导致无限循环。

private static DocumentClient _documentClient = new DocumentClient(new Uri(serviceEndpoint), key);

[FunctionName(nameof(MyFunction))]
public static async Task RunAsync([CosmosDBTrigger(
    databaseName: "MyDatabase",
    collectionName: "MyCollection",
    ConnectionStringSetting = "MyDbConnectionString",
    LeaseCollectionName = "leases",
    CreateLeaseCollectionIfNotExists = true,
    LeaseCollectionPrefix = nameof(MyFunction))]IReadOnlyList<Document> input,
    ILogger log)
{
    var replacementsTasks = new List<Task>();

    foreach (var item in input)
    {
        item.SetPropertyValue("Updated", true);
        replacementsTasks.Add(_documentClient.ReplaceDocumentAsync(item));
    }

    await Task.WhenAll(replacementsTasks);
}

我怎么能阻止这个?我可以使用CosmosDB out结果和触发器中的修改文档吗?

更新1

我不想使用其他收藏品。这将使CosmosDB的定价翻倍。我尝试使用CosmosDB输入和输出以下内容。然而,我得到了相同的结果。无限循环。

[FunctionName(nameof(DownloadImages))]
public static void Run(
    [CosmosDBTrigger(
    databaseName: database,
    collectionName: collection,
    ConnectionStringSetting = connectionStringName,
    LeaseCollectionName = "leases",
    CreateLeaseCollectionIfNotExists = true,
    LeaseCollectionPrefix = nameof(MyFunction))]IReadOnlyList<Document> input,
    [CosmosDB(database, collection, Id = "id", ConnectionStringSetting = connectionStringName)] out dynamic document,
    ILogger log)
{

    if(input.Count != 1) throw new ArgumentException();

    document = input.Single();
    document.myValue = true;
}
c# azure azure-functions azure-cosmosdb infinite-loop
2个回答
0
投票

如果您不能使用其他集合,那么实际上没有其他选择。插入或更新新文档时,触发器会有效触发。如果您的触发器正在监视它的同一个集合中更新/插入文档,它将有效地创建一个循环。

这就像使用QueueTrigger并在同一个Queue中插入消息一样,无限循环适用于任何Trigger机制。

你可以做的一件事是过滤那些已经更新过的东西:

private static DocumentClient _documentClient = new DocumentClient(new Uri(serviceEndpoint), key);

[FunctionName(nameof(MyFunction))]
public static async Task RunAsync([CosmosDBTrigger(
    databaseName: "MyDatabase",
    collectionName: "MyCollection",
    ConnectionStringSetting = "MyDbConnectionString",
    LeaseCollectionName = "leases",
    CreateLeaseCollectionIfNotExists = true,
    LeaseCollectionPrefix = nameof(MyFunction))]IReadOnlyList<Document> input,
    ILogger log)
{
    var replacementsTasks = new List<Task>();

    foreach (var item in input)
    {
        if (!item.GetPropertyValue<bool>("Updated")) {
            item.SetPropertyValue("Updated", true);
            replacementsTasks.Add(_documentClient.ReplaceDocumentAsync(item));
        }
    }

    await Task.WhenAll(replacementsTasks);
}

0
投票

建议的方法是在以下文档https://docs.microsoft.com/en-us/azure/cosmos-db/serverless-computing-database中提到的

Azure Cosmos数据库触发器可与输出绑定一起使用,以绑定到其他Azure Cosmos数据库容器。在函数对更改源中的项执行操作后,您可以将其写入另一个容器(将其写入它来自的同一容器将有效地创建递归循环)。或者,您可以使用Azure Cosmos DB触发器通过使用输出绑定将所有已更改的项目从一个容器有效迁移到另一个容器。

Azure Cosmos DB的输入绑定和输出绑定可以在同一Azure功能中使用。当您想要使用输入绑定查找某些数据,在Azure函数中修改它,然后在修改后将其保存到同一容器或不同的容器中时,这种方法很有效。

© www.soinside.com 2019 - 2024. All rights reserved.