🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

cueball

Package Overview
Dependencies
Maintainers
1
Versions
71
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cueball - npm Package Compare versions

Comparing version

to
2.1.0

README.adoc

27

lib/connection-fsm.js

@@ -6,3 +6,3 @@ /*

*
* Copyright (c) 2016, Joyent, Inc.
* Copyright 2017 Joyent, Inc.
*/

@@ -25,3 +25,2 @@

const mod_resolver = require('./resolver');
const mod_uuid = require('node-uuid');
const mod_errors = require('./errors');

@@ -341,3 +340,3 @@

SocketMgrFSM.prototype.state_backoff = function (S) {
S.validTransitions(['failed', 'connecting']);
S.validTransitions(['failed', 'connecting', 'closed']);

@@ -367,14 +366,6 @@ /*

var t = S.timeout(delay, function () {
S.timeout(delay, function () {
S.gotoState('connecting');
});
/*
* If we're in monitor mode, unref the backoff timer. That way we
* don't block a commandline app from exiting that wants to exit as
* soon as a pool enters 'failed'.
*/
if (this.sm_monitor)
t.unref();
S.on(this, 'closeAsserted', function () {

@@ -962,12 +953,2 @@ S.gotoState('closed');

if (smgr.isInState('connected')) {
var sock = smgr.getSocket();
/*
* If we can, unref the socket while idle, so that a bunch of
* spare connections doing nothing don't hold the process open.
*/
if (typeof (sock.unref) === 'function')
sock.unref();
}
/* Monitor successfully connected: make it into a normal slot now. */

@@ -1097,4 +1078,2 @@ if (this.csf_monitor === true) {

var sock = smgr.getSocket();
if (typeof (sock.ref) === 'function')
sock.ref();
hdl.accept(sock);

@@ -1101,0 +1080,0 @@ } else {

@@ -6,3 +6,3 @@ /*

*
* Copyright (c) 2016, Joyent, Inc.
* Copyright 2017 Joyent, Inc.
*/

@@ -23,3 +23,3 @@

const mod_resolver = require('./resolver');
const mod_uuid = require('node-uuid');
const mod_uuid = require('uuid');
const mod_errors = require('./errors');

@@ -26,0 +26,0 @@

@@ -920,6 +920,5 @@ /*

'sleeping until next TTL expiry');
var t = S.timeout(minDelay, function () {
S.timeout(minDelay, function () {
S.gotoState(state);
});
t.unref();
S.on(this, 'stopAsserted', function () {

@@ -926,0 +925,0 @@ S.gotoState('init');

@@ -6,3 +6,3 @@ /*

*
* Copyright (c) 2016, Joyent, Inc.
* Copyright 2017 Joyent, Inc.
*/

@@ -23,3 +23,3 @@

const mod_resolver = require('./resolver');
const mod_uuid = require('node-uuid');
const mod_uuid = require('uuid');
const mod_errors = require('./errors');

@@ -26,0 +26,0 @@ const mod_monitor = require('./pool-monitor');

{
"name": "cueball",
"version": "2.0.1",
"description": "",
"version": "2.1.0",
"description": "manage a pool of connections to a multi-node service where nodes are listed in DNS",
"main": "lib/index.js",

@@ -12,7 +12,6 @@ "dependencies": {

"ipaddr.js": ">=1.1.0 <2.0.0",
"mooremachine": ">=2.0.0 <3.0.0",
"mooremachine": ">=2.1.0 <3.0.0",
"mname-client": ">=0.5.0 <0.6.0",
"node-uuid": ">=1.4.7 <2.0.0",
"uuid": ">=3.0.1 <4.0.0",
"posix-getopt": ">=1.2.0 <2.0.0",
"restify-clients": ">=1.1.2 <2.0.0",
"vasync": ">=1.6.3 <2.0.0",

@@ -31,2 +30,5 @@ "verror": ">=1.6.1 <2.0.0"

},
"engines": {
"node": ">=0.10.0"
},
"scripts": {

@@ -33,0 +35,0 @@ "test": "tape test/*.test.js"

@@ -1,772 +0,12 @@

cueball
=======
# cueball
`cueball` is a node.js library for "playing pool" -- managing a pool of
connections to a multi-node service where nodes are listed in DNS.
<!--
This file is here because npm doesn't support any format except markdown for
README files. This way people browsing the package on npmjs.com will get a
link to the documentation instead of nothing.
It supports DNS SRV record style services, as well as the simpler kind with
multiple A/AAAA records under the same name, correctly respecting record
TTLs and making use of Additional sections where possible.
GitHub prefers .adoc files to .md, so it will render the correct README for
the repository root.
-->
The library also includes an HTTP `Agent` which can be used with the regular
node `http` client stack, including libraries like `restify` which layer on
top of it. The `Agent` transparently creates pools for services as you make
requests to connect to them.
Install
-------
```
npm install cueball
```
Example
-------
Using the `HttpsAgent`:
```js
const mod_cueball = require('cueball');
const mod_restify = require('restify-clients');
var client = mod_restify.createStringClient({
url: 'https://us-east.manta.joyent.com',
agent: new mod_cueball.HttpsAgent({
spares: 4, maximum: 10,
recovery: {
default: {
timeout: 2000,
retries: 5,
delay: 250,
maxDelay: 1000
}
}
})
});
client.get('/foobar/public', function (err, req, res, data) {
...
});
```
This will create a connection pool that aims to keep 4 spare connections at
all times, up to a maximum of 10 total connections, for
`us-east.manta.joyent.com`.
It will respect DNS TTLs and automatically rebalance the pool as IP addresses
are added to or removed from DNS.
API
---
## Agent
### `new mod_cueball.HttpAgent(options)`
### `new mod_cueball.HttpsAgent(options)`
Creates an HTTP(S) agent that can be used with the node `http` client API.
Parameters
- `options` -- Object, with keys:
- `recovery` -- Object, a recovery spec (see below)
- `spares` -- Number, number of spares wanted in the pool per host
- `maximum` -- Number, maximum number of connections per host
- `resolvers` -- optional Array of String, either containing IP addresses to
use as nameservers, or a single string for Dynamic Resolver mode
- `log` -- optional Object, a `bunyan`-style logger to use
- `initialDomains` -- optional Array of String, initial domains to create
connections to at startup (to pre-seed the Agent for quick user later)
- `defaultPort` -- optional Number, fallback TCP port to connect to (default
80 for HttpAgent, 443 for HttpsAgent). If SRV records for a name are found
the port from SRV will always be used instead of this.
- `tcpKeepAliveInitialDelay` -- optional Number, if supplied, enable TCP
level keep-alives with the given initial delay (in milliseconds)
- `ping` -- optional String, URL path to use for health checking. Connection
is considered still viable if this URL returns a non-5xx response code.
- `pingInterval` -- optional Number, interval between health check pings
- `errorOnEmpty` -- optional Boolean
### HttpAgent#stop([cb])
Stops the pools managed by this agent, calling `cb` (if given) once all have
stopped.
Once an Agent has been stopped, it can no longer accept any new requests, and
will throw an Error if asked to do so. Calling `stop()` more than once is
also an error and will throw.
Parameters
- `cb` -- optional Function (err)
## Pool
### `new mod_cueball.ConnectionPool(options)`
Creates a new pool of connections. There are two ways of using a
ConnectionPool. You can either provide your own resolver directly, or provide
parameters with which to create the default, DNS-based resolver.
Parameters
- `options` -- Object, with keys:
- `constructor` -- Function(backend) -> object, must open a new connection
to the given backend and return it
- `domain` -- String, name to look up to find backends.
- `recovery` -- Object, a recovery spec (see below)
- `spares` -- Number, number of spares wanted in the pool per host
- `maximum` -- Number, maximum number of connections per host
- `service` -- optional String, name of SRV service (e.g. `_http._tcp`)
- `defaultPort` -- optional Number, port to use for plain A/AAAA records
- `resolvers` -- optional Array of String, either containing IP addresses to
use as nameservers, or a single string for Dynamic Resolver mode (default
uses system resolvers from `/etc/resolv.conf`)
- `log` -- optional Object, a `bunyan`-style logger to use
- `maxDNSConcurrency` -- optional Number, max number of DNS queries to issue
at once (default 5)
- `checkTimeout` -- optional Number, milliseconds of idle time before
running `checker` on a connection
- `checker` -- optional Function(handle, connection), to be run on idle
connections
- `resolver` -- optional instance of an object meeting the Resolver interface
below. You would typically obtain this object by either creating your own
Resolver directly or using the `resolverForIpOrDomain` function.
Do not confuse `resolvers` (the list of IP addresses for the DNS resolvers to
contact) with `resolver` (a custom object meeting the Resolver interface below).
If you want to use a custom resolver, then you must specify the `resolver`
property. In that case, the `resolvers`, `maxDNSConcurrency`, `defaultPort`,
and `recovery` options are ignored, and the `domain` and `service` properties
are used only for logging.
Otherwise, if want to use the default DNS-based resolver, do not specify the
`resolver` property. A resolver instance will be created based on the other
configuration properties.
### Pool states
ConnectionPool exposes the `mooremachine` FSM interface, with the following
state graph:
| (from failed)
.stop() v
+--------+ connect ok +-------+ +--------+
init --> |starting| +------------> |running| +---> |stopping|
+--------+ +-------+ +--------+
+ ^ + +
resolver | | | |
failed | | | |
OR | +------+ | | v
retries +----> |failed| +-----+ | +-------+
exhausted +------+ connect ok | |stopped|
+ ^ | +-------+
| | |
.stop()| +----------------+
| all retries exhausted
Pools begin their life in the "starting" state. Once they have successfully made
one connection to any backend, they proceed to the "running" state. Otherwise,
if their underlying Resolver enters the "failed" state, or they exhaust their
retry policy attempting to connect to all their backends, they enter the
"failed" state.
A "running" pool can then either be stopped by calling the `.stop()` method, at
which point it enters the "stopping" state and begins tearing down its
connections; or all of its connections become disconnected and it exhausts its
retry policy, in which case it enters the "failed" state.
Failed pools can re-enter the "running" state at any time if they make a
successful connection to a backend and their underlying Resolver is no longer
"failed". A "failed" pool can also have the `.stop()` method called, in which
case it proceeds much as from "running".
### `ConnectionPool#stop()`
Stops the connection pool and its `Resolver`, then destroys all connections.
### `ConnectionPool#claim([options, ]callback)`
Claims a connection from the pool ready for use.
Parameters
- `options` -- optional Object, with keys:
- `timeout` -- optional Number, timeout for request in ms
(default `Infinity`)
- `errorOnEmpty` -- optional Boolean, if true return error straight away
if the pool has no backends at all (i.e., nothing was found in DNS)
- `callback` -- Function(err[, handle, connection]), parameters:
- `err` -- an Error object, if the request could not be fulfilled or timed
out
- `handle` -- Object, handle to be used to release the connection back to
the pool when work is complete
- `connection` -- Object, the actual connection (as returned by the
`constructor` given to `new ConnectionPool()`)
Returns a "waiter handle", which is an Object having a `cancel()` method. The
`cancel()` method may be called at any time up to when the `callback` is run, to
cancel the request to the pool and relinquish any queue positions held.
When a client is done with a connection, they must call `handle.release()` to
return it to the pool. All event handlers should be disconnected from the
`connection` prior to calling `release()`.
If a client determines that a connection must be closed immediately (e.g. due
to a protocol error making it impossible to continue using it safely), it must
call the `.close()` method on the *handle*, not any `.destroy()` or similar
method on the connection itself.
Calling `claim()` on a Pool that is in the "stopping", "stopped" or "failed"
states will result in the callback being called with an error on the next run of
the event loop.
### `ConnectionPool#claimSync()`
Claims a connection from the pool, only if an idle one is immediately
available. Otherwise, throws an Error. Always throws an Error if called on a
Pool that is "stopping", "stopped" or "failed".
Returns an Object with keys:
- `handle` -- Object, handle to be used to release the connection
- `connection` -- Object, actual connection
## Resolver
### `mod_cueball.Resolver` interface
An interface for all "resolvers", objects which take in some kind of
configuration (e.g. a DNS name) and track a list of "backends" for that
name. A "backend" is an IP/port pair that describes an endpoint that can
be connected to to reach a given service.
Resolver exposes the `mooremachine` FSM interface, with the following state
graph:
.start() error
+-------+ +--------+ +------+
init -> |stopped| +---> |starting| +---> |failed|
+---+---+ +---+----+ +------+
^ | +
| | ok |
| v |
+---+----+ +---+---+ |
|stopping| <--+ |running| <--------+
+--------+ +-------+ retry success
.stop()
Resolvers begin their life "stopped". When the user calls `.start()`, they
begin the process of resolving the name/configuration they were given into
backends.
If the initial attempt to resolve the name/configuration fails, the Resolver
enters the "failed" state, but continues retrying. If it succeeds, or if any
later retry succeeds, it moves to the "running" state. The reason why the
"failed" state exists is so that commandline tools and other short-lived
processes can make use of it to decide when to "give up" on a name resolution.
Once an attempt has succeeded, the Resolver will begin emitting `added` and
`removed` events (see below) describing the backends that it has found.
In the "running" state, the Resolver continues to monitor the source of its
backends (e.g. in DNS by retrying once the TTL expires) and emitting these
events when changes occur.
Finally, when the `.stop()` method is called, the Resolver transitions to
"stopping", stops monitoring and emitting events, and comes to rest in the
"stopped" state where it started.
### `Resolver#start()`
Starts the resolver's normal operation (by beginning the process of looking up
the names given).
### `Resolver#stop()`
Stops the resolver. No further events will be emitted unless `start()` is
called again.
### `Resolver#getLastError()`
Returns the last error experienced by the Resolver. This is particularly useful
when the Resolver is in the "failed" state, to produce a log message or user
interface text.
### `Resolver#getState()`
Returns the current state of the Resolver as a string (see diagram above).
Inherited from `mod_mooremachine.FSM`.
### `Resolver#onState(state, cb)`
Registers an event handler to run when the Resolver enters the given state.
Inherited from `mod_mooremachine.FSM`.
### Event `Resolver->added(key, backend)`
Emitted when a new backend has been found.
Parameters
- `key` -- String, a unique key for this backend (will be referenced by any
subsequent events about this backend)
- `backend` -- Object, with keys:
- `name` -- String, the DNS name for this backend
- `address` -- String, an IPv4 or IPv6 address
- `port` -- Number
### Event `Resolver->removed(key)`
Emitted when an existing backend has been removed.
Parameters
- `key` -- String, unique key for this backend
## DNS-based name resolver
### `new mod_cueball.DNSResolver(options)`
Creates a Resolver that looks up a name in DNS. This Resolver prefers SRV
records if they are available, and falls back to A/AAAA records if they cannot
be found.
Parameters
- `options` -- Object, with keys:
- `domain` -- String, name to look up to find backends
- `recovery` -- Object, a recovery spec (see below)
- `service` -- optional String, name of SRV service (e.g. `_http._tcp`)
- `defaultPort` -- optional Number, port to use for plain A/AAAA records
- `resolvers` -- optional Array of String, either containing IP addresses to
use as nameservers, or a single string for Dynamic Resolver mode (default
uses system resolvers from `/etc/resolv.conf`)
- `log` -- optional Object, a `bunyan`-style logger to use
- `maxDNSConcurrency` -- optional Number, max number of DNS queries to issue
at once (default 5)
## Static IP resolver
### `new mod_cueball.StaticIpResolver(options)`
Creates a new static IP resolver. This object matches the Resolver interface
above, but emits a fixed list of IP addresses when started. This list never
changes. This is intended for development environments and debugging tools,
where a user may have provided an explicit IP address rather than a DNS name to
contact. See also: `resolverForIpOrDomain()`.
Parameters
- `options` -- Object, with keys:
- `defaultPort` -- optional Number, fallback port to use for backends
that only have an `address` property
- `backends` -- Array of objects, each having properties:
- `address` -- String, an IP address to emit as a backend
- `port` -- Number (optional if `defaultPort` used), a port number
for this backend
This object provides the same `start()` and `stop()` methods as the Resolver
class, as well as the same `added` and `removed` events.
## Picking the right resolver
### `resolverForIpOrDomain(options)`
Services that use DNS for service discovery would typically use a DNS-based
resolver. But in development environments or with debugging tools, it's useful
to be able to point a cueball-using program at an instance located at a specific
IP address and port. That's what the Static IP resolver is for.
To make this easy for programs that want to support connecting to either
hostnames or IP addresses, this function is provided to take configuration
(expected to come from a user, via an environment variable, command-line
option, or other configuration source), determine whether an IP address or DNS
name was specified, and return either a DNS-based or static resolver. If the
input appears to be neither a valid IPv4 nor IPv6 address nor DNS name, or the
port number is not valid, then an Error is returned (not thrown). (If the
input is missing or has the wrong type, an Error object is thrown, since this
is a programmer error.)
Parameters
- `options` -- Object, with keys:
- `input` -- String, either an IP address or DNS name, with optional port
suffix
- `resolverConfig` -- Object, a set of additional properties to pass to
the resolver constructor, with keys:
- `defaultPort` -- optional Number, used for both DNS and static names
- `recovery` -- Object, see `DNSResolver`, required for DNS lookups
- `service` -- optional String, see `DNSResolver`
- `resolvers` -- optional Array of String, see `DNSResolver`
- `log` -- optional Object, a `bunyan`-style logger to use
The `input` string has the form `HOSTNAME[:PORT]`, where the `[:PORT]` suffix is
optional, and `HOSTNAME` may be either an IP address or DNS name.
**Example:** create a resolver that will emit one backend for an instance at IP
127.0.0.1 port 2020:
var resolver = mod_cueball.resolverForIpOrDomain({
'input': '127.0.0.1:2020',
'resolverConfig': {
'recovery': {
'default': {
'retries': 1,
'timeout': 1000,
'delay': 1000,
'maxDelay': 1000
}
}
}
})
/* check whether resolver is an Error */
**Example:** create a resolver that will track instances associated with DNS
name `mydomain.example.com`:
var resolver = mod_cueball.resolverForIpOrDomain({
'input': 'mydomain.example.com',
'resolverConfig': {
'recovery': {
'default': {
'retries': 1,
'timeout': 1000,
'delay': 1000,
'maxDelay': 1000
}
}
}
});
/* check whether resolver is an Error */
In these examples, the `input` string is assumed to come from a user
cueball does the expected thing when given an IP address or DNS name.
## Connection interface
Objects returned by a `constructor` function (such as supplied to the
`ConnectionPool` constructor) must obey a subset of the node.js socket
interface. In particular they must support the following events and methods:
### `constructor(backend)`
Parameters:
- `backend` -- an Object, with properties:
- `key` -- a String, the backend key as supplied via the Resolver interface.
Can be used to uniquely identify the backend.
- `address` -- a String, address of the backend (IPv4 or IPv6)
- `port` -- a Number, TCP or UDP port number
Returns an object obeying the Connection interface.
### Event `connect` (required)
At construction, the connection object must immediately attempt to make a
connection to the backend specified by the first argument to the constructor.
When the connection succeeds, it must emit the event `connect`. No arguments are
required.
### Event `error`
Connection objects may emit `error` at any time in response to a fatal error.
The connection will be immediately terminated (by calling `.destroy()`) upon the
emission of any `error` event.
The `error` event should be emitted with an Object as the first parameter. This
is expected to have `Error` on its prototype chain (`obj instanceof Error`
should be `true`).
May also be emitted as `connectError` only in the state before `connect` has
been emitted.
### Event `close` (required)
Connection objects must emit `close` as the final event they emit after the
connection has ended. No events may be emitted after `close`.
### `#ref()` (required)
Marks the connection as "referenced", meaning that it should keep the Node
process running even if no event handlers are registered on it.
It is generally acceptable for long-lived server processes (which never intend
to exit in normal operation) to provide a Connection that implements `ref()` and
`unref()` as no-ops.
### `#unref()` (required)
Marks the connection as "unreferenced", allowing the Node process to exit if it
is the only remaining source of events.
### `#destroy()` (required)
Immediately disconnects the connection and proceeds to emit `close`.
### Event `timeout`
Optional. Equivalent to emitting `error` with a ConnectionTimeoutError as an
argument.
May also be emitted as `connectTimeout` only in the state before `connect` has
been emitted.
## Errors
### `ClaimTimeoutError`
Passed as first argument to `ConnectionPool#claim()`'s callback when the given
timeout in `options` has been exceeded.
Properties
- `pool` -- ConnectionPool
### `NoBackendsError`
Passed as first argument to `ConnectionPool#claim()`'s callback when there are
no known backends for the pool and the `errorOnEmpty` flag is set.
Properties
- `pool` -- ConnectionPool
## Kang support
### `mod_cueball.poolMonitor.toKangOptions()`
Returns an options object that can be passed to `mod_kang.knStartServer`. The
kang options set up snapshots containing a list of all `Pool` objects in the
system and their associated backends and state.
The returned object is missing the `port` property, which should be added
before using.
## Recovery objects
To specify the retry and timeout behaviour of Cueball DNS and pooled
connections, the "recovery spec object" is a required argument to most
constructors in the API.
A recovery spec object should always have at least one key, named `"default"`,
which gives the default settings for any operation.
More specific per-operation settings can also be given as additional keys.
For example:
```js
{
default: {
timeout: 2000,
retries: 3,
delay: 100
},
dns: {
timeout: 5000,
retries: 3,
delay: 200
}
}
```
This specifies that DNS-related operations should have a timeout of 5 seconds,
3 retries, and initial delay of 200ms, while all other operations (e.g.
`connect()` while connecting to a new backend) should have a timeout of 2
seconds, 3 retries and initial delay of 100ms.
The `delay` field indicates a time to wait between retry attempts. After each
failure, it will be doubled until it exceeds the value of `maxDelay`.
The possible fields in one operation are:
- `retries` finite Number >= 0, number of retry attempts
- `timeout` finite Number > 0, milliseconds to wait before declaring an
attempt a failure
- `maxTimeout` Number > `timeout` (can be `Infinity`), maximum value of
`timeout` to be reached with exponential timeout increase
- `delay` finite Number >= 0, milliseconds to delay between retry attempts
- `maxDelay` Number > `delay` (can be `Infinity`), maximum value of `delay`
to be reached with exponential delay increase
And the available operations:
- `dns` (all DNS-related operations, lookups etc)
- `dns_srv` (specifically lookups on SRV records, this is separate in case you
need to deal with certain old buggy DNS servers that have trouble with SRV)
- `connect` (connections to backends in a `ConnectionPool`)
- `initial` (the very first attempt to connect to a new backend, will fall
back to `connect` if not given)
If a given operation has no specification given, it will use `default` instead.
Dynamic Resolver mode
---------------------
`Resolver` instances can operate in a so-called "Dynamic Resolver" mode, where
as well as tracking their particular target service in DNS, they also track the
correct nameservers to ask about it.
This is useful in systems where the nameservers are listed in DNS as a service
just like your ordinary target service (e.g. HTTP). An example is the Joyent
SDC `binder`. `binder` acts as a DNS server, listing addresses of all SDC
service instances. This includes listing its own address, and if multiple
`binder`s are deployed, all other `binder`s in the DC.
We can look up the list of currently available `binder` instances in DNS, and
use this to perform our name resolution. We can also then use the `binder`s to
update our original list of `binder` instances.
This mode requires a "bootstrap" to begin with, however -- we cannot resolve
the name that the `binder` instances are listed under until we already know the
address of one of the `binder`s. In Dynamic Resolver mode, `cueball` will
bootstrap using the system resolvers from `/etc/resolv.conf`.
### Example
```js
const mod_cueball = require('cueball');
const mod_restify = require('restify-clients');
var client = mod_restify.createJsonClient({
url: 'http://napi.coal.joyent.us',
agent: new mod_cueball.HttpAgent({
resolvers: ['binder.coal.joyent.us'],
spares: 4, maximum: 8
})
});
client.get('/networks/' + uuid, function (err, req, res, data) {
...
});
```
This example code will start by using the system resolvers to resolve
`binder.coal.joyent.us`. Then, the records found via this lookup will be used
as nameservers to look up `napi.coal.joyent.us`.
When the TTL expires on the records for `binder.coal.joyent.us`, we will use
the records from the previous lookup as the list of nameservers to query in
order to find out what the new records should be. Then, we will use any new
nameservers we find for the next `napi.coal.joyent.us` lookup as well.
ConnectionSet
-------------
Cueball also includes an alternative to the ConnectionPool, named ConnectionSet.
This is a more low-level API which is useful for implementing clients for
protocols that are not as strictly connection-oriented.
Key differences to ConnectionPool:
- Each backend in a ConnectionSet has a maximum of 1 connection open to it
(it's expected to be used with protocols that multiplex operations over a
single socket.)
- No support for leases (claim/release). ConnectionSet does not track whether
connections are busy or not, and expects its consumer to manage this.
ConnectionSets have an identical state graph to ConnectionPools.
### `new mod_cueball.ConnectionSet(options)`
Parameters
- `options` -- Object, with keys:
- `resolver` -- Object, an instance of the Resolver interface
- `constructor` -- Function, same as in ConnectionPool
- `recovery` -- Object, a recovery spec (see below)
- `target` -- Number, target number of connections to be made
available in the entire set
- `maximum` -- Number, maximum number of sockets opened by the set.
Note that this number may temporarily be exceeded by 1 socket
to allow the set to re-balance.
- `log` -- optional Object, a `bunyan`-style logger to use
### Event `'added'`
Emitted when a new connection becomes available in the set. This event *must*
have a handler on it at all times.
The `handle` that is given as the third argument to this event has two methods
`.release()` and `.close()`, like a Pool handle. As with Pool handles, it can
be used to indicate the failure of a connection (e.g. due to a protocol error
making safe use of the connection impossible) at any time, but unlike a Pool
handle, it is an error to call `.release()` until after a `'removed'` event
has been emitted.
The user of the ConnectionSet should store both the `connection` and `handle`
in such a way as to be able to retrieve them using the `key`.
Parameters
- `key` -- String, a unique key to identify this connection
- `connection` -- Object, the connection as returned by the constructor
- `handle` -- Object, a handle to be used in response to a 'removed' event
about this connection
### Event `removed`
Emitted when an existing connection should be removed from the pool. This event
*must* have a handler on it at all times. The handler is obligated to take all
necessary actions to drain the connection of outstanding requests and then
call the `.release()` method on the relevant handle.
Parameters
- `key` -- String, a unique key to identify the connection
### `ConnectionSet#stop()`
Stops the ConnectionSet, disconnecting all available connections (by first
emitting `'removed'` for them.)
### `ConnectionSet#setTarget(target)`
Sets the target number of connections in the ConnectionSet. Will trigger an
async operation to add or remove connections in order to meet the new target.
Parameters:
- `target` -- Number
### `ConnectionSet#getConnections()`
Returns all the currently open connections in the Set, as an Array.
Tools
-----
The `cbresolve` tool is provided to show how cueball would resolve a given
configuration. The output format is not committed. It may change in the
future.
usage: cbresolve HOSTNAME[:PORT] # for DNS-based lookup
cbresolve -S | --static IP[:PORT]... # for static IPs
Locate services in DNS using Cueball resolver.
The following options are available for DNS-based lookups:
-f, --follow periodically re-resolve and report changes
-p, --port PORT default backend port
-r, --resolvers IP[,IP...] list of DNS resolvers
-s, --service SERVICE "service" name (for SRV)
-t, --timeout TIMEOUT timeout for lookups
**Example:** resolve DNS name "1.moray.us-east.joyent.us":
$ cbresolve 1.moray.emy-10.joyent.us
domain: 1.moray.emy-10.joyent.us
timeout: 5000 milliseconds
172.27.10.218 80 lLbminikNKjfy+iwDobYBuod7Hs=
172.27.10.219 80 iJMaVRehJ2zKfiS55H/lUUFPb9o=
**Example:** resolve IP/port "127.0.0.1:2020". This is only useful for seeing
how cueball would parse your input:
$ cbresolve --static 127.0.0.1:2020
using static IP resolver
127.0.0.1 2020 xBut/f1D52k1TpDN/miW82qXw6k=
**Example: resolve DNS name "1.moray.us-east.joyent.us" and watch for changes:
$ cbresolve --follow 1.moray.emy-10.joyent.us
domain: 1.moray.emy-10.joyent.us
timeout: 5000 milliseconds
2016-06-23T00:45:00.312Z added 172.27.10.218:80 (lLbminikNKjfy+iwDobYBuod7Hs=)
2016-06-23T00:45:00.314Z added 172.27.10.219:80 (iJMaVRehJ2zKfiS55H/lUUFPb9o=)
2016-06-23T00:49:00.478Z removed 172.27.10.218:80 (lLbminikNKjfy+iwDobYBuod7Hs=)
In this example, one of the DNS entries was removed a few minutes after the
program was started.
See the [documentation](https://joyent.github.io/node-cueball).

Sorry, the diff of this file is not supported yet