WIP: initial prototype

- Added sniff reason
- Improved types
This commit is contained in:
delvedor
2018-12-04 14:29:40 +01:00
parent bf4adf0546
commit b60a716e00
3 changed files with 80 additions and 41 deletions

15
index.d.ts vendored
View File

@ -2,11 +2,10 @@
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { SecureContextOptions } from 'tls'; import { SecureContextOptions } from 'tls';
import Transport from './lib/Transport'; import Transport, { ApiResponse, EventMeta, SniffMeta } from './lib/Transport';
import Connection, { AgentOptions } from './lib/Connection'; import Connection, { AgentOptions } from './lib/Connection';
import ConnectionPool, { nodeSelectorFn, nodeFilterFn } from './lib/ConnectionPool'; import ConnectionPool, { nodeSelectorFn, nodeFilterFn } from './lib/ConnectionPool';
import Serializer from './lib/Serializer'; import Serializer from './lib/Serializer';
import { ApiResponse } from './lib/Transport';
declare type anyObject = { declare type anyObject = {
[key: string]: any; [key: string]: any;
@ -471,4 +470,14 @@ declare const events: {
SNIFF: string; SNIFF: string;
}; };
export { Client, Transport, ConnectionPool, Connection, Serializer, events, ApiResponse }; export {
Client,
Transport,
ConnectionPool,
Connection,
Serializer,
events,
ApiResponse,
EventMeta,
SniffMeta
};

79
lib/Transport.d.ts vendored
View File

@ -6,42 +6,61 @@ declare type noopFn = (...args: any[]) => void;
declare type emitFn = (event: string | symbol, ...args: any[]) => boolean; declare type emitFn = (event: string | symbol, ...args: any[]) => boolean;
interface TransportOptions { interface TransportOptions {
emit: emitFn & noopFn; emit: emitFn & noopFn;
connectionPool: ConnectionPool; connectionPool: ConnectionPool;
serializer: Serializer; serializer: Serializer;
maxRetries: number; maxRetries: number;
requestTimeout: number | string; requestTimeout: number | string;
suggestCompression: boolean; suggestCompression: boolean;
sniffInterval: number; sniffInterval: number;
sniffOnConnectionFault: boolean; sniffOnConnectionFault: boolean;
sniffEndpoint: string; sniffEndpoint: string;
sniffOnStart: boolean; sniffOnStart: boolean;
} }
export interface ApiResponse { export interface ApiResponse {
body: any; body: any;
statusCode: number | null; statusCode: number | null;
headers: any; headers: any;
warnings: any[] | null; warnings: any[] | null;
}
export interface EventMeta {
connection: Connection;
request: any;
response: ApiResponse;
attempts: number;
aborted: boolean;
}
export interface SniffMeta {
hosts: any[];
reason: string;
} }
export default class Transport { export default class Transport {
emit: emitFn & noopFn; static sniffReasons: {
connectionPool: ConnectionPool; SNIFF_ON_START: string;
serializer: Serializer; SNIFF_INTERVAL: string;
maxRetries: number; SNIFF_ON_CONNECTION_FAULT: string;
requestTimeout: number; DEFAULT: string;
suggestCompression: boolean; };
sniffInterval: number; emit: emitFn & noopFn;
sniffOnConnectionFault: boolean; connectionPool: ConnectionPool;
sniffEndpoint: string; serializer: Serializer;
_sniffEnabled: boolean; maxRetries: number;
_nextSniff: number; requestTimeout: number;
_isSniffing: boolean; suggestCompression: boolean;
constructor(opts: TransportOptions); sniffInterval: number;
request(params: any, callback: (err: Error | null, result: ApiResponse) => void): any; sniffOnConnectionFault: boolean;
getConnection(): Connection | null; sniffEndpoint: string;
sniff(callback?: (...args: any[]) => void): void; _sniffEnabled: boolean;
_nextSniff: number;
_isSniffing: boolean;
constructor(opts: TransportOptions);
request(params: any, callback: (err: Error | null, result: ApiResponse) => void): any;
getConnection(): Connection | null;
sniff(callback?: (...args: any[]) => void): void;
} }
export {}; export {};

View File

@ -29,7 +29,7 @@ class Transport {
this._isSniffing = false this._isSniffing = false
if (opts.sniffOnStart === true) { if (opts.sniffOnStart === true) {
this.sniff() this.sniff(Transport.sniffReasons.SNIFF_ON_START)
} }
} }
@ -112,7 +112,7 @@ class Transport {
this.connectionPool.markDead(meta.connection) this.connectionPool.markDead(meta.connection)
if (this.sniffOnConnectionFault === true) { if (this.sniffOnConnectionFault === true) {
this.sniff() this.sniff(Transport.sniffReasons.SNIFF_ON_CONNECTION_FAULT)
} }
// retry logic // retry logic
@ -225,19 +225,22 @@ class Transport {
getConnection () { getConnection () {
const now = Date.now() const now = Date.now()
if (this._sniffEnabled === true && now > this._nextSniff) { if (this._sniffEnabled === true && now > this._nextSniff) {
this.sniff() this.sniff(Transport.sniffReasons.SNIFF_INTERVAL)
} }
this.connectionPool.resurrect(now) this.connectionPool.resurrect(now)
return this.connectionPool.getConnection() return this.connectionPool.getConnection()
} }
// TODO: add sniff reason sniff (reason = Transport.sniffReasons.DEFAULT, callback = noop) {
// 'connection-fault', 'interval', 'start', ...
sniff (callback = noop) {
if (this._isSniffing === true) return if (this._isSniffing === true) return
this._isSniffing = true this._isSniffing = true
debug('Started sniffing request') debug('Started sniffing request')
if (typeof reason === 'function') {
callback = reason
reason = Transport.sniffReasons.DEFAULT
}
const request = { const request = {
method: 'GET', method: 'GET',
path: this.sniffEndpoint path: this.sniffEndpoint
@ -251,7 +254,7 @@ class Transport {
if (err != null) { if (err != null) {
debug('Sniffing errored', err) debug('Sniffing errored', err)
this.emit('sniff', err, null) this.emit('sniff', err, { hosts: [], reason })
return callback(err) return callback(err)
} }
@ -259,12 +262,20 @@ class Transport {
const hosts = this.connectionPool.nodesToHost(result.body.nodes) const hosts = this.connectionPool.nodesToHost(result.body.nodes)
this.connectionPool.update(hosts) this.connectionPool.update(hosts)
this.emit('sniff', null, hosts) this.emit('sniff', null, { hosts, reason })
callback(null, hosts) callback(null, hosts)
}) })
} }
} }
Transport.sniffReasons = {
SNIFF_ON_START: 'sniff-on-start',
SNIFF_INTERVAL: 'sniff-interval',
SNIFF_ON_CONNECTION_FAULT: 'sniff-on-connection-fault',
// TODO: find a better name
DEFAULT: 'default'
}
function toMs (time) { function toMs (time) {
if (typeof time === 'string') { if (typeof time === 'string') {
return ms(time) return ms(time)