public Task QueueMessageBatchAsync <T>(Guid streamGuid, string streamNamespace, IEnumerable <T> events, StreamSequenceToken token, Dictionary <string, object> requestContext) { if (token != null) { throw new ArgumentException("RabbitMq stream provider does not support non-null StreamSequenceToken.", nameof(token)); } var queueId = _mapper.GetQueueForStream(streamGuid, streamNamespace); var key = new Tuple <int, QueueId>(Thread.CurrentThread.ManagedThreadId, queueId); if (!_queues.TryGetValue(key, out var rmq)) { rmq = _queues.GetOrAdd(key, _rmqConnectorFactory.CreateProducer(queueId)); } rmq.Send(RabbitMqDataAdapter.ToQueueMessage(_serializationManager, streamGuid, streamNamespace, events, requestContext)); return(Task.CompletedTask); }
public RabbitMqAdapterFactory( string providerName, IOptionsMonitor <RabbitMqOptions> rmqOptionsAccessor, IOptionsMonitor <SimpleQueueCacheOptions> cachingOptionsAccessor, IServiceProvider serviceProvider, ILoggerFactory loggerFactory, IRabbitMqStreamQueueMapperFactory streamQueueMapperFactory) { if (string.IsNullOrEmpty(providerName)) { throw new ArgumentNullException(nameof(providerName)); } if (rmqOptionsAccessor == null) { throw new ArgumentNullException(nameof(rmqOptionsAccessor)); } if (cachingOptionsAccessor == null) { throw new ArgumentNullException(nameof(cachingOptionsAccessor)); } if (serviceProvider == null) { throw new ArgumentNullException(nameof(serviceProvider)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } if (streamQueueMapperFactory == null) { throw new ArgumentNullException(nameof(streamQueueMapperFactory)); } var rmqOptions = rmqOptionsAccessor.Get(providerName); var cachingOptions = cachingOptionsAccessor.Get(providerName); _cache = new SimpleQueueAdapterCache(cachingOptions, providerName, loggerFactory); _mapper = streamQueueMapperFactory.Get(providerName); _failureHandler = Task.FromResult <IStreamFailureHandler>(new NoOpStreamDeliveryFailureHandler(false)); var dataAdapter = serviceProvider.GetServiceByName <IQueueDataAdapter <RabbitMqMessage, IEnumerable <IBatchContainer> > >(providerName) ?? RabbitMqDataAdapter.Create(serviceProvider, providerName); _adapter = new RabbitMqAdapter(rmqOptions, dataAdapter, providerName, _mapper, serviceProvider.GetRequiredServiceByName <IRabbitMqConnectorFactory>(providerName)); }
public async Task <IList <IBatchContainer> > GetQueueMessagesAsync(int maxCount) { var batch = new List <IBatchContainer>(); var startTimestamp = DateTime.UtcNow; for (int count = 0; count < maxCount || maxCount == QueueAdapterConstants.UNLIMITED_GET_QUEUE_MSG; count++) { // in case of high latency on the network, new messages will be coming in a low rate and until the cache // will be filled, we would will be looping here; the timeout is here to break the loop and start the // consumption if it takes too long to fill the cache if (DateTime.UtcNow - startTimestamp > _cacheFillingTimeout) { break; } // on a very slow network with high latency, the synchronous RMQ Receive will block all worker threads until // the RMQ queue is empty or the cache is full; in order to enforce the consumption, the Yield is called, // which foces asynchronicity and allows other scheduled methods (the consumers) to continue; // the right ways would be to await a ReceiveAsync, but there is currently no such method in RMQ client library; // we could only wrap the call in Task.Run, which is also a bad practice await Task.Yield(); var item = _consumer.Receive(); if (item == null) { break; } try { batch.Add(RabbitMqDataAdapter.FromQueueMessage(_serializationManager, item.Body, _sequenceId++, item.DeliveryTag)); } catch (Exception ex) { _rmqConnectorFactory.Logger.Log(0, Runtime.Severity.Error, "GetQueueMessagesAsync: failed to deserialize the message! The message will be thrown away (by calling ACK).", null, ex); _consumer.Ack(item.DeliveryTag); } } return(batch); }