コード例 #1
0
        private (AtomicCounter, TestPublisher.Probe <string>, TestSubscriber.Probe <string>, TestPublisher.Probe <string>, TestSubscriber.Probe <string>) SetupFlow(
            TimeSpan minBackoff,
            TimeSpan maxBackoff,
            int maxRestarts     = -1,
            bool onlyOnFailures = false)
        {
            var created       = new AtomicCounter(0);
            var probe1        = this.SourceProbe <string>().ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
            var flowInSource  = probe1.Item1;
            var flowInProbe   = probe1.Item2;
            var probe2        = this.SourceProbe <string>().ToMaterialized(BroadcastHub.Sink <string>(), Keep.Both).Run(Materializer);
            var flowOutProbe  = probe2.Item1;
            var flowOutSource = probe2.Item2;

            // We can't just use ordinary probes here because we're expecting them to get started/restarted. Instead, we
            // simply use the probes as a message bus for feeding and capturing events.
            var probe3 = this.SourceProbe <string>().ViaMaterialized(RestartFlowFactory(() =>
            {
                created.IncrementAndGet();
                var snk = Flow.Create <string>()
                          .TakeWhile(s => s != "cancel")
                          .To(Sink.ForEach <string>(c => flowInSource.SendNext(c))
                              .MapMaterializedValue(task => task.ContinueWith(
                                                        t1 =>
                {
                    if (t1.IsFaulted || t1.IsCanceled)
                    {
                        flowInSource.SendNext("in error");
                    }
                    else
                    {
                        flowInSource.SendNext("in complete");
                    }
                })));

                var src = flowOutSource.TakeWhile(s => s != "complete").Select(c =>
                {
                    if (c == "error")
                    {
                        throw new ArgumentException("failed");
                    }
                    return(c);
                }).WatchTermination((s1, task) =>
                {
                    task.ContinueWith(_ =>
                    {
                        flowInSource.SendNext("out complete");
                        return(NotUsed.Instance);
                    }, TaskContinuationOptions.OnlyOnRanToCompletion);
                    return(s1);
                });

                return(Flow.FromSinkAndSource(snk, src));
            }, onlyOnFailures, RestartSettings.Create(minBackoff, maxBackoff, 0).WithMaxRestarts(maxRestarts, minBackoff)), Keep.Left)
                         .ToMaterialized(this.SinkProbe <string>(), Keep.Both).Run(Materializer);
            var source = probe3.Item1;
            var sink   = probe3.Item2;

            return(created, source, flowInProbe, flowOutProbe, sink);
        }
コード例 #2
0
        public void BroadcastHub_must_ensure_that_from_two_different_speed_consumers_the_slower_controls_the_rate()
        {
            this.AssertAllStagesStopped(() =>
            {
                var other = Source.From(Enumerable.Range(2, 19))
                            .MapMaterializedValue <TaskCompletionSource <int> >(_ => null);
                var t = Source.Maybe <int>()
                        .Concat(other)
                        .ToMaterialized(BroadcastHub.Sink <int>(1), Keep.Both)
                        .Run(Materializer);
                var firstElement = t.Item1;
                var source       = t.Item2;

                var f1 = source
                         .Throttle(1, TimeSpan.FromMilliseconds(10), 1, ThrottleMode.Shaping)
                         .RunWith(Sink.Seq <int>(), Materializer);
                // Second cannot be overwhelmed since the first one throttles the overall rate, and second allows a higher rate
                var f2 = source
                         .Throttle(10, TimeSpan.FromMilliseconds(10), 8, ThrottleMode.Shaping)
                         .RunWith(Sink.Seq <int>(), Materializer);

                // Ensure subscription of Sinks. This is racy but there is no event we can hook into here.
                Thread.Sleep(100);
                firstElement.SetResult(1);
                f1.AwaitResult().ShouldAllBeEquivalentTo(Enumerable.Range(1, 20));
                f2.AwaitResult().ShouldAllBeEquivalentTo(Enumerable.Range(1, 20));
            }, Materializer);
        }
