amqp-connection-manager
Version:
Auto-reconnect and round robin support for amqplib.
185 lines (184 loc) • 7.89 kB
TypeScript
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
/// <reference types="node" />
import * as amqp from 'amqplib';
import { EventEmitter } from 'events';
import { TcpSocketConnectOpts } from 'net';
import { ConnectionOptions } from 'tls';
import ChannelWrapper, { CreateChannelOpts } from './ChannelWrapper.js';
export type ConnectionUrl = string | amqp.Options.Connect | {
url: string;
connectionOptions?: AmqpConnectionOptions;
};
export interface ConnectListener {
(arg: {
connection: amqp.Connection;
url: string | amqp.Options.Connect;
}): void;
}
export interface ConnectFailedListener {
(arg: {
err: Error;
url: string | amqp.Options.Connect | undefined;
}): void;
}
export type AmqpConnectionOptions = (ConnectionOptions | TcpSocketConnectOpts) & {
noDelay?: boolean;
timeout?: number;
keepAlive?: boolean;
keepAliveDelay?: number;
clientProperties?: any;
credentials?: {
mechanism: string;
username: string;
password: string;
response: () => Buffer;
} | {
mechanism: string;
response: () => Buffer;
} | undefined;
};
export interface AmqpConnectionManagerOptions {
/** Interval to send heartbeats to broker. Defaults to 5 seconds. */
heartbeatIntervalInSeconds?: number;
/**
* The time to wait before trying to reconnect. If not specified, defaults
* to `heartbeatIntervalInSeconds`.
*/
reconnectTimeInSeconds?: number | undefined;
/**
* `findServers` is a function that which returns one or more servers to
* connect to. This should return either a single URL or an array of URLs.
* This is handy when you're using a service discovery mechanism such as
* Consul or etcd. Instead of taking a callback, this can also return a
* Promise. Note that if this is supplied, then `urls` is ignored.
*/
findServers?: ((callback: (urls: ConnectionUrl | ConnectionUrl[]) => void) => void) | (() => Promise<ConnectionUrl | ConnectionUrl[]>) | undefined;
/** Connection options, passed as options to the amqplib.connect() method. */
connectionOptions?: AmqpConnectionOptions;
}
export interface IAmqpConnectionManager {
connectionOptions?: AmqpConnectionOptions;
heartbeatIntervalInSeconds: number;
reconnectTimeInSeconds: number;
addListener(event: string, listener: (...args: any[]) => void): this;
addListener(event: 'connect', listener: ConnectListener): this;
addListener(event: 'connectFailed', listener: ConnectFailedListener): this;
addListener(event: 'blocked', listener: (arg: {
reason: string;
}) => void): this;
addListener(event: 'unblocked', listener: () => void): this;
addListener(event: 'disconnect', listener: (arg: {
err: Error;
}) => void): this;
listeners(eventName: string | symbol): Function[];
on(event: string, listener: (...args: any[]) => void): this;
on(event: 'connect', listener: ConnectListener): this;
on(event: 'connectFailed', listener: ConnectFailedListener): this;
on(event: 'blocked', listener: (arg: {
reason: string;
}) => void): this;
on(event: 'unblocked', listener: () => void): this;
on(event: 'disconnect', listener: (arg: {
err: Error;
}) => void): this;
once(event: string, listener: (...args: any[]) => void): this;
once(event: 'connect', listener: ConnectListener): this;
once(event: 'connectFailed', listener: ConnectFailedListener): this;
once(event: 'blocked', listener: (arg: {
reason: string;
}) => void): this;
once(event: 'unblocked', listener: () => void): this;
once(event: 'disconnect', listener: (arg: {
err: Error;
}) => void): this;
prependListener(event: string, listener: (...args: any[]) => void): this;
prependListener(event: 'connect', listener: ConnectListener): this;
prependListener(event: 'connectFailed', listener: ConnectFailedListener): this;
prependListener(event: 'blocked', listener: (arg: {
reason: string;
}) => void): this;
prependListener(event: 'unblocked', listener: () => void): this;
prependListener(event: 'disconnect', listener: (arg: {
err: Error;
}) => void): this;
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
prependOnceListener(event: 'connect', listener: ConnectListener): this;
prependOnceListener(event: 'connectFailed', listener: ConnectFailedListener): this;
prependOnceListener(event: 'blocked', listener: (arg: {
reason: string;
}) => void): this;
prependOnceListener(event: 'unblocked', listener: () => void): this;
prependOnceListener(event: 'disconnect', listener: (arg: {
err: Error;
}) => void): this;
removeListener(event: string, listener: (...args: any[]) => void): this;
connect(options?: {
timeout?: number;
}): Promise<void>;
reconnect(): void;
createChannel(options?: CreateChannelOpts): ChannelWrapper;
close(): Promise<void>;
isConnected(): boolean;
/** The current connection. */
readonly connection: amqp.Connection | undefined;
/** Returns the number of registered channels. */
readonly channelCount: number;
}
export default class AmqpConnectionManager extends EventEmitter implements IAmqpConnectionManager {
private _channels;
private _currentUrl;
private _closed;
private _cancelRetriesHandler?;
private _connectPromise?;
private _currentConnection?;
private _findServers;
private _urls?;
connectionOptions: AmqpConnectionOptions | undefined;
heartbeatIntervalInSeconds: number;
reconnectTimeInSeconds: number;
/**
* Create a new AmqplibConnectionManager.
*
* @param urls - An array of brokers to connect to.
* Takes url strings or objects {url: string, connectionOptions?: object}
* If present, a broker's [connectionOptions] will be used instead
* of [options.connectionOptions] when passed to the amqplib connect method.
* AmqplibConnectionManager will round-robin between them whenever it
* needs to create a new connection.
* @param [options={}] -
* @param [options.heartbeatIntervalInSeconds=5] - The interval,
* in seconds, to send heartbeats.
* @param [options.reconnectTimeInSeconds] - The time to wait
* before trying to reconnect. If not specified, defaults to
* `heartbeatIntervalInSeconds`.
* @param [options.connectionOptions] - Passed to the amqplib
* connect method.
* @param [options.findServers] - A `fn(callback)` or a `fn()`
* which returns a Promise. This should resolve to one or more servers
* to connect to, either a single URL or an array of URLs. This is handy
* when you're using a service discovery mechanism such as Consul or etcd.
* Note that if this is supplied, then `urls` is ignored.
*/
constructor(urls: ConnectionUrl | ConnectionUrl[] | undefined | null, options?: AmqpConnectionManagerOptions);
/**
* Start the connect retries and await the first connect result. Even if the initial connect fails or timeouts, the
* reconnect attempts will continue in the background.
* @param [options={}] -
* @param [options.timeout] - Time to wait for initial connect
*/
connect({ timeout }?: {
timeout?: number;
}): Promise<void>;
createChannel(options?: CreateChannelOpts): ChannelWrapper;
close(): Promise<void>;
isConnected(): boolean;
/** Force reconnect - noop unless connected */
reconnect(): void;
/** The current connection. */
get connection(): amqp.Connection | undefined;
/** Returns the number of registered channels. */
get channelCount(): number;
private _connect;
}