title: Rabbit MQ - Recovery of connection/channel/consumer
body: <p>I am creating a consumer that runs in an infinite loop to read messages from the queue. I am looking for advice/sample code on how to recover abd continue within my infinite loop even if there are network disruptions. The consumer has to stay running as it will be installed as a WindowsService.</p>
  
  <p>1) Can someone please explain how to properly use these settings? What is the difference between them?</p>
  
  <pre><code>NetworkRecoveryInterval 
  AutomaticRecoveryEnabled
  RequestedHeartbeat
  </code></pre>
  
  <p>2) Please see my current sample code for the consumer. I am using the .Net RabbitMQ Client v3.5.6.</p>
  
  <p>How will the above settings do the "recovery" for me? 
  e.g. will consumer.Queue.Dequeue block until it is recovered?
  That doesn't seem right
  so...</p>
  
  <p>Do I have to code for this manually? e.g. will consumer.Queue.Dequeue throw an exception for which I have to detect and manually re-create my connection, channel, and consumer? Or just the consumer, as "AutomaticRecovery" will recover the channel for me?</p>
  
  <p>Does this mean I should move the consumer creation inside the while loop? what about the channel creation? and the connection creation?</p>
  
  <p>3) Assuming I have to do some of this recovery code manually, are there event callbacks (and how do I register for them) to tell me that there are network problems?</p>
  
  <p>Thanks!</p>
  
  <pre><code>public void StartConsumer(string queue)
  {
              using (IModel channel = this.Connection.CreateModel())
              {
                  var consumer = new QueueingBasicConsumer(channel);
                  const bool noAck = false;
                  channel.BasicConsume(queue, noAck, consumer);
  
                  // do I need these conditions? or should I just do while(true)???
                  while (channel.IsOpen &amp;&amp;        
                         Connection.IsOpen &amp;&amp;     
                         consumer.IsRunning)
                  {
                      try
                      {
                          BasicDeliverEventArgs item;
                          if (consumer.Queue.Dequeue(Timeout, out item))
                          {
                              string message = System.Text.Encoding.UTF8.GetString(item.Body);
                              DoSomethingMethod(message);
                              channel.BasicAck(item.DeliveryTag, false);
                          }
                      }
                      catch (EndOfStreamException ex)
                      {   
                          // this is likely due to some connection issue -- what am I to do?
                      }
                      catch (Exception ex)
                      {   
                          // should never happen, but lets say my DoSomethingMethod(message); throws an exception
                          // presumably, I'll just log the error and keep on going
                      }
                  }
              }
  }
  
          public IConnection Connection
          {
              get
              {
                  if (_connection == null) // _connection defined in class -- private static IConnection _connection;
                  {
                       _connection = CreateConnection();
                  }
                  return _connection;
              }
          }
  
          private IConnection CreateConnection()
          {
              ConnectionFactory factory = new ConnectionFactory()
              {
                  HostName = "RabbitMqHostName",
                  UserName = "RabbitMqUserName",
                  Password = "RabbitMqPassword",
              };
  
              // why do we need to set this explicitly? shouldn't this be the default?
              factory.AutomaticRecoveryEnabled = true;
  
              // what is a good value to use?
              factory.NetworkRecoveryInterval = TimeSpan.FromSeconds(5); 
  
              // what is a good value to use? How is this different from NetworkRecoveryInterval?
              factory.RequestedHeartbeat = 5; 
  
              IConnection connection = factory.CreateConnection();
              return connection;
          }
  </code></pre>