コード例 #3
0
        public void BroadcastHub_must_be_able_to_implement_a_keep_dropping_if_unsubscribed_policy_with_a_simple_SinkIgnore()
        {
            this.AssertAllStagesStopped(() =>
            {
                var killSwitch = KillSwitches.Shared("test-switch");
                var source     = Source.From(Enumerable.Range(1, int.MaxValue))
                                 .Via(killSwitch.Flow <int>())
                                 .RunWith(BroadcastHub.Sink <int>(8), Materializer);

                // Now the Hub "drops" elements until we attach a new consumer (Source.ignore consumes as fast as possible)
                source.RunWith(Sink.Ignore <int>(), Materializer);

                // Now we attached a subscriber which will block the Sink.ignore to "take away" and drop elements anymore,
                // turning the BroadcastHub to a normal non-dropping mode
                var downstream = this.CreateSubscriberProbe <int>();
                source.RunWith(Sink.FromSubscriber(downstream), Materializer);

                downstream.Request(1);
                var first = downstream.ExpectNext();

                for (var i = first + 1; i < first + 11; i++)
                {
                    downstream.Request(1);
                    downstream.ExpectNext(i);
                }

                downstream.Cancel();
                killSwitch.Shutdown();
            }, Materializer);
        }
コード例 #4
0
        public void BroadcastHub_must_properly_signal_error_to_consumers()
        {
            this.AssertAllStagesStopped(() =>
            {
                var upstream = this.CreatePublisherProbe <int>();
                var source   = Source.FromPublisher(upstream).RunWith(BroadcastHub.Sink <int>(8), Materializer);

                var downstream1 = this.CreateSubscriberProbe <int>();
                var downstream2 = this.CreateSubscriberProbe <int>();
                source.RunWith(Sink.FromSubscriber(downstream1), Materializer);
                source.RunWith(Sink.FromSubscriber(downstream2), Materializer);

                downstream1.Request(4);
                downstream2.Request(8);

                Enumerable.Range(1, 8).ForEach(x => upstream.SendNext(x));

                downstream1.ExpectNext(1, 2, 3, 4);
                downstream2.ExpectNext(1, 2, 3, 4, 5, 6, 7, 8);

                downstream1.ExpectNoMsg(TimeSpan.FromMilliseconds(100));
                downstream2.ExpectNoMsg(TimeSpan.FromMilliseconds(100));

                upstream.SendError(new TestException("failed"));
                downstream1.ExpectError().Message.Should().Be("failed");
                downstream2.ExpectError().Message.Should().Be("failed");
            }, Materializer);
        }
コード例 #5
0
        public ChangeTrackerActor()
        {
            var mat = Context.Materializer();

            var(queue, source) = Source.Queue <AppInfo>(10, OverflowStrategy.DropHead).PreMaterialize(mat);

            _appInfos = queue;

            var hub = source.ToMaterialized(BroadcastHub.Sink <AppInfo>(), Keep.Right);


            Receive <QueryChangeSource>("QueryChanedSource", (changeSource, reporter) => reporter.Compled(OperationResult.Success(new AppChangedSource(hub.Run(mat)))));
            Receive <AppInfo>(ai => _appInfos.OfferAsync(ai).PipeTo(Self));
            Receive <IQueueOfferResult>(r =>
            {
                switch (r)
                {
                case QueueOfferResult.Failure f:
                    Log.Error(f.Cause, "Error In Change Tracker");
                    break;

                case QueueOfferResult.QueueClosed _:
                    Log.Warning("Unexpectem Tracker Queue Close.");
                    break;
                }
            });
        }
コード例 #6
0
 public void BroadcastHub_must_work_in_the_happy_case()
 {
     this.AssertAllStagesStopped(() =>
     {
         var source = Source.From(Enumerable.Range(1, 10)).RunWith(BroadcastHub.Sink <int>(8), Materializer);
         source.RunWith(Sink.Seq <int>(), Materializer)
         .AwaitResult()
         .ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));
     }, Materializer);
 }
