我正在摆弄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;,否则我无法将替代标记作为答案。我并不寻求解决问题的最佳方法,我希望它按照我设计的方式工作。我知道这很顽固,但这是练习/摆弄。
答案 0 :(得分:1)
Blob租约确实可以很好地用于您正在尝试完成的任务(函数运行时实际上在内部广泛使用它)。
如果在处理分区之前,您获得blob上的租约(按照惯例,以分区命名的blob或类似的东西),您将能够确保只有给定的函数正在处理那个分区。
您链接的文章确实显示了租约获取和发布的示例,您可以在documentation中找到更多信息。
您要确保的一件事是,在离开锁定范围(通过调用FlushAsync
之前)冲洗收集器
我希望这有帮助!