2013-07-28 60 views
1

我使用RavenDB作为从域事件填充的非规范化读取模型。我发现问题,当两个事件(让我们称它们为“已创建”和“已更新”)在同一时间被非规范化时,在保存Created事件所做的更改之前,会发生由更新事件更新的加载文档。我已经与解决方案基于API的变化上来,以等待创建文件:RavenDB - 等待文档创建

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(); 
     }    
    } 

不幸的是第二次调用加载返回null,原因的文件ID已在knownMissingIds领域InMemoryDocumentSessionOperations和服务器发出任何请求。

有没有其他方式可以等到创建文档?

回答

2

嗯,我不知道你用于事件处理的是什么机制,但我一直在类似的情况下,像NServiceBus。我不认为这完全是一个RavenDB问题。如果您正在写入SQL Server数据库,您可能会遇到同样的问题。

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

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

不建议在处理程序中特别阻塞和等待Update事件,因为如果您有几个这样的事件,那么它们可以阻止所有工作线程,并且事件永远不会通过。