Exemple #1
0
        public void Set_routing_key_per_message_and_consume_them_in_the_same_process()
        {
            string GetRoutingKey(string s) => $"key.{s}";

            var exchangeName        = "amqp.topic." + Environment.TickCount;
            var queueName           = "amqp-conn-it-spec-simple-queue-" + Environment.TickCount;
            var exchangeDeclaration = ExchangeDeclaration.Create(exchangeName, "topic");
            var queueDeclaration    = QueueDeclaration.Create(queueName);
            var bindingDeclaration  = BindingDeclaration.Create(queueName, exchangeName).WithRoutingKey(GetRoutingKey("*"));

            var amqpSink = AmqpSink.Create(
                AmqpSinkSettings.Create(_connectionSettings)
                .WithExchange(exchangeName)
                .WithDeclarations(exchangeDeclaration, queueDeclaration, bindingDeclaration));

            var amqpSource = AmqpSource.AtMostOnceSource(
                NamedQueueSourceSettings.Create(_connectionSettings, queueName).WithDeclarations(exchangeDeclaration, queueDeclaration, bindingDeclaration),
                bufferSize: 10);

            var input       = new[] { "one", "two", "three", "four", "five" };
            var routingKeys = input.Select(GetRoutingKey);

            Source.From(input)
            .Select(s => new OutgoingMessage(ByteString.FromString(s), false, false, routingKey: GetRoutingKey(s)))
            .RunWith(amqpSink, _mat)
            .Wait();

            var result = amqpSource
                         .Take(input.Length)
                         .RunWith(Sink.Seq <IncomingMessage>(), _mat)
                         .Result;

            result.Select(x => x.Envelope.RoutingKey).Should().Equal(routingKeys);
            result.Select(x => x.Bytes.ToString()).Should().Equal(input);
        }
Exemple #2
0
        public void Publish_from_one_source_and_consume_elements_with_multiple_sinks()
        {
            var queueName        = "amqp-conn-it-spec-work-queues-" + Environment.TickCount;
            var queueDeclaration = QueueDeclaration.Create(queueName);
            var amqpSink         = AmqpSink.CreateSimple(
                AmqpSinkSettings.Create(_connectionSettings)
                .WithRoutingKey(queueName)
                .WithDeclarations(queueDeclaration));

            var input = new[] { "one", "two", "three", "four", "five" };

            Source.From(input).Select(ByteString.FromString).RunWith(amqpSink, _mat);

            var mergedSources = Source.FromGraph(GraphDsl.Create(b =>
            {
                const int count = 3;
                var merge       = b.Add(new Merge <IncomingMessage>(count));
                for (var n = 0; n < count; n++)
                {
                    var source = b.Add(
                        AmqpSource.AtMostOnceSource(
                            NamedQueueSourceSettings.Create(_connectionSettings, queueName).WithDeclarations(queueDeclaration),
                            bufferSize: 1));

                    b.From(source.Outlet).To(merge.In(n));
                }

                return(new SourceShape <IncomingMessage>(merge.Out));
            }));

            var result = mergedSources.Select(x => x.Bytes.ToString()).Take(input.Length).RunWith(Sink.Seq <string>(), _mat);

            result.Result.OrderBy(x => x).ToArray().Should().Equal(input.OrderBy(x => x).ToArray());
        }
Exemple #3
0
        public void Publish_and_consume_elements_through_a_simple_queue_again_in_the_same_process()
        {
            ExchangeDeclaration.Create("logs", "topic");

            //queue declaration
            var queueName        = "amqp-conn-it-spec-simple-queue-" + Environment.TickCount;
            var queueDeclaration = QueueDeclaration.Create(queueName).WithDurable(false).WithAutoDelete(true);

            //create sink
            var amqpSink = AmqpSink.CreateSimple(
                AmqpSinkSettings.Create(_connectionSettings)
                .WithRoutingKey(queueName)
                .WithDeclarations(queueDeclaration));

            //create source
            var amqpSource = AmqpSource.AtMostOnceSource(
                NamedQueueSourceSettings.Create(_connectionSettings, queueName).WithDeclarations(queueDeclaration),
                bufferSize: 10);

            //run sink
            var input = new[] { "one", "two", "three", "four", "five" };

            Source.From(input).Select(ByteString.FromString).RunWith(amqpSink, _mat).Wait();

            //run source
            var result =
                amqpSource.Select(m => m.Bytes.ToString(Encoding.UTF8))
                .Take(input.Length)
                .RunWith(Sink.Seq <string>(), _mat);

            result.Wait(TimeSpan.FromSeconds(3));
            Assert.Equal(input, result.Result);
        }
