public void Handle_missing_reply_to_header_correctly() { var outgoingMessage = new OutgoingMessage(ByteString.Empty, false, false); Source .Single(outgoingMessage) .WatchTermination(Keep.Right) .To(AmqpSink.ReplyTo(AmqpReplyToSinkSettings.Create(_connectionSettings))) .Run(_mat) .Wait(); try { Source .Single(outgoingMessage) .ToMaterialized(AmqpSink.ReplyTo(AmqpReplyToSinkSettings.Create(_connectionSettings, failIfReplyToMissing: true)), Keep.Right) .Run(_mat) .Wait(); throw new Exception("Expected exception but there is no one"); } catch (AggregateException ex) { ex.InnerException?.Message.Should().Be("Reply-to header was not set"); } }
public void Publish_via_RPC_which_expects_2_responses_per_message_and_then_consume_through_a_simple_queue_again_in_the_same_process() { var queueName = "amqp-conn-it-spec-rpc-queue-" + Environment.TickCount; var queueDeclaration = QueueDeclaration.Create(queueName); var amqpRpcFlow = AmqpRpcFlow.CreateSimple( AmqpSinkSettings.Create(_connectionSettings).WithRoutingKey(queueName).WithDeclarations(queueDeclaration), repliesPerMessage: 2); var amqpSource = AmqpSource.AtMostOnceSource(NamedQueueSourceSettings.Create(_connectionSettings, queueName), bufferSize: 1); var input = new[] { "one", "two", "three", "four", "five" }; var t = Source.From(input) .Select(ByteString.FromString) .ViaMaterialized(amqpRpcFlow, Keep.Right) .ToMaterialized(this.SinkProbe <ByteString>(), Keep.Both) .Run(_mat); var rpcQueueF = t.Item1; var probe = t.Item2; rpcQueueF.Result.Should().NotBeNullOrWhiteSpace("RPC flow materializes into response queue name"); var amqpSink = AmqpSink.ReplyTo(AmqpReplyToSinkSettings.Create(_connectionSettings)); amqpSource .SelectMany(b => new[] { new OutgoingMessage(b.Bytes.Concat(ByteString.FromString("a")), false, false, b.Properties), new OutgoingMessage(b.Bytes.Concat(ByteString.FromString("aa")), false, false, b.Properties) }) .RunWith(amqpSink, _mat); probe .Request(10) .ExpectNextUnorderedN(input.SelectMany(s => new[] { ByteString.FromString(s + "a"), ByteString.FromString(s + "aa") })) .ExpectComplete(); }
public void Publish_via_RPC_and_then_consume_through_a_simple_queue_again_in_the_same_process_without_autoAck() { var queueName = "amqp-conn-it-spec-rpc-queue-" + Environment.TickCount; var queueDeclaration = QueueDeclaration.Create(queueName); var input = new[] { "one", "two", "three", "four", "five" }; var amqpRpcFlow = AmqpRpcFlow.CommittableFlow( AmqpSinkSettings.Create(_connectionSettings).WithRoutingKey(queueName).WithDeclarations(queueDeclaration), bufferSize: 10); var t = Source.From(input) .Select(ByteString.FromString) .Select(bytes => new OutgoingMessage(bytes, false, false)) .ViaMaterialized(amqpRpcFlow, Keep.Right) .SelectAsync(1, async cm => { await cm.Ack(); return(cm.Message); }) .ToMaterialized(this.SinkProbe <IncomingMessage>(), Keep.Both) .Run(_mat); var rpcQueueF = t.Item1; var probe = t.Item2; rpcQueueF.Wait(); var amqpSink = AmqpSink.ReplyTo(AmqpReplyToSinkSettings.Create(_connectionSettings)); var amqpSource = AmqpSource.AtMostOnceSource(NamedQueueSourceSettings.Create(_connectionSettings, queueName), bufferSize: 1); amqpSource .Select(b => new OutgoingMessage(b.Bytes, false, false, b.Properties)) .RunWith(amqpSink, _mat); probe.ToStrict(TimeSpan.FromSeconds(3)).Select(x => x.Bytes.ToString()).Should().Equal(input); }
public AmqpReplyToSinkStage(AmqpReplyToSinkSettings settings) { Settings = settings; }
/// <summary> /// Connects to an AMQP server upon materialization and sends incoming messages to the server. /// Each materialized sink will create one connection to the broker. This stage sends messages to /// the queue named in the replyTo options of the message instead of from settings declared at construction. /// This stage materializes to a `Future[Done]`, which can be used to know when the Sink completes, either normally /// or because of an amqp failure /// </summary> /// <param name="settings"></param> /// <returns></returns> public static Sink <OutgoingMessage, Task> ReplyTo(AmqpReplyToSinkSettings settings) { return(Sink.FromGraph(new AmqpReplyToSinkStage(settings))); }