public void IdleTimeoutBidi_must_signal_error_to_all_outputs() { this.AssertAllStagesStopped(() => { var upWrite = this.CreatePublisherProbe <string>(); var upRead = this.CreateSubscriberProbe <int>(); var downWrite = this.CreatePublisherProbe <int>(); var downRead = this.CreateSubscriberProbe <string>(); RunnableGraph.FromGraph(GraphDsl.Create(b => { var timeoutStage = b.Add(BidiFlow.BidirectionalIdleTimeout <string, int>(TimeSpan.FromSeconds(2))); b.From(Source.FromPublisher(upWrite)).To(timeoutStage.Inlet1); b.From(timeoutStage.Outlet1).To(Sink.FromSubscriber(downRead)); b.From(timeoutStage.Outlet2).To(Sink.FromSubscriber(upRead)); b.From(Source.FromPublisher(downWrite)).To(timeoutStage.Inlet2); return(ClosedShape.Instance); })).Run(Materializer); var te = new TestException("test"); upWrite.SendError(te); upRead.ExpectSubscriptionAndError().ShouldBeEquivalentTo(te); downRead.ExpectSubscriptionAndError().ShouldBeEquivalentTo(te); downWrite.ExpectCancellation(); }, Materializer); }
public void IdleTimeoutBidi_must_not_signal_error_if_traffic_is_one_way() { this.AssertAllStagesStopped(() => { var upstreamWriter = this.CreatePublisherProbe <int>(); var downstreamWriter = this.CreatePublisherProbe <string>(); var upstream = Flow.FromSinkAndSource(Sink.Ignore <string>(), Source.FromPublisher(upstreamWriter), Keep.Left); var downstream = Flow.FromSinkAndSource(Sink.Ignore <int>(), Source.FromPublisher(downstreamWriter), Keep.Left); var assembly = upstream.JoinMaterialized( BidiFlow.BidirectionalIdleTimeout <int, string>(TimeSpan.FromSeconds(2)), Keep.Left).JoinMaterialized(downstream, Keep.Both); var r = assembly.Run(Materializer); var upFinished = r.Item1; var downFinished = r.Item2; upstreamWriter.SendNext(1); Thread.Sleep(1000); upstreamWriter.SendNext(1); Thread.Sleep(1000); upstreamWriter.SendNext(1); Thread.Sleep(1000); upstreamWriter.SendComplete(); downstreamWriter.SendComplete(); upFinished.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); downFinished.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); }, Materializer); }
public void IdleTimeoutBidi_must_be_able_to_signal_timeout_once_no_traffic_on_either_sides() { this.AssertAllStagesStopped(() => { var upWrite = this.CreatePublisherProbe <string>(); var upRead = this.CreateSubscriberProbe <int>(); var downWrite = this.CreatePublisherProbe <int>(); var downRead = this.CreateSubscriberProbe <string>(); RunnableGraph.FromGraph(GraphDsl.Create(b => { var timeoutStage = b.Add(BidiFlow.BidirectionalIdleTimeout <string, int>(TimeSpan.FromSeconds(2))); b.From(Source.FromPublisher(upWrite)).To(timeoutStage.Inlet1); b.From(timeoutStage.Outlet1).To(Sink.FromSubscriber(downRead)); b.From(timeoutStage.Outlet2).To(Sink.FromSubscriber(upRead)); b.From(Source.FromPublisher(downWrite)).To(timeoutStage.Inlet2); return(ClosedShape.Instance); })).Run(Materializer); // Request enough for the whole test upRead.Request(100); downRead.Request(100); upWrite.SendNext("DATA1"); downRead.ExpectNext("DATA1"); Thread.Sleep(1500); downWrite.SendNext(1); upRead.ExpectNext(1); Thread.Sleep(1500); upWrite.SendNext("DATA2"); downRead.ExpectNext("DATA2"); Thread.Sleep(1000); downWrite.SendNext(2); upRead.ExpectNext(2); upRead.ExpectNoMsg(TimeSpan.FromMilliseconds(500)); var error1 = upRead.ExpectError(); var error2 = downRead.ExpectError(); error1.Should().BeOfType <TimeoutException>(); error1.Message.Should().Be($"No elements passed in the last {TimeSpan.FromSeconds(2)}."); error2.ShouldBeEquivalentTo(error1); upWrite.ExpectCancellation(); downWrite.ExpectCancellation(); }, Materializer); }
public void IdleTimeoutBidi_must_not_signal_error_in_simple_loopback_case_and_pass_through_elements_unmodified() { this.AssertAllStagesStopped(() => { var timeoutIdentity = BidiFlow.BidirectionalIdleTimeout <int, int>(TimeSpan.FromSeconds(2)).Join(Flow.Create <int>()); var t = Source.From(Enumerable.Range(1, 100)) .Via(timeoutIdentity).Grouped(200) .RunWith(Sink.First <IEnumerable <int> >(), Materializer); t.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); t.Result.ShouldAllBeEquivalentTo(Enumerable.Range(1, 100)); }, Materializer); }
public static BidiFlow <ByteString, ByteString, ByteString, ByteString, NotUsed> Create(TimeSpan idleTimeout, EndPoint remoteAddress = null) { var connectionString = remoteAddress == null ? "" : $" on connection to [{remoteAddress}]"; var idleException = new TcpIdleTimeoutException( $"TCP idle-timeout encountered{connectionString}, no bytes passed in the last {idleTimeout}", idleTimeout); var toNetTimeout = BidiFlow.FromFlows( Flow.Create <ByteString>().SelectError(e => e is TimeoutException ? idleException : e), Flow.Create <ByteString>()); var fromNetTimeout = toNetTimeout.Reversed(); // now the bottom flow transforms the exception, the top one doesn't (since that one is "fromNet") return(fromNetTimeout.Atop(BidiFlow.BidirectionalIdleTimeout <ByteString, ByteString>(idleTimeout)) .Atop(toNetTimeout)); }
private StreamTcp.IncomingConnection ConnectionFor(Tcp.Connected connected, IActorRef connection) { _connectionFlowsAwaitingInitialization.IncrementAndGet(); var tcpFlow = Flow.FromGraph(new IncomingConnectionStage(connection, connected.RemoteAddress, _stage._halfClose)) .Via(new Detacher <ByteString>()) // must read ahead for proper completions .MapMaterializedValue(unit => { _connectionFlowsAwaitingInitialization.DecrementAndGet(); return(unit); }); // FIXME: Previous code was wrong, must add new tests var handler = tcpFlow; if (_stage._idleTimeout.HasValue) { handler = tcpFlow.Join(BidiFlow.BidirectionalIdleTimeout <ByteString, ByteString>(_stage._idleTimeout.Value)); } return(new StreamTcp.IncomingConnection(connected.LocalAddress, connected.RemoteAddress, handler)); }