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);
        }
コード例 #2
0
        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));
        }
コード例 #3
0
        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);
        }