2013-07-28 2 views
1

Я использую RavenDB как денормализованную модель чтения, заполненную событиями домена. Я обнаружил проблему, когда два события (назовем их «Создано и обновлено») денормализуются одновременно, загружая документ, который будет обновляться обновленным событием, происходит до сохранения изменений, внесенных созданным событием. Я придумал решение, основываясь на изменениях 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(); 
     }    
    } 

К сожалению, второй вызов Load возвращает нуль, потому что Id документа уже в поле knownMissingIds в InMemoryDocumentSessionOperations и никакого запроса к серверу не производится.

Есть ли какой-либо другой способ подождать, пока не будет создан документ?

ответ

2

Ну, я не уверен, какой механизм вы используете для обработки событий, но я был в аналогичной ситуации с чем-то вроде NServiceBus. Я не думаю, что это именно проблема RavenDB. Вероятно, у вас была бы такая же проблема, если бы вы писали в базу данных SQL Server.

Общая проблема заключается в том, что Create и Update события увольняются, но они принимаются и обрабатываются в неправильном порядке. Что делать?

Ну, общий совет заключается в том, что ваши обработчики событий должны быть идемпотентными, и should retry when failed. Поэтому, если сначала получено Update, оно будет вызывать исключение и планироваться для повторной попытки. Затем приходит Create, затем Update повторяет попытку и все это хорошо.

В частности, блокировка и ожидание в обработчике события Update не рекомендуется, так как если бы у вас было несколько из них, они могли бы блокировать все рабочие потоки, и события Create никогда не пройдут.

Смежные вопросы