private static IEnumerable <IModel> CreateSeed(IChannelFactory factory, int channelCount) { for (var i = 0; i < channelCount; i++) { yield return(factory.CreateChannelAsync().GetAwaiter().GetResult()); } }
public ISubscription SubscribeAsync <T>(Func <T, TMessageContext, Task> subscribeMethod, SubscriptionConfiguration config) { var routingKey = _config.RouteWithGlobalId ? $"{config.RoutingKey}.#" : config.RoutingKey; var topologyTask = _topologyProvider.BindQueueAsync(config.Queue, config.Exchange, routingKey); var channelTask = _channelFactory.CreateChannelAsync(); var subscriberTask = Task .WhenAll(topologyTask, channelTask) .ContinueWith(t => { var consumer = _consumerFactory.CreateConsumer(config, channelTask.Result); consumer.OnMessageAsync = (o, args) => _errorHandling.ExecuteAsync(() => { var body = _serializer.Deserialize <T>(args.Body); var context = _contextProvider.ExtractContext(args.BasicProperties.Headers[PropertyHeaders.Context]); _contextEnhancer.WireUpContextFeatures(context, consumer, args); return(subscribeMethod(body, context)); }, exception => _errorHandling.OnSubscriberExceptionAsync(consumer, config, args, exception)); consumer.Model.BasicConsume(config.Queue.FullQueueName, config.NoAck, consumer); _logger.LogDebug($"Setting up a consumer on channel '{channelTask.Result.ChannelNumber}' for queue {config.Queue.QueueName} with NoAck set to {config.NoAck}."); return(new Subscription(consumer, config.Queue.QueueName)); }); Task.WaitAll(subscriberTask); _subscriptions.Add(subscriberTask.Result); return(subscriberTask.Result); }
public ISubscription SubscribeAsync <T>(Func <T, Task> subscribeMethod, SubscriptionConfiguration config) { var routingKey = config.RoutingKey; var topologyTask = _topologyProvider.BindQueueAsync(config.Queue, config.Exchange, routingKey); var channelTask = _channelFactory.CreateChannelAsync(); var subscriberTask = Task .WhenAll(topologyTask, channelTask) .ContinueWith(t => { if (topologyTask.IsFaulted) { throw topologyTask.Exception ?? new Exception("Topology Task Faulted"); } var consumer = _consumerFactory.CreateConsumer(config, channelTask.Result); consumer.OnMessageAsync = async(o, args) => { var body = _serializer.Deserialize <T>(args.Body); await subscribeMethod(body); }; consumer.Model.BasicConsume(config.Queue.FullQueueName, config.NoAck, consumer); _logger.LogDebug($"Setting up a consumer on channel '{channelTask.Result.ChannelNumber}' for queue {config.Queue.QueueName} with NoAck set to {config.NoAck}."); return(new Subscription(consumer, config.Queue.FullQueueName)); }); Task.WaitAll(subscriberTask); _subscriptions.Add(subscriberTask.Result); return(subscriberTask.Result); }
public override async Task <IModel> GetAsync(CancellationToken ct = default(CancellationToken)) { var activeChannels = GetActiveChannelCount(); if (activeChannels < _options.MinimunPoolSize) { _logger.Debug("Pool currently has {channelCount}, which is lower than the minimal pool size {minimalPoolSize}. Creating channels.", activeChannels, _options.MinimunPoolSize); var delta = _options.MinimunPoolSize - Pool.Count; for (var i = 0; i < delta; i++) { var channel = await _factory.CreateChannelAsync(ct); Add(channel); } } return(await base.GetAsync(ct)); }
public ISubscription RespondAsync <TRequest, TResponse>(Func <TRequest, TMessageContext, Task <TResponse> > onMessage, ResponderConfiguration cfg) { var routingKey = _config.RouteWithGlobalId ? $"{cfg.RoutingKey}.#" : cfg.RoutingKey; var topologyTask = _topologyProvider.BindQueueAsync(cfg.Queue, cfg.Exchange, routingKey); var channelTask = _channelFactory.CreateChannelAsync(); var respondTask = Task.WhenAll(topologyTask, channelTask) .ContinueWith(t => { if (topologyTask.IsFaulted) { throw topologyTask.Exception ?? new Exception("Topology Task Fauled"); } var consumer = _consumerFactory.CreateConsumer(cfg, channelTask.Result); consumer.OnMessageAsync = (o, args) => _errorHandling.ExecuteAsync(() => { var body = _serializer.Deserialize <TRequest>(args.Body); var context = _contextProvider.ExtractContext(args.BasicProperties.Headers[PropertyHeaders.Context]); _contextEnhancer.WireUpContextFeatures(context, consumer, args); return(onMessage(body, context) .ContinueWith(tResponse => { if (tResponse.IsFaulted) { throw tResponse.Exception ?? new Exception(); } if (consumer.AcknowledgedTags.Contains(args.DeliveryTag)) { return; } if (tResponse.Result == null) { return; } _logger.LogDebug($"Sending response to request with correlation '{args.BasicProperties.CorrelationId}'."); consumer.Model.BasicPublish( exchange: string.Empty, routingKey: args.BasicProperties.ReplyTo, basicProperties: _propertyProvider.GetProperties <TResponse>(p => p.CorrelationId = args.BasicProperties.CorrelationId), body: _serializer.Serialize(tResponse.Result) ); })); }, exception => _errorHandling.OnResponseHandlerExceptionAsync(consumer, cfg, args, exception)); consumer.Model.BasicConsume(cfg.Queue.QueueName, cfg.NoAck, consumer); return(new Subscription(consumer, cfg.Queue.QueueName)); }); Task.WaitAll(respondTask); _subscriptions.Add(respondTask.Result); return(respondTask.Result); }
public override async Task InvokeAsync(IPipeContext context, CancellationToken token = default(CancellationToken)) { var ack = GetMessageAcknowledgement(context); if (!(ack is Retry retryAck)) { await Next.InvokeAsync(context, token); return; } var deadLeterExchangeName = GetDeadLetterExchangeName(retryAck.Span); await TopologyProvider.DeclareExchangeAsync(new ExchangeDeclaration { Name = deadLeterExchangeName, Durable = true, ExchangeType = ExchangeType.Direct }); var deliveryArgs = GetDeliveryEventArgs(context); Logger.LogInformation("Message is marked for Retry. Will be published on exchange {exchangeName} with routing key {routingKey} in {retryIn}", deliveryArgs.Exchange, deliveryArgs.RoutingKey, retryAck.Span); UpdateRetryHeaders(deliveryArgs, context); var deadLetterQueueName = GetDeadLetterQueueName(deliveryArgs.Exchange, retryAck.Span); var deadLetterExchange = context?.GetConsumerConfiguration()?.Exchange.Name ?? deliveryArgs.Exchange; await TopologyProvider.DeclareQueueAsync(new QueueDeclaration { Name = deadLetterQueueName, Durable = true, Arguments = new Dictionary <string, object> { { QueueArgument.DeadLetterExchange, deadLetterExchange }, { QueueArgument.Expires, Convert.ToInt32(retryAck.Span.Add(TimeSpan.FromSeconds(1)).TotalMilliseconds) }, { QueueArgument.MessageTtl, Convert.ToInt32(retryAck.Span.TotalMilliseconds) } } }); await TopologyProvider.BindQueueAsync(deadLetterQueueName, deadLeterExchangeName, deliveryArgs.RoutingKey, deliveryArgs.BasicProperties.Headers); using (var publishChannel = await ChannelFactory.CreateChannelAsync(token)) { publishChannel.BasicPublish(deadLeterExchangeName, deliveryArgs.RoutingKey, false, deliveryArgs.BasicProperties, deliveryArgs.Body); } await TopologyProvider.UnbindQueueAsync(deadLetterQueueName, deadLeterExchangeName, deliveryArgs.RoutingKey, deliveryArgs.BasicProperties.Headers); context.Properties.AddOrReplace(PipeKey.MessageAcknowledgement, new Ack()); await Next.InvokeAsync(context, token); }
public override async Task <IModel> GetAsync(CancellationToken ct = default(CancellationToken)) { var currentCount = GetActiveChannelCount(); if (currentCount < _desiredChannelCount) { var createCount = _desiredChannelCount - currentCount; for (var i = 0; i < createCount; i++) { var channel = await ChannelFactory.CreateChannelAsync(ct); Add(channel); } } return(await base.GetAsync(ct)); }
private void InitializeConsumer() { var channelTask = _channelFactory.CreateChannelAsync(); var topologyTask = _topologyProvider.DeclareQueueAsync(_queueConfig); Task.WhenAll(channelTask, topologyTask) .ContinueWith(tChannel => { _consumer = new EventingBasicConsumer(channelTask.Result); _consumer.Received += (sender, args) => { var context = _contextProvider.ExtractContext(args.BasicProperties.Headers[PropertyHeaders.Context]); var body = _serializer.Deserialize(args); _messageDispatcher.InvokeMessageHandler(context.GlobalRequestId, body, context); _consumer.Model.BasicAck(args.DeliveryTag, false); }; _consumer.Model.BasicConsume(_queueConfig.FullQueueName, false, _consumer); }) .Wait(); }
protected virtual Task <IModel> GetOrCreateChannelAsync(CancellationToken token = default(CancellationToken)) { _logger.LogInformation("Creating a dedicated channel for consumer."); return(_channelFactory.CreateChannelAsync(token)); }
protected virtual Task <IModel> CreateChannelAsync(IPipeContext context, CancellationToken ct) { return(ChannelFactory.CreateChannelAsync(ct)); }