private static void GetStore(out IStateReader reader, out IStateWriter writer) { var store = new InMemoryStateStore(Guid.NewGuid().ToString()); reader = new InMemoryStateReader(store); writer = new InMemoryStateWriter(store, CheckpointKind.Full); }
public void Recovery() { DisposeEngineCore(); CreateEngine(); using var reader = new InMemoryStateReader(_stateStore); _queryEngine.RecoverAsync(reader).Wait(); }
public void TwoQueryEnginesFirstFailAndRecover() { var qe1Id = "qe:/1/" + Guid.NewGuid(); var qe2Id = "qe:/2/" + Guid.NewGuid(); Uri sub = new Uri("bing:/sub1"); IObserver <int> o1s; MockObservable <int> o1; MockObserver <int> v1; IReactiveQubscription sub1; InMemoryStateStore store; CheckpointingQueryEngine qe1 = CreateQueryEngine(qe1Id); var ctx1 = GetQueryEngineReactiveService(qe1); var qe2 = CreateQueryEngine(qe2Id); var ctx2 = GetQueryEngineReactiveService(qe2); // // BUG: There's a known test bug here with the resolver not being smart enough to deal with a disposed // upstream engine. When QE2 triggers disposal of the upstream subscription (after having sent 5 // events causing Take to reach OnCompleted and thus disposing its source), its InputEdge is faced // with an external subscription into the original QE1 instance. If this instance got disposed by // means of `using (qe1)`, an ObjectDisposedException will propagate out of QE1 into the Dispose // path triggered inside QE2. // // In a real setup, the resolver returns IReactive interface implementations that encapsulate a // transport layer where failures are detected and re-resolution takes place if there's a broken // channel. For this particular case, the original instance of QE1 having disappeared would result // in such an error (e.g. having failed over to another node in a cluster). // // For our test setup, we lack re-resolution logic, so disposing QE1 is problematic. One option is // to rewrite the mock resolver to have proper failure detection. Alternatively, this test would // have to be built on a more realistic setup (e.g. using the remoting stack). // //using (qe1) { AssertObservableNotCreated <int>("o1"); AssertObserverNotCreated <int>("v1"); ctx1.DefineObservable <int>( new Uri(qe1Id + "/obs1"), ctx1.GetObservable <string, int>(MockObservableUri)("o1").Where(x => x > 0).Take(10), null); var obs1 = ctx1.GetObservable <int>(new Uri(qe1Id + "/obs1")); ctx2.DefineObservable <int>( new Uri(qe2Id + "/obs2"), obs1.Where(x => x % 2 == 1).Take(5), null); var obs2 = ctx2.GetObservable <int>(new Uri(qe2Id + "/obs2")); sub1 = obs2.Subscribe( ctx2.GetObserver <string, int>(MockObserverUri)("v1"), sub, null); o1 = MockObservable.Get <int>("o1"); Assert.IsNotNull(o1); Assert.AreEqual(1, o1.SubscriptionCount); o1s = o1.Synchronize(qe1.Scheduler); v1 = GetMockObserver <int>("v1"); for (int i = 0; i < 4; i++) { o1s.OnNext(i); } Assert.IsTrue(v1.WaitForCount(2, Timeout)); Assert.IsFalse(v1.Completed); Assert.IsFalse(v1.Error); AssertResult(v1, 2, (i, v) => Assert.AreEqual(i * 2 + 1, v)); store = Checkpoint(qe1); RemoveQueryEngine(qe1); } o1.DropAllSubscriptions(); Assert.AreEqual(0, o1.SubscriptionCount); qe1 = CreateQueryEngine(qe1Id); //using (qe1) { using (var stateReader = new InMemoryStateReader(store)) { qe1.RecoverAsync(stateReader).Wait(); } Assert.AreEqual(1, o1.SubscriptionCount); o1s = o1.Synchronize(qe1.Scheduler); for (int i = 4; i < 20; i++) { o1s.OnNext(i); } Assert.IsTrue(v1.WaitForCount(5, Timeout)); Assert.IsTrue(v1.WaitForCompleted(Timeout)); Assert.IsTrue(v1.Completed); Assert.IsFalse(v1.Error); sub1.Dispose(); Assert.AreEqual(0, o1.SubscriptionCount); AssertResult(v1, 5, (i, v) => Assert.AreEqual(i * 2 + 1, v)); } }
public void TwoQueryEnginesSecondFailAndRecover() { var qe1Id = "qe:/1/" + Guid.NewGuid(); var qe2Id = "qe:/2/" + Guid.NewGuid(); Uri sub = new Uri("my:/sub1"); IObserver <int> o1s; MockObservable <int> o1; MockObserver <int> v1; InMemoryStateStore store; var qe1 = CreateQueryEngine(qe1Id); { var ctx1 = GetQueryEngineReactiveService(qe1); var qe2 = CreateQueryEngine(qe2Id); { var ctx2 = GetQueryEngineReactiveService(qe2); AssertObservableNotCreated <int>("o1"); AssertObserverNotCreated <int>("v1"); ctx1.DefineObservable <int>( new Uri(qe1Id + "/obs1"), ctx1.GetObservable <string, int>(MockObservableUri)("o1").Where(x => x > 0).Take(10), null); var obs1 = ctx1.GetObservable <int>(new Uri(qe1Id + "/obs1")); ctx2.DefineObservable <int>( new Uri(qe2Id + "/obs2"), obs1.Where(x => x % 2 == 1).Take(5), null); var obs2 = ctx2.GetObservable <int>(new Uri(qe2Id + "/obs2")); var sub1 = obs2.Subscribe( ctx2.GetObserver <string, int>(MockObserverUri)("v1"), sub, null); o1 = MockObservable.Get <int>("o1"); Assert.IsNotNull(o1); Assert.AreEqual(1, o1.SubscriptionCount); o1s = o1.Synchronize(qe1.Scheduler); v1 = GetMockObserver <int>("v1"); for (int i = 0; i < 4; i++) { o1s.OnNext(i); } Assert.IsTrue(v1.WaitForCount(2, Timeout)); Assert.IsFalse(v1.Completed); Assert.IsFalse(v1.Error); AssertResult(v1, 2, (i, v) => Assert.AreEqual(i * 2 + 1, v)); store = Checkpoint(qe2); RemoveQueryEngine(qe2); } qe2 = CreateQueryEngine(qe2Id); { var ctx2 = GetQueryEngineReactiveService(qe2); using (var stateReader = new InMemoryStateReader(store)) { qe2.RecoverAsync(stateReader).Wait(); } var sub1 = ctx2.GetSubscription(sub); Assert.IsNotNull(sub1); for (int i = 4; i < 20; i++) { o1s.OnNext(i); } Assert.IsTrue(v1.WaitForCount(5, Timeout)); Assert.IsTrue(v1.Completed); Assert.IsFalse(v1.Error); sub1.Dispose(); Assert.AreEqual(0, o1.SubscriptionCount); AssertResult(v1, 5, (i, v) => Assert.AreEqual(i * 2 + 1, v)); } } }