コード例 #7
0
ファイル: Wallet.cs プロジェクト: andyfreer/NDash
        /// <summary>
        /// Broadcast a transaction, if the same template behavior as been used for other nodes, they will also broadcast
        /// </summary>
        /// <param name="transaction">The transaction to broadcast</param>
        /// <returns>The cause of the rejection or null</returns>
        public Task <RejectPayload> BroadcastTransactionAsync(Transaction transaction)
        {
            AssertGroupAffected();
            var hub = BroadcastHub.GetBroadcastHub(_Group.NodeConnectionParameters);

            if (hub == null)
            {
                throw new InvalidOperationException("No broadcast hub detected in the group");
            }
            return(hub.BroadcastTransactionAsync(transaction));
        }
コード例 #8
0
        public static IPreparedFeature New()
        => Feature.Create(() => new ChangeTrackerActor(),
                          c =>
        {
            var mat = c.Materializer();

            var(queue, source) = Source.Queue <AppInfo>(10, OverflowStrategy.DropHead).PreMaterialize(mat);

            var hub = source.ToMaterialized(BroadcastHub.Sink <AppInfo>(), Keep.Right);

            return(new ChangeTrackeState(mat, queue, hub));
        });
コード例 #9
0
        public void BroadcastHub_must_properly_signal_completion_to_consumers_arriving_after_producer_finished()
        {
            this.AssertAllStagesStopped(() =>
            {
                var source = Source.Empty <int>().RunWith(BroadcastHub.Sink <int>(8), Materializer);
                // Wait enough so the Hub gets the completion. This is racy, but this is fine because both
                // cases should work in the end
                Thread.Sleep(50);

                source.RunWith(Sink.Seq <int>(), Materializer).AwaitResult().Should().BeEmpty();
            }, Materializer);
        }
コード例 #10
0
        public void BroadcastHub_must_properly_signal_error_to_consumers_arriving_after_producer_finished()
        {
            this.AssertAllStagesStopped(() =>
            {
                var source = Source.Failed <int>(new TestException("Fail!"))
                             .RunWith(BroadcastHub.Sink <int>(8), Materializer);
                // Wait enough so the Hub gets the completion. This is racy, but this is fine because both
                // cases should work in the end
                Thread.Sleep(50);

                var task = source.RunWith(Sink.Seq <int>(), Materializer);
                task.Invoking(t => t.Wait(TimeSpan.FromSeconds(3))).ShouldThrow <TestException>();
            }, Materializer);
        }
コード例 #11
0
        protected override void ConfigImpl()
        {
            var mat    = Context.Materializer();
            var source = Source.FromObservable(from evt in CurrentState.EventPublisher
                                               where CurrentState.Configugration.MonitorChanges
                                               select evt);
            var hubSource = source.ToMaterialized(BroadcastHub.Sink <IConfigEvent>(), Keep.Right).Run(mat);

            (from evt in CurrentState.EventPublisher
             where evt is ServerConfigurationEvent
             from pair in UpdateAndSyncActor((ServerConfigurationEvent)evt)
             select pair.State with {
                Configugration = pair.Event.Configugration
            }
コード例 #12
0
ファイル: Wallet.cs プロジェクト: andyfreer/NDash
 protected override void AttachCore()
 {
     _Tracker = AttachedNode.Behaviors.Find <TrackerBehavior>();
     if (_Tracker != null)
     {
         AttachedNode.Disconnected += AttachedNode_Disconnected;
         AttachedNode.StateChanged += AttachedNode_StateChanged;
     }
     _Broadcast = BroadcastHub.GetBroadcastHub(AttachedNode);
     if (_Broadcast != null)
     {
         _Broadcast.TransactionBroadcasted += _Broadcast_TransactionBroadcasted;
         _Broadcast.TransactionRejected    += _Broadcast_TransactionRejected;
     }
 }
コード例 #13
0
 public void BroadcastHub_must_ensure_that_subsequent_consumers_see_subsequent_elements_without_gap()
 {
     this.AssertAllStagesStopped(() =>
     {
         var source = Source.From(Enumerable.Range(1, 20)).RunWith(BroadcastHub.Sink <int>(8), Materializer);
         source.Take(10)
         .RunWith(Sink.Seq <int>(), Materializer)
         .AwaitResult()
         .ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));
         source.Take(10)
         .RunWith(Sink.Seq <int>(), Materializer)
         .AwaitResult()
         .ShouldAllBeEquivalentTo(Enumerable.Range(11, 10));
     }, Materializer);
 }
