OutboundConnectionHandler(StreamsTransport transport, Address remoteAddress, EndPoint remoteSocketAddr) { var settings = transport.Settings; var transmissionHandle = Source.ActorRef <Google.Protobuf.ByteString>(settings.BufferedMessages, OverflowStrategy.Backpressure); var fromLocalActors = FromProtobuf().Via(Encode(4, settings.MaxFrameSize, settings.ByteOrder)); var fromRemoteActors = Decode(4, settings.MaxFrameSize, settings.ByteOrder).Via(ToProtobuf()); var transmissionRef = transmissionHandle.PreMaterialize(transport.StreamMaterializer); var finalOutput = new RemoteOutboundAssociationSink(transport, remoteAddress, remoteSocketAddr, transmissionRef.Item1); var dsl = GraphDsl.Create(finalOutput, (builder, remoteOutput) => { // local stages var localInput = builder.Add(transmissionRef.Item2); var compilerCeremony = builder.Add(Flow.Create <Google.Protobuf.ByteString>()); var local = builder.Add(fromLocalActors); var merge = builder.Add(new Merge <Google.Protobuf.ByteString, Google.Protobuf.ByteString>(2, false)); builder.From(localInput.Outlet).To(merge.In(0)); builder.From(compilerCeremony.Outlet).To(merge.In(1)); builder.From(merge.Out).To(local.Inlet); // remote stages var remote = builder.Add(fromRemoteActors); builder.From(remote.Outlet).To(remoteOutput.Inlet); return(new BidiShape <ByteString, Google.Protobuf.ByteString, Google.Protobuf.ByteString, ByteString>(remote.Inlet, remote.Outlet, compilerCeremony.Inlet, local.Outlet)); }); return(BidiFlow.FromGraph(dsl)); }
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); }
private static BidiFlow <long, int, string, ByteString, NotUsed> Inverse() { return (BidiFlow.FromFlows( Flow.Create <long>().Select(x => ((int)x) + 2).WithAttributes(Attributes.CreateName("top")), Flow.Create <string>() .Select(ByteString.FromString) .WithAttributes(Attributes.CreateName("bottom")))); }
private static BidiFlow <int, long, ByteString, string, NotUsed> Bidi() { return (BidiFlow.FromFlows( Flow.Create <int>().Select(x => ((long)x) + 2).WithAttributes(Attributes.CreateName("top")), Flow.Create <ByteString>() .Select(x => x.ToString(Encoding.UTF8)) .WithAttributes(Attributes.CreateName("bottom")))); }
private static BidiFlow <int, long, ByteString, string, Task <int> > BidiMaterialized() { return(BidiFlow.FromGraph(GraphDsl.Create(Sink.First <int>(), (b, s) => { b.From(Source.Single(42).MapMaterializedValue(_ => Task.FromResult(0))).To(s); var top = b.Add(Flow.Create <int>().Select(x => ((long)x) + 2)); var bottom = b.Add(Flow.Create <ByteString>().Select(x => x.ToString(Encoding.UTF8))); return new BidiShape <int, long, ByteString, string>(top.Inlet, top.Outlet, bottom.Inlet, bottom.Outlet); }))); }
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 void ActorGraphInterpreter_should_be_able_to_interpret_a_simple_bidi_stage() { this.AssertAllStagesStopped(() => { var identityBidi = new IdentityBidiGraphStage(); var identity = BidiFlow.FromGraph(identityBidi).Join(Flow.Identity <int>().Select(x => x)); var task = Source.From(Enumerable.Range(1, 10)) .Via(identity) .Grouped(100) .RunWith(Sink.First <IEnumerable <int> >(), Materializer); task.AwaitResult().Should().Equal(Enumerable.Range(1, 10)); }, 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)); }
public void ActorGraphInterpreter_should_be_able_to_interpret_and_reuse_a_simple_bidi_stage() { this.AssertAllStagesStopped(() => { var identityBidi = new IdentityBidiGraphStage(); var identityBidiFlow = BidiFlow.FromGraph(identityBidi); var identity = identityBidiFlow.Atop(identityBidiFlow).Atop(identityBidiFlow).Join(Flow.Identity <int>().Select(x => x)); var task = Source.From(Enumerable.Range(1, 10)) .Via(identity) .Grouped(100) .RunWith(Sink.First <IEnumerable <int> >(), _materializer); task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); task.Result.Should().Equal(Enumerable.Range(1, 10)); }, _materializer); }
public void Length_field_based_framing_must_support_simple_framing_adapter() { var rechunkBidi = BidiFlow.FromFlowsMat(Rechunk, Rechunk, Keep.Left); var codecFlow = Framing.SimpleFramingProtocol(1024) .Atop(rechunkBidi) .Atop(Framing.SimpleFramingProtocol(1024).Reversed()) .Join(Flow.Create <ByteString>()); // Loopback var random = new Random(); var testMessages = Enumerable.Range(1, 100).Select(_ => ReferenceChunk.Slice(0, random.Next(1024))).ToList(); var task = Source.From(testMessages) .Via(codecFlow) .Limit(1000) .RunWith(Sink.Seq <ByteString>(), Materializer); task.Wait(TimeSpan.FromSeconds(3)).Should().BeTrue(); task.Result.ShouldAllBeEquivalentTo(testMessages); }
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)); }
public static BidiFlow <Emitted <T>, IPersistentRepresentation, Delivery <IPersistentRepresentation>, Delivery <Durable <T> >, NotUsed> Create(string persistenceId) => BidiFlow.FromFlows(Encoder(persistenceId), Decoder);