RavenDB - 等待文档创建

时间:2013-07-28 13:01:03

标签: c# ravendb

我正在使用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字段中,并且没有对服务器发出请求。

还有其他方法可以等到创建文档吗?​​

1 个答案:

答案 0 :(得分:2)

好吧,我不确定你使用什么机制进行事件处理,但是我遇到类似NServiceBus的情况。我不认为这完全是RavenDB问题。如果您正在写入SQL Server数据库,则可能会遇到相同的问题。

广义问题是,CreateUpdate事件被触发,但它们以错误的顺序被接收和处理。怎么办?

一般的建议是你的事件处理程序应该是幂等的,should retry when failed。因此,如果首先收到Update,它将抛出异常并安排重试。然后Create出现,然后Update重试,一切都很好。

不建议在Update事件的处理程序中特别阻塞和等待,因为如果你有其中的几个,那么它们可以阻止所有工作线程,Create事件永远不会通过。< / p>