コード例 #14
0
            protected override void AttachCore()
            {
#pragma warning disable CS0612 // Type or member is obsolete
                _Tracker = AttachedNode.Behaviors.Find <TrackerBehavior>();
#pragma warning restore CS0612 // Type or member is obsolete
                if (_Tracker != null)
                {
                    AttachedNode.Disconnected += AttachedNode_Disconnected;
                    AttachedNode.StateChanged += AttachedNode_StateChanged;
                }
                _Broadcast = BroadcastHub.GetBroadcastHub(AttachedNode);
                if (_Broadcast != null)
                {
                    _Broadcast.TransactionBroadcasted += _Broadcast_TransactionBroadcasted;
                    _Broadcast.TransactionRejected    += _Broadcast_TransactionRejected;
                }
            }
コード例 #15
0
        public void BroadcastHub_must_remember_completion_for_materialisations_after_completion()
        {
            var t = this.SourceProbe <NotUsed>()
                    .ToMaterialized(BroadcastHub.Sink <NotUsed>(), Keep.Both)
                    .Run(Materializer);
            var sourceProbe = t.Item1;
            var source      = t.Item2;
            var sinkProbe   = source.RunWith(this.SinkProbe <NotUsed>(), Materializer);

            sourceProbe.SendComplete();

            sinkProbe.Request(1).ExpectComplete();

            // Materialize a second time. There was a race here, where we managed to enqueue our Source registration just
            // immediately before the Hub shut down.
            var sink2Probe = source.RunWith(this.SinkProbe <NotUsed>(), Materializer);

            sink2Probe.Request(1).ExpectComplete();
        }
コード例 #16
0
        public void Hubs_must_demonstrate_creating_a_dynamic_broadcast()
        {
            #region broadcast-hub
            Source <string, ICancelable> producer = Source.Tick(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(1), "New message");

            // Attach a BroadcastHub Sink to the producer. This will materialize to a
            // corresponding Source.
            // (We need to use ToMaterialized and Keep.Right since by default the materialized
            // value to the left is used)
            IRunnableGraph <Source <string, NotUsed> > runnableGraph =
                producer.ToMaterialized(BroadcastHub.Sink <string>(bufferSize: 256), Keep.Right);

            // By running/materializing the producer, we get back a Source, which
            // gives us access to the elements published by the producer.
            Source <string, NotUsed> fromProducer = runnableGraph.Run(Materializer);

            // Print out messages from the producer in two independent consumers
            fromProducer.RunForeach(msg => Console.WriteLine($"consumer1:{msg}"), Materializer);
            fromProducer.RunForeach(msg => Console.WriteLine($"consumer2:{msg}"), Materializer);
            #endregion
        }
コード例 #17
0
        public void Hubs_must_demonstrate_combination()
        {
            void WriteLine(string s) => TestActor.Tell(s);

            #region pub-sub-1
            // Obtain a Sink and Source which will publish and receive from the "bus" respectively.
            var(sink, source) = MergeHub
                                .Source <string>(perProducerBufferSize: 16)
                                .ToMaterialized(BroadcastHub.Sink <string>(bufferSize: 256), Keep.Both)
                                .Run(Materializer);
            #endregion

            #region pub-sub-2
            // Ensure that the Broadcast output is dropped if there are no listening parties.
            // If this dropping Sink is not attached, then the broadcast hub will not drop any
            // elements itself when there are no subscribers, backpressuring the producer instead.
            source.RunWith(Sink.Ignore <string>(), Materializer);
            #endregion

            #region pub-sub-3
            // We create now a Flow that represents a publish-subscribe channel using the above
            // started stream as its "topic". We add two more features, external cancellation of
            // the registration and automatic cleanup for very slow subscribers.
            Flow <string, string, UniqueKillSwitch> busFlow = Flow.FromSinkAndSource(sink, source)
                                                              .JoinMaterialized(KillSwitches.SingleBidi <string, string>(), Keep.Right)
                                                              .BackpressureTimeout(TimeSpan.FromSeconds(3));
            #endregion

            #region pub-sub-4

            UniqueKillSwitch killSwitch = Source
                                          .Repeat("Hello world!")
                                          .ViaMaterialized(busFlow, Keep.Right)
                                          .To(Sink.ForEach <string>(WriteLine))
                                          .Run(Materializer);

            // Shut down externally
            killSwitch.Shutdown();
            #endregion
        }
