25

RavenDb で単体テストを行う場合、新しく追加されたデータが取得されるか、その他の方法で処理されることがよくあります。これにより、「古いインデックス」例外が発生する可能性があります。

Bulk operation cancelled because the index is stale and allowStale is false

数々の回答によると

IDocumentStoreクエリまたはバッチ操作を処理する前にインデックスが古くなくなるまでデータベース (インスタンス) を強制的に待機させる方法は、次のように初期化DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites中に使用することです。IDocumentStore

public class InMemoryRavenSessionProvider : IRavenSessionProvider
{
    private static IDocumentStore documentStore;

    public static IDocumentStore DocumentStore
    {
        get { return (documentStore ?? (documentStore = CreateDocumentStore())); }
    }

    private static IDocumentStore CreateDocumentStore()
    {
        var store = new EmbeddableDocumentStore
        {
            RunInMemory = true,
            Conventions = new DocumentConvention
            {
                DefaultQueryingConsistency = ConsistencyOptions.QueryYourWrites,
                IdentityPartsSeparator = "-"
            }
        };
        store.Initialize();
        IndexCreation.CreateIndexes(typeof (RavenIndexes).Assembly, store);
        return store;
    }

    public IDocumentSession GetSession()
    {
        return DocumentStore.OpenSession();
    }
}

残念ながら、上記のコードは機能しません。古いインデックスに関する例外が引き続き発生します。これらは、 を含むダミー クエリを挿入することで解決できます.Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())

これらが単体テストに含まれている限り、これは問題ありませんが、そうでない場合はどうなりますか? これらのWaitForNonStaleResults*呼び出しが製品コードに忍び込んでいることがわかりました。これは、単体テストに合格できるようにするためです。

では、最新バージョンの RavenDb を使用して、コマンドの処理を許可する前にインデックスを強制的に更新する確実な方法はありますか?

編集 1

これは、以下の回答に基づく解決策であり、インデックスが古くなくなるまで強制的に待機します。単体テストの利便性のために、拡張メソッドとして記述しました。

public static class IDocumentSessionExt
{
    public static void ClearStaleIndexes(this IDocumentSession db)
    {
        while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
        {
            Thread.Sleep(10);
        }
    }
}

WaitForNonStaleResultsAsOfLastWriteこれは、冗長な手法を使用していたが、より適切な拡張方法を使用する単体テストです。

[Fact]
public void Should_return_list_of_Relationships_for_given_mentor()
{
    using (var db = Fake.Db())
    {
        var mentorId = Fake.Mentor(db).Id;
        Fake.Relationship(db, mentorId, Fake.Mentee(db).Id);
        Fake.Relationship(db, mentorId, Fake.Mentee(db).Id);
        Fake.Relationship(db, Fake.Mentor(db).Id, Fake.Mentee(db).Id);

        //db.Query<Relationship>()
        //  .Customize(x => x.WaitForNonStaleResultsAsOfLastWrite())
        //  .Count()
        //  .ShouldBe(3);

        db.ClearStaleIndexes();
        db.Query<Relationship>().Count().ShouldBe(3);
        MentorService.GetRelationships(db, mentorId).Count.ShouldBe(2);
    }
}
4

3 に答える 3

30

Map/Reduce インデックスがある場合は機能しDefaultQueryingConsistency = ConsistencyOptions.QueryYourWritesません。別の方法を使用する必要があります。

単体テストでは、データを挿入した直後に次のようなコードを呼び出します。これにより、他の操作を行う前にすべてのインデックスが強制的に更新されます。

while (documentStore.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
{
    Thread.Sleep(10);
}

更新したい場合は、もちろん拡張メソッドに入れることができます。

public static class IDocumentSessionExt
{
    public static void ClearStaleIndexes(this IDocumentSession db)
    {
        while (db.Advanced.DatabaseCommands.GetStatistics().StaleIndexes.Length != 0)
        {
            Thread.Sleep(10);
        }
    }
}

次に、次のように言うことができます。

db.ClearStaleIndexes();
于 2012-04-25T13:57:07.837 に答える
14

DocumentStore にクエリ リスナを実際に追加して、古くない結果を待つことができます。これは、各操作ではなくドキュメント ストアにあるため、単体テストにのみ使用できます。

// Initialise the Store.
var documentStore = new EmbeddableDocumentStore
                {
                    RunInMemory = true
                };
documentStore.Initialize();

// Force queries to wait for indexes to catch up. Unit Testing only :P
documentStore.RegisterListener(new NoStaleQueriesListener());

....


#region Nested type: NoStaleQueriesListener

public class NoStaleQueriesListener : IDocumentQueryListener
{
    #region Implementation of IDocumentQueryListener

    public void BeforeQueryExecuted(IDocumentQueryCustomization queryCustomization)
    {
        queryCustomization.WaitForNonStaleResults();
    }

    #endregion
}

#endregion

(恥知らずにRavenDB から盗んだものをフラッシュする方法は? )

于 2012-04-25T14:27:57.063 に答える
2

StaleIndexes には、破棄された無効なインデックスも含まれていることに注意してください。これらは最新の状態にはなりません。

したがって、無期限に待機しないようにするには、代わりにこのプロパティを使用します。

 var staleIndices = store.DatabaseCommands.GetStatistics().CountOfStaleIndexesExcludingDisabledAndAbandoned;
于 2017-07-31T11:02:00.883 に答える