如何使用IQueryable和IAsyncCollector在Azure函数中锁定Azure表分区?

时间:2016-11-02 19:44:59

标签: c# concurrency locking azure-table-storage azure-functions

我正在摆弄Azure功能,将其与CQRS和事件采购相结合。我使用Azure表存储作为事件存储。下面的代码是一个简化版本,不会分散注意力。

我对任何代码提示都不感兴趣,因为这不是代码的最终版本。

public static async Task Run(BrokeredMessage commandBrokeredMessage, IQueryable<DomainEvent> eventsQueryable, IAsyncCollector<IDomainEvent> eventsCollector, TraceWriter log)
{
    var command = commandBrokeredMessage.GetBody<FooCommand>();
    var committedEvents = eventsQueryable.Where(e => e.PartitionKey = command.AggregateRootId);
    var expectedVersion = committedEvents .Max(e => e.Version);

    // some domain logic that will result in domain events
    var uncommittedEvents = HandleFooCommand(command, committedEvents);

    // using(Some way to lock partition)
    // {
    var currentVersion = eventsQueryable.Where(e => e.PartitionKey = command.AggregateRootId).Max(e => e.Version);

    if(expectedVersion != currentVersion)
    {
        throw new ConcurrencyException("expected version is not the same as current version");
    }

    var i = currentVersion;
    foreach (var domainEvent in uncommittedEvents.OrderBy(e => e.Timestamp))
    {
        i++;
        domainEvent.Version = i;
        await eventsCollector.AddAsync(domainEvent);
    }
    // }
}

public class DomainEvent : TableEntity
{
    private string eventType;

    public virtual string EventType
    {
        get { return eventType ?? (eventType = GetType().UnderlyingSystemType.Name); }
        set { eventType = value; }
    }

    public long Version { get; set; }
}

我的努力

公平地说,我无法尝试任何事情,因为我不知道从哪里开始,如果可能的话。我做了一些没有解决我的问题的研究,但可以帮助你解决这个问题。

Azure表是否支持锁定? 是的,他们这样做:Managing Concurrency in Microsoft Azure Storage。它被称为租赁,但我不知道如何在Azure功能中实现它。

其他来源

提示,建议,备选方案

我总是对如何解决问题的任何建议持开放态度,但我不能接受这些作为我问题的答案。除非我的问题的答案是&#34;否&#34;,否则我无法将替代标记作为答案。我并不寻求解决问题的最佳方法,我希望它按照我设计的方式工作。我知道这很顽固,但这是练习/摆弄。

1 个答案:

答案 0 :(得分:1)

Blob租约确实可以很好地用于您正在尝试完成的任务(函数运行时实际上在内部广泛使用它)。

如果在处理分区之前,您获得blob上的租约(按照惯例,以分区命名的blob或类似的东西),您将能够确保只有给定的函数正在处理那个分区。

您链接的文章确实显示了租约获取和发布的示例,您可以在documentation中找到更多信息。

您要确保的一件事是,在离开锁定范围(通过调用FlushAsync之前)冲洗收集器

我希望这有帮助!