コード例 #18
0
        public void BroadcastHub_must_send_the_same_elements_to_consumers_attaching_around_the_same_time_with_a_buffer_size_of_one()
        {
            this.AssertAllStagesStopped(() =>
            {
                var other = Source.From(Enumerable.Range(2, 9))
                            .MapMaterializedValue <TaskCompletionSource <int> >(_ => null);
                var t = Source.Maybe <int>()
                        .Concat(other)
                        .ToMaterialized(BroadcastHub.Sink <int>(1), Keep.Both)
                        .Run(Materializer);
                var firstElement = t.Item1;
                var source       = t.Item2;

                var f1 = source.RunWith(Sink.Seq <int>(), Materializer);
                var f2 = source.RunWith(Sink.Seq <int>(), Materializer);

                // Ensure subscription of Sinks. This is racy but there is no event we can hook into here.
                Thread.Sleep(500);
                firstElement.SetResult(1);
                f1.AwaitResult().ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));
                f2.AwaitResult().ShouldAllBeEquivalentTo(Enumerable.Range(1, 10));
            }, Materializer);
        }
コード例 #19
0
ファイル: spv_tests.cs プロジェクト: zzms/NBitcoin
        //[Trait("UnitTest", "UnitTest")]
        public void CanBroadcastTransaction()
        {
            using (NodeServerTester servers = new NodeServerTester())
            {
                var notifiedTransactions = new List <WalletTransaction>();
                var chainBuilder         = new BlockchainBuilder();
                SetupSPVBehavior(servers, chainBuilder);
                var    tx     = new Transaction();
                Wallet wallet = new Wallet(new WalletCreation()
                {
                    Network  = servers.Network,
                    RootKeys = new[] { new ExtKey().Neuter() },
                    UseP2SH  = false
                }, keyPoolSize: 11);
                NodesGroup connected = CreateGroup(servers, 2);
                wallet.Configure(connected);
                wallet.Connect();

                AutoResetEvent evt      = new AutoResetEvent(false);
                bool           passed   = false;
                bool           rejected = false;
                BroadcastHub   hub      = BroadcastHub.GetBroadcastHub(wallet.Group.NodeConnectionParameters);
                hub.ManualBroadcast = true;
                var broadcasting = wallet.BroadcastTransactionAsync(tx);
                wallet.TransactionBroadcasted += (t) =>
                {
                    passed = true;
                    evt.Set();
                };
                wallet.TransactionRejected += (t, r) =>
                {
                    rejected = true;
                    evt.Set();
                };
                while (connected.ConnectedNodes.Count != 2 && connected.ConnectedNodes.All(n => n.State == NodeState.HandShaked))
                {
                    Thread.Sleep(10);
                }

                var behaviors = connected.ConnectedNodes.Select(n => n.Behaviors.Find <BroadcastHubBehavior>()).ToArray();

                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 1));
                Assert.Equal(1, hub.BroadcastingTransactions.Count());
                hub.BroadcastTransactions();
                Assert.True(evt.WaitOne(20000));
                Assert.True(broadcasting.Wait(2000));
                Assert.True(passed);
                evt.Reset();


                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 0));
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.Null(broadcasting.Result);

                broadcasting = wallet.BroadcastTransactionAsync(tx);

                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 1));
                hub.BroadcastTransactions();
                Assert.True(evt.WaitOne(20000));
                Assert.True(broadcasting.Wait(2000));
                Assert.True(rejected);
                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 0));
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.NotNull(broadcasting.Result);
            }
        }