Exemple #4
0
        public void Not_fail_on_a_fast_producer_and_a_slow_consumer()
        {
            var queueName        = "amqp-conn-it-spec-simple-queue-2-" + Environment.TickCount;
            var queueDeclaration = QueueDeclaration.Create(queueName);

            var amqpSource = AmqpSource.AtMostOnceSource(
                NamedQueueSourceSettings.Create(_connectionSettings, queueName).WithDeclarations(queueDeclaration), bufferSize: 2);

            var amqpSink   = AmqpSink.CreateSimple(AmqpSinkSettings.Create(_connectionSettings).WithRoutingKey(queueName).WithDeclarations(queueDeclaration));
            var publisher  = this.CreatePublisherProbe <ByteString>();
            var subscriber = this.CreateSubscriberProbe <IncomingMessage>();

            amqpSink.AddAttributes(Attributes.CreateInputBuffer(1, 1)).RunWith(Source.FromPublisher(publisher), _mat);
            amqpSource.AddAttributes(Attributes.CreateInputBuffer(1, 1)).RunWith(Sink.FromSubscriber(subscriber), _mat);

            // note that this essentially is testing rabbitmq just as much as it tests our sink and source
            publisher.EnsureSubscription();
            subscriber.EnsureSubscription();

            publisher.ExpectRequest().Should().Be(1);
            publisher.SendNext(ByteString.FromString("one"));

            publisher.ExpectRequest();
            publisher.SendNext(ByteString.FromString("two"));

            publisher.ExpectRequest();
            publisher.SendNext(ByteString.FromString("three"));

            publisher.ExpectRequest();
            publisher.SendNext(ByteString.FromString("four"));

            publisher.ExpectRequest();
            publisher.SendNext(ByteString.FromString("five"));

            subscriber.Request(4);
            subscriber.ExpectNext().Bytes.ToString().Should().Be("one");
            subscriber.ExpectNext().Bytes.ToString().Should().Be("two");
            subscriber.ExpectNext().Bytes.ToString().Should().Be("three");
            subscriber.ExpectNext().Bytes.ToString().Should().Be("four");

            subscriber.Request(1);
            subscriber.ExpectNext().Bytes.ToString().Should().Be("five");

            subscriber.Cancel();
            publisher.SendComplete();
        }
Exemple #5
0
        public void Pub_sub_from_one_source_with_multiple_sinks()
        {
            // with pubsub we arrange one exchange which the sink writes to and then one queue for each source which subscribes to the
            // exchange - all this described by the declarations

            //#exchange-declaration
            var exchangeName        = "amqp-conn-it-spec-pub-sub-" + Environment.TickCount;
            var exchangeDeclaration = ExchangeDeclaration.Create(exchangeName, "fanout");

            //#create-exchange-sink
            var amqpSink = AmqpSink.CreateSimple(AmqpSinkSettings.Create(_connectionSettings).WithExchange(exchangeName).WithDeclarations(exchangeDeclaration));

            //#create-exchange-source
            const int fanoutSize = 4;

            var mergedSources =
                Enumerable.Range(0, fanoutSize)
                .Aggregate(Source.Empty <(int, string)>(), (source, fanoutBranch) =>
                           source.Merge(
                               AmqpSource.AtMostOnceSource(
                                   TemporaryQueueSourceSettings.Create(_connectionSettings, exchangeName).WithDeclarations(exchangeDeclaration),
                                   bufferSize: 1)
                               .Select(msg => (branch: fanoutBranch, message: msg.Bytes.ToString())))
                           );

            var completion = new TaskCompletionSource <Done>();

            mergedSources.RunWith(Sink.Aggregate <(int branch, string msg), ImmutableHashSet <int> >(ImmutableHashSet.Create <int>(), (seen, t) =>
            {
                if (seen.Count == fanoutSize)
                {
                    completion.SetResult(Done.Instance);
                }
                return(seen.Add(t.branch));
            }), _mat);

            Sys.Scheduler.Advanced.ScheduleOnce(
                TimeSpan.FromSeconds(5),
                () => completion.TrySetException(new Exception("Did not get at least one element from every fanout branch")));

            Source.Repeat("stuff").Select(ByteString.FromString).RunWith(amqpSink, _mat);
            completion.Task.Result.Should().Be(Done.Instance);
        }
Exemple #6
0
        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();
        }
Exemple #7
0
        public void Publish_elements_with_flow_then_consume_them_with_source()
        {
            ExchangeDeclaration.Create("logs", "topic");

            var queueName        = "amqp-conn-it-spec-simple-queue-" + Environment.TickCount;
            var queueDeclaration = QueueDeclaration.Create(queueName).WithDurable(false).WithAutoDelete(true);

            var amqpFlow =
                AmqpFlow.Create <string>(
                    AmqpSinkSettings.Create(_connectionSettings)
                    .WithRoutingKey(queueName)
                    .WithDeclarations(queueDeclaration));


            var input = new[] { "one", "two", "three", "four", "five" };

            var passedThrough =
                Source.From(input)
                .Select(x => (new OutgoingMessage(ByteString.FromString(x), true, true), x))
                .Via(amqpFlow)
                .RunWith(Sink.Seq <string>(), _mat)
                .Result
                .ToArray();

            Assert.Equal(input, passedThrough, StringComparer.InvariantCulture);

            var consumed =
                AmqpSource.AtMostOnceSource(
                    NamedQueueSourceSettings.Create(_connectionSettings, queueName).WithDeclarations(queueDeclaration),
                    bufferSize: 10)
                .Select(m => m.Bytes.ToString(Encoding.UTF8))
                .Take(input.Length)
                .RunWith(Sink.Seq <string>(), _mat)
                .Result
                .ToArray();

            Assert.Equal(input, consumed, StringComparer.InvariantCulture);
        }
Exemple #8
0
        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);
        }