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

And*_*ter 3 c# infinite-loop azure azure-functions azure-cosmosdb

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

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

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);
}
Run Code Online (Sandbox Code Playgroud)

我怎样才能防止这种情况发生?我可以将 CosmosDB 输出结果与触发器中修改后的文档一起使用吗?

更新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;
}
Run Code Online (Sandbox Code Playgroud)

Mat*_*nta 5

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

这就像使用 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);
}
Run Code Online (Sandbox Code Playgroud)