コード例 #20
0
        public void ShouldSyncBlockChainAgainstLocal()
        {
            var network = new TestNetwork();

            network.AddSeed(new NetworkAddress(new IPEndPoint(IPAddress.Parse("192.168.2.101"), 9999)));

            var p = new TestTransactionPool();

            p.Add("t1", 1);
            p.Add("t2", 0);
            p.Spend("t2", "t1", 0);

            p.Render();

            var genesisBlock = new TestBlock(p.TakeOut("t1").Value);
            var block1       = new TestBlock(p.TakeOut("t2").Value);

            block1.Parent = genesisBlock;

            genesisBlock.Render();
            block1.Render();

            WithBlockChains(1, genesisBlock.Value.Key, blockChains =>
            {
                //	blockChains[0].HandleNewBlock(genesisBlock.Value.Value);
                //	blockChains[0].HandleNewBlock(block1.Value.Value);


                AutoResetEvent waitForConnection = new AutoResetEvent(false);
                bool connected = false;

                blockChains[0].OnAddedToStore += transaction =>
                {
                    Trace.Information("-- Transaction Received (node server)");
                    //	actionReceiver();
                };

                AddressManager addressManager = new AddressManager();
                addressManager.PeersToFind    = 1;
                NodeConnectionParameters nodesGroupParameters = new NodeConnectionParameters();
//				nodesGroupParameters.AddressFrom = servers[1].ExternalEndpoint;
                nodesGroupParameters.TemplateBehaviors.Add(new AddressManagerBehavior(addressManager));
                nodesGroupParameters.TemplateBehaviors.Add(new ChainBehavior(blockChains[0]));
                nodesGroupParameters.TemplateBehaviors.Add(new BroadcastHubBehavior());
                nodesGroupParameters.TemplateBehaviors.Add(new SPVBehavior(blockChains[0], BroadcastHub.GetBroadcastHub(nodesGroupParameters.TemplateBehaviors)));

                NodesGroup nodesGroup            = new NodesGroup(network, nodesGroupParameters);
                nodesGroup.AllowSameGroup        = true;
                nodesGroup.MaximumNodeConnection = 1;
                nodesGroup.ConnectedNodes.Added += (object sender, NodeEventArgs e) =>
                {
                    Trace.Information("-- Node added to node group");
                    connected = true;
                    waitForConnection.Set();
                };
                nodesGroup.Connect();


                Assert.True(waitForConnection.WaitOne(10000));                 //TODO: use reset events instead of sleep
                Assert.True(connected);



                //TODO
                Thread.Sleep(40000);



                //					actionSender(BroadcastHub.GetBroadcastHub(nodesGroup.NodeConnectionParameters));

                Trace.Information("-- Done");
            });
        }
