Example #1
0
 private void CreateEngine()
 {
     _scheduler   = new LogicalScheduler(_physicalScheduler);
     _queryEngine = new CheckpointingQueryEngine(new Uri(QeId), _resolver, _scheduler, _context, _keyValueStore, SerializationPolicy.Default, s_map, null);
     _queryEngine.Options.TemplatizeExpressions = _templatize;
     EngineContext = _queryEngine.ReactiveService;
 }
Example #2
0
        public QueryEvaluatorServiceProvider(CheckpointingQueryEngine queryEngine, IReactiveMetadataCache metadata, Func <Expression, Expression> rewriter)
        {
            _queryEngine = queryEngine;
            _metadata    = metadata;
            _rewriter    = rewriter;

            _queryEngine.Options.ForeignFunctionBinder = ForeignFunctionsBinder.Bind;
        }
        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));
            }
        }