README.md

## Erlang NSQ client
This library implements a client to the [NSQ Messaging Queue](http://bitly.github.io/nsq/) it does it's best to follow the [guidelines provided by the project](http://bitly.github.io/nsq/clients/building_client_libraries.html).

### Missing features

- Support for direct non discovery connections.
- TCP discovery (using HTTP currently).
- Proper behavior when `max_in_flight` is smaller then the total number of connections.
- Support for UTF8 hostnames (seems to be a Erlang limitation).
- Protocol negation with `IDENTIFY`.
	- max_ready_count delegation from the server.

### Design
The Erlang process model fits the nsq client concept quite well so:
 - The top level 'process' are one (or more) topics and discovery server combinations.
 	- they can have none, one or multiple a channel + handler combinations.
 		- each discovered producer spawns one process for channel/handler that opens a own TCP connection.
 	- they can have none, one or multiple target hosts or host groups for `PUB`
	 	- Each `PUB` host spawns one sender.
	 	- Messages are send in a round robin principle.
	 	- Messages to host groups are send to all members.
	 	

```
                                 topic*
                                 /     \ 
                                /       \
                               /         \
                              /           \
                      discovery_server     \
                           /    \           \
                          /      \          target*(PUB)
                         /        \         
                        /          \       
                      server      server2
                       / \          |
                      /   \         |
                     |     |        |
                 channel* channel* channel*
                  

* - seperate process
```

### API

#### Using `ensq:init`
One way to connect to nsq is using 

#### Setting up topics separately
```
%% Setting up a topic separately.
DiscoveryServers = [{"localhost", 4161}], %% Discovery Server
Channels = [{<<"test">>,                  %% Channel name
			  ensq_debug_callback},       %% Callback Module
			  {<<"test2">>, ensq_debug_callback}],
ensq_topic:discover(
  test,                                   %% Topic
  DiscoveryServers,                       %% Discovery servers to use
  Channels,                               %% Channels to join.
  [{"localhost", 4150}]).                 %% Targets for SUBing


%% Sending a message to a topic
ensq:send(test, <<"hello there!">>).
```

### Non registered channels
By default channels are registered processes that way it's possible to do things like `ensq:send(test, ...)` but for some situations registering the process and creating an `atom` for the name is not desirable to prevent poisoning the atom table. A dynamically created and destroyed channel would be an example of this. Passing a `binary` instead of a `atom` binary to `ensq_topic:discover/4` will solve this issue but loose the advantage of being able to call the process by name, it still is possible to either save the `PID` on creation or retrieve it from `ensq:list/1`.

### Configuration

- `max_in_flight` maximum number of messages the server can handle at once (`300`).
- `discovery_inteval` Delay between discovery requests in milliseconds (`60000`).
- `discover_jitter` Jitter in percent added or subtracted of the discovery interval, a value of `10` gives a total jitter of `20%` by adding between `-10%` and `+10%` (`10`).
- `max_retry_delay` The maximum delay for retries in milliseconds (`10000`).
- `retry_inital` Initial retry value in milliseconds (`1000`).
- `retry_inc_type` The algorithm the retry interval progresses, it can either be `linear` making the retry delay `Attempt*retry_inital` milliseconds or `quadratic` making the retry delay `Attempt*Attempt*retry_inital`