コード例 #21
0
        private void BroadcastTransaction(Action <BroadcastHub> actionSender, Action actionReceiver)
        {
            WithServerSet(2, servers =>
            {
                WithBlockChains(2, null, blockChains =>
                {
                    AutoResetEvent waitForConnection = new AutoResetEvent(false);
                    bool connected = false;

                    servers.SeedServerIndex = 0;

                    AddressManager serverAddressManager = new AddressManager();
                    serverAddressManager.Add(
                        new NetworkAddress(servers[0].ExternalEndpoint),
                        servers[0].ExternalEndpoint.Address
                        );
                    serverAddressManager.Connected(new NetworkAddress(servers[0].ExternalEndpoint));

                    NodeConnectionParameters serverParameters = new NodeConnectionParameters();
                    serverParameters.TemplateBehaviors.Add(new AddressManagerBehavior(serverAddressManager));
                    serverParameters.TemplateBehaviors.Add(new BroadcastHubBehavior());
                    serverParameters.TemplateBehaviors.Add(new SPVBehavior(blockChains[0], BroadcastHub.GetBroadcastHub(serverParameters.TemplateBehaviors)));

                    blockChains[0].OnAddedToMempool += transaction => {
                        Trace.Information("-- Transaction Received (node server)");
                        actionReceiver();
                    };

                    servers[0].InboundNodeConnectionParameters = serverParameters;

                    #region NodeGroup

                    AddressManager addressManager = new AddressManager();
                    addressManager.PeersToFind    = 1;
                    NodeConnectionParameters nodesGroupParameters = new NodeConnectionParameters();
                    nodesGroupParameters.AddressFrom = servers[1].ExternalEndpoint;
                    nodesGroupParameters.TemplateBehaviors.Add(new AddressManagerBehavior(addressManager));
                    nodesGroupParameters.TemplateBehaviors.Add(new BroadcastHubBehavior());
                    nodesGroupParameters.TemplateBehaviors.Add(new SPVBehavior(blockChains[1], BroadcastHub.GetBroadcastHub(nodesGroupParameters.TemplateBehaviors)));

                    blockChains[1].OnAddedToMempool += transaction =>
                    {
                        Trace.Information("-- Transaction Received (node group)");
                    };

                    NodesGroup nodesGroup            = new NodesGroup(servers.Network, nodesGroupParameters);
                    nodesGroup.AllowSameGroup        = true;
                    nodesGroup.MaximumNodeConnection = 1;
                    nodesGroup.ConnectedNodes.Added += (object sender, NodeEventArgs e) =>
                    {
                        Trace.Information("-- Node added to node group");
                        connected = true;
                        waitForConnection.Set();
                    };
                    nodesGroup.Connect();

                    #endregion

                    Assert.True(waitForConnection.WaitOne(10000));                     //TODO: use reset events instead of sleep
                    Assert.True(connected);

                    actionSender(BroadcastHub.GetBroadcastHub(nodesGroup.NodeConnectionParameters));

                    Trace.Information("-- Done");
                });
            });
        }
コード例 #22
0
ファイル: spv_tests.cs プロジェクト: ywzqhl/NBitcoin
        public void CanBroadcastTransaction()
        {
            using (NodeServerTester servers = new NodeServerTester(Network.TestNet))
            {
                var notifiedTransactions = new List <WalletTransaction>();
                var chainBuilder         = new BlockchainBuilder();
                SetupSPVBehavior(servers, chainBuilder);
                var    tx     = new Transaction();
                Wallet wallet = new Wallet(new WalletCreation()
                {
                    Network  = Network.TestNet,
                    RootKeys = new[] { new ExtKey().Neuter() },
                    UseP2SH  = false
                }, keyPoolSize: 11);
                NodesGroup connected = CreateGroup(servers, 2);
                wallet.Configure(connected);
                wallet.Connect();

                AutoResetEvent evt          = new AutoResetEvent(false);
                bool           passed       = false;
                bool           rejected     = false;
                var            broadcasting = wallet.BroadcastTransactionAsync(tx);
                wallet.TransactionBroadcasted += (t) =>
                {
                    passed = true;
                    evt.Set();
                };
                wallet.TransactionRejected += (t, r) =>
                {
                    rejected = true;
                    evt.Set();
                };
                BroadcastHub         hub      = BroadcastHub.GetBroadcastHub(connected.NodeConnectionParameters);
                BroadcastHubBehavior behavior = null;
                while (behavior == null || behavior.AttachedNode.State != NodeState.HandShaked)
                {
                    behavior = connected.ConnectedNodes.Select(n => n.Behaviors.Find <BroadcastHubBehavior>()).FirstOrDefault();
                    Thread.Sleep(1);
                }
                if (broadcasting.Status != TaskStatus.RanToCompletion)
                {
                    Assert.Equal(1, behavior.Broadcasts.Count());
                    Assert.Equal(1, hub.BroadcastingTransactions.Count());
                }
                Assert.True(evt.WaitOne(20000));
                Assert.True(broadcasting.Status == TaskStatus.RanToCompletion);
                Assert.True(passed);
                evt.Reset();
                Assert.Equal(0, behavior.Broadcasts.Count());
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.Null(broadcasting.Result);

                broadcasting = wallet.BroadcastTransactionAsync(tx);
                if (broadcasting.Status != TaskStatus.RanToCompletion)
                {
                    Assert.Equal(1, behavior.Broadcasts.Count());
                }
                Assert.True(evt.WaitOne(20000));
                Assert.True(rejected);
                Assert.Equal(0, behavior.Broadcasts.Count());
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.NotNull(broadcasting.Result);
            }
        }
