/// <summary>
        /// Publisher
        /// </summary>
        protected TResponse Publish <TRequest, TResponse>(TRequest request, TimeSpan?ttl)
        {
            if (request == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            if (!(request is Exception) && Descriptor.IsAsync)
            {
                throw new NotSupportedException();
            }

            _consumer.Received += OnConsumerOnReceived;
            var requestBytes = _serializer.Serialize(request);
            var properties   = GetBasicProperties(1, ttl);

            properties.CorrelationId = Guid.NewGuid().ToString();
            properties.ReplyTo       = _model.QueueDeclare().QueueName;
            _model.BasicConsume(properties.ReplyTo, true, _consumer);
            _model.BasicPublish(string.Empty, Descriptor.QueueName, properties, requestBytes);

            BasicDeliverEventArgs args;

            try
            {
                var ctx = new CancellationTokenSource();
                Task.Delay(_config.GetResponseTimeout(), CancellationToken.None).ContinueWith(c => ctx.Cancel(), CancellationToken.None);
                args = _blockingCollection.Take(ctx.Token);
            }
            catch (OperationCanceledException)
            {
                throw new TimeoutException();
            }

            if (true != args.BasicProperties?.Headers?.ContainsKey(nameof(Exception)))
            {
                var response = _serializer.Deserialize(typeof(TResponse), args.Body);
                return((TResponse)response);
            }

            var exception = _serializer.Deserialize(typeof(Exception), args.Body) as Exception ?? new SystemException();

            throw exception;
        }