<NME> README.md
<BEF> # Lyra
[![Build Status](https://travis-ci.org/jhalterman/lyra.svg)](https://travis-ci.org/jhalterman/lyra)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/net.jodah/lyra/badge.svg)][maven] 

## Introduction

Dealing with failure is a fact of life in distributed systems. Lyra is a [RabbitMQ](http://www.rabbitmq.com/) client that embraces failure, allowing for AMQP resources such as connections, channels and consumers to be automatically recovered when network failures occur.

## Features

* Automatic resource recovery
* Automatic invocation retries
* Connection and Channel pooling

## Setup



`mvn install`

## User Guide

### Recoverable Resources

Lyra extends the [Java AMQP client](http://www.rabbitmq.com/java-client.html) to provide *recoverable* resources such as [Connections](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Connection.html), [Channels](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html) and [Consumers](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Consumer.html). Let's create some recoverable resources:

```
LyraOptions options = LyraOptions.forHost("localhost")
	.withRecoveryPolicy(new RetryPolicy()
		.withMaxRetries(100)

#### Automatic Resource Recovery

> Please note that Lyra and RabbitMQ Java client's recovery feature are **mutually exclusive** and **must not be used together**.
> Note that RabbitMQ Java client 4.0 and later versions have automatic connection recovery enabled by default.
channel.basicConsume("foo-queue", myConsumer);
```

We've created a new Connection through the `Connections` class, specifying a recovery policy to use in case any of our resources are *unexpectedly* closed and need to be recovered. If the consumer is cancelled, the channel is closed, or the connection is closed as the result of a *recoverable* server error or a network failure, Lyra will attempt to recover the closed resources automatically, according to the recovery policy.

### Retryable Invocation

Lyra also support *retryable* invocation against resources:

```
LyraOptions options = LyraOptions.forHost("localhost"))
	.withRetryPolicy(new RetryPolicy()
		.withBackoff(Duration.seconds(1), Duration.seconds(30))
		.withMaxDuration(Duration.minutes(10)));
		
Connection connection = Connections.create(options);
```

With a retry policy specified, any invocation against a resource, including initial connection attempts, will be automatically retried according to the policy, should it fail for some *recoverable* reason. If the invocation failure results in the resource being closed, as is often the case with channels, then the resource will automatically be recovered before the invocation is retried.

### More on Retry / Recovery Policies

Retry / Recovery policies allow you to specify the maximum number of retry attempts to perform, the maxmimum duration that retries should be performed for, the standard interval between retry attempts, and the maximum interval between retries to exponentially backoff to.

Lyra allows for Retry / Recovery policies to be set globally or for individually for specific resource types, including for initial connect attempt.

### More on Recoverable Failures

Lyra will only recover or retry after a failure that is deemed *recoverable*. These include connection attempts that are not authentication failures, and channel or connection errors that might be the result of temporary problems.

### Connection Pooling



### Channel Pooling



## License

ConfigurableConnection configurableConnection = Config.of(connection);
ConfigurableChannel configurableChannel = Config.of(channel);
```

#### Event Listeners

Lyra offers [listeners](http://jodah.net/lyra/javadoc/net/jodah/lyra/event/package-summary.html) for creation and recovery events:

```java
Config config = new Config();
	.withConnectionListeners(myConnectionListener)
	.withChannelListeners(myChannelListener)
	.withConsumerListeners(myConsumerListener);
```

Event listeners can be useful for setting up additional resources during recovery, such as auto-deleted exchanges and queues.


## Additional Notes

#### On Recovery and Retry Policies

[Recovery][recovery-policy] and [Retry][retry-policy] policies allow you to specify:

* The maximum number of attempts to perform
* The maxmimum duration that attempts should be performed for
* The interval between attempts
* The maximum interval between attempts to exponentially backoff to

Lyra allows for recovery and retry policies to be set globally, for individual resource types, and for initial connection attempts.

#### On Recoverable / Retryable Failures

Lyra will only recover or retry on certain failures. By default these include connection errors that are not related to failed authentication, and channel or connection errors that might be the result of temporary network failures. It is possible to see different exceptions for the same failure on different platforms. Because of this, you can freely modify the sets of [recoverable][recoverable-exceptions] and [retryable][retryable-exceptions] exceptions can as needed to handle any type of failure.

#### On Publishing

When a channel is closed and is in the process of being recovered, attempts to publish to that channel will result in `AlreadyClosedException` being thrown. Publishers should either wait and listen for recovery by way of a [ChannelListener][channel-listener], or use a [RetryPolicy][retry-policy] to retry publish attempts once the channel is recovered. 

#### On Message Delivery

When a channel is closed and recovered, any messages that were delivered but not acknowledged will be redelivered on the newly recovered channel. Attempts to ack/nack/reject messages that were delivered before the channel was recovered are simply ignored since their delivery tags will be invalid for the newly recovered channel. 

Note, since channel recovery happens transparently, in effect when a channel is recovered and message redelivery occurs **messages may be seen more than once on the recovered channel**.

#### On Threading

When a Connection or Channel are closed unexpectedly recovery occurs in a background thread. If a retry policy is configured then any invocation attempts will block the calling thread until the Connection/Channel is recovered and the invocation can be retried.

#### On QueueingConsumer

`QueueingConsumer` is [deprecated][queueing-consumer-javadoc]. Since the current implementation is [not recoverable](https://github.com/rabbitmq/rabbitmq-java-client/blob/master/src/com/rabbitmq/client/QueueingConsumer.java#L198) it should not be used with Lyra. Instead it's recommended to extend `DefaultConsumer` or implement `Consumer` directly. See the [JavaDoc][queueing-consumer-javadoc] for more details.

#### On Logging

Logging is provided via the [slf4j](http://www.slf4j.org/) [API](http://www.slf4j.org/apidocs/index.html) using the `net.jodah.lyra` category. To enable Lyra's logging, just include an slf4j logging [implementation](http://www.slf4j.org/manual.html#swapping) on your classpath.

## Additional Resources

* JavaDocs are available [here](https://jodah.net/lyra/javadoc).
* The various failure scenarios handled by Lyra are described [here][failure-scenarios].
* See the [Lyra cookbook][cookbook] for handling specific RabbitMQ use cases.
* A [Clojure][kithara] wrapper for Lyra is available.

## Thanks

Thanks to Brett Cameron, Michael Klishin and Matthias Radestock for their valuable ideas and feedback.

## License

Copyright 2013-2017 Jonathan Halterman - Released under the [Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html).

[java-client]: http://www.rabbitmq.com/java-client.html
[Connection]: http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Connection.html
[Channel]: http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html
[Consumer]: http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Consumer.html
[amqp-client]: http://search.maven.org/#search%7Cga%7C1%7Ca%3A%22amqp-client%22
[before-consumer-recovery]: http://jodah.net/lyra/javadoc/net/jodah/lyra/event/ConsumerListener.html#onBeforeRecovery(com.rabbitmq.client.Consumer%2C%20com.rabbitmq.client.Channel)
[connect-retry]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/Config.html#withConnectRetryPolicy-net.jodah.lyra.config.RetryPolicy-
[global-recovery]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/Config.html#withRecoveryPolicy-net.jodah.lyra.config.RecoveryPolicy-
[global-retry]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/Config.html#withRetryPolicy-net.jodah.lyra.config.RetryPolicy-
[config]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/Config.html
[channel-listener]: http://jodah.net/lyra/javadoc/net/jodah/lyra/event/ChannelListener.html
[connection-config]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/ConnectionConfig.html
[channel-config]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/ChannelConfig.html
[consumer-config]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/ConsumerConfig.html
[recovery-policy]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/RecoveryPolicy.html
[retry-policy]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/RetryPolicy.html
[eventing]: http://jodah.net/lyra/javadoc/net/jodah/lyra/event/package-summary.html
[cookbook]: https://github.com/jhalterman/lyra/wiki/Lyra-Cookbook
[failure-scenarios]: https://github.com/jhalterman/lyra/wiki/Failure-Scenarios
[queueing-consumer-javadoc]: http://www.rabbitmq.com/releases/rabbitmq-java-client/v3.3.1/rabbitmq-java-client-javadoc-3.3.1/com/rabbitmq/client/QueueingConsumer.html
[recoverable-exceptions]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/Config.html#getRecoverableExceptions--
[retryable-exceptions]: http://jodah.net/lyra/javadoc/net/jodah/lyra/config/Config.html#getRetryableExceptions--
[exchange-deletion]: http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html#exchangeDelete(java.lang.String)
[queue-deletion]: http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html#queueDelete(java.lang.String)
[kithara]: https://github.com/xsc/kithara
[maven]: https://maven-badges.herokuapp.com/maven-central/net.jodah/lyra

<MSG> Doc improvements

<DFF> @@ -4,13 +4,14 @@
 
 ## Introduction
 
-Dealing with failure is a fact of life in distributed systems. Lyra is a [RabbitMQ](http://www.rabbitmq.com/) client that embraces failure, allowing for AMQP resources such as connections, channels and consumers to be automatically recovered when network failures occur.
+Dealing with failure is a fact of life in distributed systems. Lyra is a [RabbitMQ](http://www.rabbitmq.com/) client that embraces failure, allowing for AMQP resources such as connections, channels and consumers to be automatically recovered when server or network failures occur.
 
-## Features
+#### Features
 
 * Automatic resource recovery
 * Automatic invocation retries
-* Connection and Channel pooling
+* Channel pooling
+* Event listeners
 
 ## Setup
 
@@ -18,13 +19,15 @@ Until the initial release to Maven Central, you can install Lyra via Maven:
 
 `mvn install`
 
-## User Guide
+## Usage
 
-### Recoverable Resources
+Lyra is built on top of the [Java AMQP client API](http://www.rabbitmq.com/java-client.html), providing *managed* resources such as [Connections](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Connection.html), [Channels](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html) and [Consumers](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Consumer.html).
 
-Lyra extends the [Java AMQP client](http://www.rabbitmq.com/java-client.html) to provide *recoverable* resources such as [Connections](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Connection.html), [Channels](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html) and [Consumers](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Consumer.html). Let's create some recoverable resources:
+### Resource Recovery
 
-```
+The key feature of Lyra is its ability to automatically recover resources such as [Connections](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Connection.html), [Channels](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html) and [Consumers](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Consumer.html) when unexpected failures occur. For example:
+
+```java
 LyraOptions options = LyraOptions.forHost("localhost")
 	.withRecoveryPolicy(new RetryPolicy()
 		.withMaxRetries(100)
@@ -36,40 +39,56 @@ Channel channel = connection.createChannel();
 channel.basicConsume("foo-queue", myConsumer);
 ```
 
-We've created a new Connection through the `Connections` class, specifying a recovery policy to use in case any of our resources are *unexpectedly* closed and need to be recovered. If the consumer is cancelled, the channel is closed, or the connection is closed as the result of a *recoverable* server error or a network failure, Lyra will attempt to recover the closed resources automatically, according to the recovery policy.
+Here we've created a new `Connection` and `Channel`, specifying a recovery policy to use in case any of our resources are *unexpectedly* closed. If the consumer is cancelled, the channel is closed, or the connection is closed, Lyra will automatically attempt to recover the closed resources according to the given recovery policy.
 
-### Retryable Invocation
+### Invocation Retries
 
-Lyra also support *retryable* invocation against resources:
+Lyra also supports invocation retries when a *retryable* failure occurs while creating a connection or invoking a method against a [Connection](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Connection.html) or [Channel](http://www.rabbitmq.com/releases/rabbitmq-java-client/current-javadoc/com/rabbitmq/client/Channel.html). For example:
 
-```
-LyraOptions options = LyraOptions.forHost("localhost"))
+```java
+LyraOptions options = LyraOptions.forHost("localhost")
+	.withRecoveryPolicy(new RetryPolicy()
+		.withMaxRetries(100)
+		.withInterval(Duration.seconds(1))
+		.withMaxDuration(Duration.minutes(5)))
 	.withRetryPolicy(new RetryPolicy()
 		.withBackoff(Duration.seconds(1), Duration.seconds(30))
 		.withMaxDuration(Duration.minutes(10)));
 		
 Connection connection = Connections.create(options);
+Channel channel = connection.createChannel();
+channel.basicConsume("foo-queue", myConsumer);
 ```
 
-With a retry policy specified, any invocation against a resource, including initial connection attempts, will be automatically retried according to the policy, should it fail for some *recoverable* reason. If the invocation failure results in the resource being closed, as is often the case with channels, then the resource will automatically be recovered before the invocation is retried.
+Here again we've created a new `Connection` and `Channel`, specifying a recovery policy to use in case any of our resources are *unexpectedly* closed as a result of an invocation failure, and a retry policy that dictates how and when the failed method invocation should be retried. If the `Connections.create()`, `connection.createChannel()`, or `channel.basicConsume()` method invocations fail as the result of a *retryable* error, Lyra will recover any resources that were closed according to the recovery policy and retry the invocation according to the retry policy.
 
-### More on Retry / Recovery Policies
+### More on Recovery / Retry Policies
 
-Retry / Recovery policies allow you to specify the maximum number of retry attempts to perform, the maxmimum duration that retries should be performed for, the standard interval between retry attempts, and the maximum interval between retries to exponentially backoff to.
+Recovery/Retry policies allow you to specify:
 
-Lyra allows for Retry / Recovery policies to be set globally or for individually for specific resource types, including for initial connect attempt.
+* The maximum number of retry attempts to perform
+* The maxmimum duration that retries should be performed for
+* The standard interval between retry attempts
+* The maximum interval between retries to exponentially backoff to
 
-### More on Recoverable Failures
+Lyra allows for Recovery/Retry policies to be set globally or for individual resource types, as well as for initial connection attempts.
 
-Lyra will only recover or retry after a failure that is deemed *recoverable*. These include connection attempts that are not authentication failures, and channel or connection errors that might be the result of temporary problems.
+### More on Retryable Failures
 
-### Connection Pooling
+Lyra will only retry failed invocations that are deemed *retryable*. These include connection errors that are not related to failed authentication, and channel or connection errors that might be the result of temporary network failures.
 
+### Channel Pooling
 
+Lyra supports channel pooling to avoid the expense of creating/closing channels. When enabled, channel pooling allows for generic (non-numbered) channels to be recycled. To enable, simply set a channel pool site:
 
-### Channel Pooling
+```java
+LyraOptions.forHost("localhost")
+	.withChannelPoolSize(12);
+```
 
+### Notes on Threading
 
+When a Connection or Channel are closed as the result of an invocation, the calling thread is blocked according to the recovery policy until the Connection/Channel can be recovered. Connection recovery occurs in a background thread while Channel recovery occurs in the invoking thread. When a Connection is closed involuntarily (not as the result of an invocation), recovery occurs in a background thread.
 
 ## License
 

Doc improvements