コード例 #23
0
        public void PublishSubscribeOnHubsAddsAndRemovesPublishersAndSubscribers()
        {
            const int publisherMaxCount  = 16;
            const int subscriberMaxCount = 16;
            const int bufferSize         = 4;

            //       Source         ToMat          Bidi
            //   +------------+               +------------+
            //   |  MergeHub  |               |BroadcastHub|
            //   |   Source   | ~> Message ~> |    Sink    |
            //   |            |               |            |
            //   +------------+               +------------+
            //   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //   ~~    (Sink<Message>, Source<Message>)   ~~
            //   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            (Sink <string, NotUsed> mergeSink, Source <string, NotUsed> mergeSource) =
                MergeHub.Source <string>(perProducerBufferSize: publisherMaxCount)
                .ToMaterialized(BroadcastHub.Sink <string>(bufferSize: subscriberMaxCount), Keep.Both)
                .Run(_materializer);

            TestProbe sub0 = CreateTestProbe();
            TestProbe sub1 = CreateTestProbe();

            //        Flow         JoinMat         Bidi
            //   +------------+               +------------+
            //   |  FromSink  | ~> Message ~> |KillSwitches| ~> Message
            //   |     And    |               |   Single   |
            //   |    Source  | <~ Message <~ |    Bidi    | <~ Message
            //   +------------+               +------------+
            //   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //   ~~                 UniqueKillSwitch                 ~~
            //   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Flow <string, string, UniqueKillSwitch> busFlow =
                Flow.FromSinkAndSource(mergeSink, mergeSource)
                .JoinMaterialized(KillSwitches.SingleBidi <string, string>(), Keep.Right);

            var(pub0, uniqueKillSwitch0) =
                Source.ActorRef <string>(bufferSize, OverflowStrategy.Fail)
                .ViaMaterialized(busFlow, Keep.Both)
                .To(Sink.ActorRef <string>(sub0, "complete"))
                .Run(_materializer);

            pub0.Tell("It's chat member 0!");
            sub0.ExpectMsg("It's chat member 0!"); // Echo.
            sub0.ExpectNoMsg(TimeSpan.FromMilliseconds(50));

            var(pub1, uniqueKillSwitch1) =
                Source.ActorRef <string>(bufferSize, OverflowStrategy.Fail)
                .ViaMaterialized(busFlow, Keep.Both)
                .To(Sink.ActorRef <string>(sub1, "complete"))
                .Run(_materializer);

            pub1.Tell("Hi! It's chat member 1!");
            sub1.ExpectMsg("Hi! It's chat member 1!"); // Echo.
            sub0.ExpectMsg("Hi! It's chat member 1!");
            pub0.Tell("Oh, Hi! Sry, but I gotta go, bye!");
            sub0.ExpectMsg("Oh, Hi! Sry, but I gotta go, bye!"); // Echo.
            uniqueKillSwitch0.Shutdown();                        // Looks like this Shutdown is non-blocking.
            sub0.ExpectMsg("complete",
                           TimeSpan.FromMilliseconds(1000));     // Wait for the running graph to stop.
            sub1.ExpectMsg("Oh, Hi! Sry, but I gotta go, bye!");
            pub1.Tell("Oh, looks like I stayed alone.");
            sub1.ExpectMsg("Oh, looks like I stayed alone."); // Echo.
            sub0.ExpectNoMsg();
        }
コード例 #24
0
 public RequestController(BroadcastHub hub, TimerManager timer, IRequestService requestService)
 {
     _hub            = hub;
     _timer          = timer;
     _requestService = requestService;
 }
コード例 #25
0
 private async void Broadcast(IHubContext <BroadcastHub> hub, string message)
 {
     var broadcast = new BroadcastHub(hub);
     await broadcast.SendMessage(message);
 }