public void ReliableMultiSubjectProxy_AsReliableObservable_Dispose() { Run(client => { var env = new TestReliableExecutionEnvironment(); var ctx = client.CreateContext(env); var uri = new Uri("test://stream"); var subject = new ReliableSubject <int>(); env.AddArtifact(uri, subject); var proxy = new ReliableMultiSubjectProxy <int, int>(uri); var observer = new MockObserver <int>(client); var sub = proxy.ToSubscribable().Subscribe(observer); new SubscriptionInitializeVisitor(sub).Initialize(ctx); sub.Dispose(); // Reliable subscriptions must be ack'd before they can be disposed // Unfortunately, this acking must be done on the implicit interface. SubscriptionVisitor.Do <ReliableSubscriptionBase>(s => ((IReliableSubscription)s).AcknowledgeRange(0)).Apply(sub); sub.Dispose(); var isDisposed = false; SubscriptionVisitor.Do <ReliableSubcription <int> >(s => isDisposed |= s.IsDisposed).Apply(sub); Assert.IsTrue(isDisposed); }); }
public void Window_Environment_Time_Dependencies() { Run(client => { var env = new TestExecutionEnvironment(); var ctx = client.CreateContext(env); var xs = client.CreateHotObservable <int>( OnNext(210, 1), OnNext(220, 2), OnNext(230, 3), OnNext(240, 4), OnNext(250, 5), OnNext(260, 6), OnNext(270, 7), OnNext(280, 8), OnNext(290, 9), OnCompleted <int>(300) ); var s = default(ISubscription); client.ScheduleAbsolute(200, () => { s = xs.Window(TimeSpan.FromTicks(30)).Subscribe(Observer.Nop <ISubscribable <int> >()); new SubscriptionInitializeVisitor(s).Initialize(ctx); }); foreach (var t in new[] { 215, 245, 275 }) { client.ScheduleAbsolute(t, () => { var ds = default(IEnumerable <Uri>); SubscriptionVisitor.Do <IDependencyOperator>(op => { ds = op.Dependencies; }).Apply(s); Assert.IsNotNull(ds); Assert.AreEqual(1, ds.Count(d => d.OriginalString.StartsWith("rx://tollbooth"))); Assert.AreEqual(1, ds.Count(d => d.OriginalString.StartsWith("rx://collector"))); Assert.AreEqual(1, ds.Count(d => d.OriginalString.StartsWith("rx://tunnel/window"))); }); } client.Start(); }); }
public void AverageInt32_Overflow2() { Run(client => { var xs = client.CreateColdObservable( OnNext <int>(10, -2), OnNext <int>(20, -3), OnNext <int>(30, -5), OnNext <int>(40, -7), OnCompleted <int>(50) ); var res = client.CreateObserver <Double>(); client.ScheduleAbsolute(default(object), 200, (s, _) => { var ys = xs.Average(); var sub = ys.Subscribe(res); InitializeSubscription(sub, client); // Yes, dirty. No, I don't care. SubscriptionVisitor.Do <IOperator>(op => { var top = op.GetType(); if (top.DeclaringType == ys.GetType()) { var count = top.GetField("_sum", BindingFlags.Instance | BindingFlags.NonPublic); count.SetValue(op, long.MinValue + 8); } }).Apply(sub); }); client.Start(); res.Messages.AssertEqual( OnError <Double>(230, ex => ex is OverflowException) ); xs.Subscriptions.AssertEqual( Subscribe(200, 230) ); }); }
public void SubscriptionVisitor_Simple() { var g1 = new MySpecialOperator("g1"); var c1 = new MyOperator("c1", g1); var c2 = new MySpecialOperator("c2"); var c3 = new MyOperator("c3"); var p = new MyOperator("p", c1, c2, c3); var log = new List <int>(); var lst1 = new List <string>(); var lst2 = new List <string>(); SubscriptionVisitor .Do <IMyOperator>(op => { log.Add(1); lst1.Add(op.Name); }) .Do <IMySpecialOperator>(op => { log.Add(2); lst2.Add(op.Name); }) .Apply(p); Assert.IsTrue(new[] { 1, 1, 1, 2, 1, 2, 1 }.SequenceEqual(log)); Assert.IsTrue(new[] { "p", "c1", "g1", "c2", "c3" }.SequenceEqual(lst1)); Assert.IsTrue(new[] { "g1", "c2" }.SequenceEqual(lst2)); }
private static void Start(ISubscription o) { SubscriptionVisitor.Do <IOperator>(op => op.Start()).Apply(o); }
public void Collect() { var trace = _queryEngine.TraceSource; var enabled = _queryEngine.Options.GarbageCollectionEnabled; if (!enabled) { trace.RegistryGarbageCollection_NotEnabled(_queryEngine.Uri); return; } trace.RegistryGarbageCollection_Started(_queryEngine.Uri); var sw = Stopwatch.StartNew(); var allDependenciesList = new List <Uri>(); var visitor = SubscriptionVisitor.Do <IDependencyOperator>(op => { allDependenciesList.AddRange(op.Dependencies); }); foreach (var sub in _queryEngine._registry.Subscriptions) { var value = sub.Value; if (value != null) { var instance = value.Instance; if (instance != null && value.IsInitialized) { visitor.Apply(instance); } } } foreach (var sub in _queryEngine._registry.Subjects) { var value = sub.Value; if (value != null) { var instance = value.Instance; if (instance != null && value.IsInitialized) { if (instance is IDependencyOperator op) { allDependenciesList.AddRange(op.Dependencies); } } } } var allDependencies = new HashSet <Uri>(allDependenciesList); var markTime = sw.Elapsed; trace.RegistryGarbageCollection_LiveDependencies(_queryEngine.Uri, allDependencies.Count, (int)markTime.TotalMilliseconds); sw.Restart(); var observables = _queryEngine._registry.Observables; var unreachableObservables = 0; foreach (var obs in observables) { var value = obs.Value; if (value != null) { // // NB: Right now, we take a narrow approach for known entities that cannot be top-level nodes (i.e. // they are always owned by a parent, and such a parent should be found for them to be alive). // // A more complete implementation should have a mechanism to discover these, because they are // really dependent on the operator library used (with the exception of e.g. edges), and thus // this violates the layering map right now. // if (obs.Key.EndsWith("/upstream-observable", StringComparison.Ordinal)) { if (!allDependencies.Contains(value.Uri)) { unreachableObservables++; _collectibleEntities.Enqueue(value); } } } } // // NB: Removed various internal-only identifiers from libraries other than Reaqtor for the OSS release. // var scanTime = sw.Elapsed; trace.RegistryGarbageCollection_UnreachableObservables(_queryEngine.Uri, unreachableObservables, observables.Values.Count, (int)scanTime.TotalMilliseconds); if (!_queryEngine.Options.GarbageCollectionSweepEnabled) { trace.RegistryGarbageCollection_SweepDisabled(_queryEngine.Uri); } }