1

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

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

4

1 回答 1

2

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

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

一般的建议是您的事件处理程序应该是幂等的,并且应该在失败时重试。所以如果Update先收到,就会抛出异常,并安排重试。然后Create通过,然后Update重试,一切都很好。

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

于 2013-07-28T18:50:38.247 回答