我正在使用RavenDB作为从域事件填充的非规范化读取模型。我发现问题,当两个事件(让我们称之为Created和Updated)同时进行非规范化时,在保存Created事件所做的更改之前,加载要由Updated事件更新的文档。我想出了基于Changes API的解决方案来等待文档创建:
public static T WaitAndLoad<T>(this IDocumentSession @this, ValueType id)
where T : class
{
var fullId = @this.Advanced.DocumentStore.Conventions.FindFullDocumentKeyFromNonStringIdentifier(id, typeof(T), false);
var ev = new ManualResetEvent(false);
var cancelation = new CancellationTokenSource();
@this.Advanced.DocumentStore
.Changes()
.ForDocument(fullId)
.Subscribe(change =>
{
if (change.Type == DocumentChangeTypes.Put)
{
ev.Set();
}
}, cancelation.Token);
try
{
var existing = @this.Load<T>(id);
if (existing != null)
{
return existing;
}
ev.WaitOne();
return @this.Load<T>(id);
}
finally
{
cancelation.Cancel();
}
}
不幸的是,对Load的第二次调用返回null,因为文档的Id已经在InMemoryDocumentSessionOperations中的knownMissingIds字段中,并且没有对服务器发出请求。
还有其他方法可以等到创建文档吗?
答案 0 :(得分:2)
好吧,我不确定你使用什么机制进行事件处理,但是我遇到类似NServiceBus的情况。我不认为这完全是RavenDB问题。如果您正在写入SQL Server数据库,则可能会遇到相同的问题。
广义问题是,Create
和Update
事件被触发,但它们以错误的顺序被接收和处理。怎么办?
一般的建议是你的事件处理程序应该是幂等的,should retry when failed。因此,如果首先收到Update
,它将抛出异常并安排重试。然后Create
出现,然后Update
重试,一切都很好。
不建议在Update
事件的处理程序中特别阻塞和等待,因为如果你有其中的几个,那么它们可以阻止所有工作线程,Create
事件永远不会通过。< / p>