예제 #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);
        }
예제 #2
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);
        }
예제 #3
0
        public Task DeclareExchangeAsync(ExchangeDeclaration exchange)
        {
            if (IsDeclared(exchange))
            {
                return(_completed);
            }

            var scheduled = new ScheduledExchangeTask(exchange);

            _topologyTasks.Enqueue(scheduled);
            EnsureWorker();
            return(scheduled.TaskCompletionSource.Task);
        }
예제 #4
0
        protected override Task DeclareExchangeAsync(ExchangeDeclaration exchange, IPipeContext context, CancellationToken token)
        {
            var policy = context.GetPolicy(PolicyKeys.ExchangeDeclare);

            return(policy.ExecuteAsync(
                       action: ct => base.DeclareExchangeAsync(exchange, context, ct),
                       cancellationToken: token,
                       contextData: new Dictionary <string, object>
            {
                [RetryKey.TopologyProvider] = TopologyProvider,
                [RetryKey.ExchangeDeclaration] = exchange,
                [RetryKey.PipeContext] = context,
                [RetryKey.CancellationToken] = token,
            }));
        }
예제 #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);
        }
예제 #6
0
        public void PublishAndConsume()
        {
            var connectionSettings = AmqpConnectionDetails.Create("localhost", 5672).WithAutomaticRecoveryEnabled(true).WithNetworkRecoveryInterval(TimeSpan.FromSeconds(1));

            var exchange = 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
            int bufferSize = 10;
            var amqpSource = AmqpSource.Create(
                NamedQueueSourceSettings.Create(DefaultAmqpConnection.Instance, queueName)
                .WithDeclarations(queueDeclaration),
                bufferSize);

            //run sink
            var input = new List <string> {
                "one", "two", "three", "four", "five"
            };

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

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

            result.Wait(TimeSpan.FromSeconds(3));

            Assert.Equal(input, result.Result);
        }
예제 #7
0
        private void DeclareExchange(ExchangeDeclaration exchange)
        {
            if (IsDeclared(exchange))
            {
                return;
            }

            _logger.Info("Declaring exchange {exchangeName}.", exchange.Name);
            var channel = GetOrCreateChannel();

            channel.ExchangeDeclare(
                exchange.Name,
                exchange.ExchangeType,
                exchange.Durable,
                exchange.AutoDelete,
                exchange.Arguments);
            if (!exchange.AutoDelete)
            {
                _initExchanges.Add(exchange.Name);
            }
        }
예제 #8
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);
        }
        protected virtual Task PublishToErrorExchangeAsync(IPipeContext context, IModel channel, Exception exception, ExchangeDeclaration exchange)
        {
            var args = context.GetDeliveryEventArgs();

            args.BasicProperties.Headers?.TryAdd(PropertyHeaders.Host, Environment.MachineName);
            args.BasicProperties.Headers?.TryAdd(PropertyHeaders.ExceptionType, exception.GetType().Name);
            args.BasicProperties.Headers?.TryAdd(PropertyHeaders.ExceptionStackTrace, exception.StackTrace);
            channel.BasicPublish(exchange.Name, args.RoutingKey, false, args.BasicProperties, args.Body);
            return(Task.FromResult(0));
        }
 protected virtual Task DeclareErrorExchangeAsync(ExchangeDeclaration exchange)
 {
     return(_provider.DeclareExchangeAsync(exchange));
 }
 public static bool IsDefaultExchange(this ExchangeDeclaration declaration)
 {
     return(string.IsNullOrEmpty(declaration.Name));
 }
 protected virtual Task DeclareExchangeAsync(ExchangeDeclaration exchange, IPipeContext context, CancellationToken token)
 {
     return(TopologyProvider.DeclareExchangeAsync(exchange));
 }
예제 #13
0
 protected virtual void SaveToContext(IPipeContext context, ExchangeDeclaration declaration)
 {
     SaveToContextAction?.Invoke(context, declaration);
 }
예제 #14
0
 public ScheduledExchangeTask(ExchangeDeclaration exchange)
 {
     Declaration = exchange;
 }
예제 #15
0
 public bool IsDeclared(ExchangeDeclaration exchange)
 {
     return(exchange.IsDefaultExchange() || _initExchanges.Contains(exchange.Name));
 }
예제 #16
0
 public static Task DeclareExchangeAsync(this IBusClient client, ExchangeDeclaration declaration, CancellationToken ct = default(CancellationToken))
 {
     return(client.InvokeAsync(DeclareExchangeAction, ctx => ctx.Properties.Add(PipeKey.ExchangeDeclaration, declaration), ct));
 }