Add configurable heartbeat to WebSocketOrderbookChannel
This commit is contained in:
parent
e2b51c5dc4
commit
c4bcf24640
@ -3,6 +3,7 @@
|
|||||||
## v0.6.0 - _TBD, 2018_
|
## v0.6.0 - _TBD, 2018_
|
||||||
|
|
||||||
* Add pagination options to HttpClient methods (#393)
|
* Add pagination options to HttpClient methods (#393)
|
||||||
|
* Add heartbeat configuration to WebSocketOrderbookChannel constructor (#393)
|
||||||
|
|
||||||
## v0.5.7 - _February 9, 2018_
|
## v0.5.7 - _February 9, 2018_
|
||||||
|
|
||||||
|
@ -17,4 +17,5 @@ export {
|
|||||||
TokenPairsItem,
|
TokenPairsItem,
|
||||||
TokenPairsRequestOpts,
|
TokenPairsRequestOpts,
|
||||||
TokenTradeInfo,
|
TokenTradeInfo,
|
||||||
|
WebSocketOrderbookChannelConfig,
|
||||||
} from './types';
|
} from './types';
|
||||||
|
@ -3,6 +3,7 @@ import { orderBookRequestSchema } from './orderbook_request_schema';
|
|||||||
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
|
import { ordersRequestOptsSchema } from './orders_request_opts_schema';
|
||||||
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
|
import { pagedRequestOptsSchema } from './paged_request_opts_schema';
|
||||||
import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema';
|
import { tokenPairsRequestOptsSchema } from './token_pairs_request_opts_schema';
|
||||||
|
import { webSocketOrderbookChannelConfigSchema } from './websocket_orderbook_channel_config_schema';
|
||||||
|
|
||||||
export const schemas = {
|
export const schemas = {
|
||||||
feesRequestSchema,
|
feesRequestSchema,
|
||||||
@ -10,4 +11,5 @@ export const schemas = {
|
|||||||
ordersRequestOptsSchema,
|
ordersRequestOptsSchema,
|
||||||
pagedRequestOptsSchema,
|
pagedRequestOptsSchema,
|
||||||
tokenPairsRequestOptsSchema,
|
tokenPairsRequestOptsSchema,
|
||||||
|
webSocketOrderbookChannelConfigSchema,
|
||||||
};
|
};
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
export const webSocketOrderbookChannelConfigSchema = {
|
||||||
|
id: '/WebSocketOrderbookChannelConfig',
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
heartbeatIntervalMs: { type: 'number' },
|
||||||
|
},
|
||||||
|
};
|
@ -43,6 +43,13 @@ export interface OrderbookChannel {
|
|||||||
close: () => void;
|
close: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* heartbeatInterval: Interval in milliseconds that the orderbook channel should ping the underlying websocket. Default: 15000
|
||||||
|
*/
|
||||||
|
export interface WebSocketOrderbookChannelConfig {
|
||||||
|
heartbeatIntervalMs?: number;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
|
* baseTokenAddress: The address of token designated as the baseToken in the currency pair calculation of price
|
||||||
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
|
* quoteTokenAddress: The address of token designated as the quoteToken in the currency pair calculation of price
|
||||||
|
@ -3,6 +3,7 @@ import { schemas } from '@0xproject/json-schemas';
|
|||||||
import * as _ from 'lodash';
|
import * as _ from 'lodash';
|
||||||
import * as WebSocket from 'websocket';
|
import * as WebSocket from 'websocket';
|
||||||
|
|
||||||
|
import { schemas as clientSchemas } from './schemas/schemas';
|
||||||
import {
|
import {
|
||||||
OrderbookChannel,
|
OrderbookChannel,
|
||||||
OrderbookChannelHandler,
|
OrderbookChannelHandler,
|
||||||
@ -10,9 +11,12 @@ import {
|
|||||||
OrderbookChannelSubscriptionOpts,
|
OrderbookChannelSubscriptionOpts,
|
||||||
WebsocketClientEventType,
|
WebsocketClientEventType,
|
||||||
WebsocketConnectionEventType,
|
WebsocketConnectionEventType,
|
||||||
|
WebSocketOrderbookChannelConfig,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
|
import { orderbookChannelMessageParser } from './utils/orderbook_channel_message_parser';
|
||||||
|
|
||||||
|
const DEFAULT_HEARTBEAT_INTERVAL_MS = 15000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class includes all the functionality related to interacting with a websocket endpoint
|
* This class includes all the functionality related to interacting with a websocket endpoint
|
||||||
* that implements the standard relayer API v0
|
* that implements the standard relayer API v0
|
||||||
@ -21,15 +25,25 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
private _apiEndpointUrl: string;
|
private _apiEndpointUrl: string;
|
||||||
private _client: WebSocket.client;
|
private _client: WebSocket.client;
|
||||||
private _connectionIfExists?: WebSocket.connection;
|
private _connectionIfExists?: WebSocket.connection;
|
||||||
|
private _heartbeatTimerIfExists?: NodeJS.Timer;
|
||||||
private _subscriptionCounter = 0;
|
private _subscriptionCounter = 0;
|
||||||
|
private _heartbeatIntervalMs: number;
|
||||||
/**
|
/**
|
||||||
* Instantiates a new WebSocketOrderbookChannel instance
|
* Instantiates a new WebSocketOrderbookChannel instance
|
||||||
* @param url The relayer API base WS url you would like to interact with
|
* @param url The relayer API base WS url you would like to interact with
|
||||||
|
* @param url The configuration object. Look up the type for the description.
|
||||||
* @return An instance of WebSocketOrderbookChannel
|
* @return An instance of WebSocketOrderbookChannel
|
||||||
*/
|
*/
|
||||||
constructor(url: string) {
|
constructor(url: string, config?: WebSocketOrderbookChannelConfig) {
|
||||||
assert.isUri('url', url);
|
assert.isUri('url', url);
|
||||||
|
if (!_.isUndefined(config)) {
|
||||||
|
assert.doesConformToSchema('config', config, clientSchemas.webSocketOrderbookChannelConfigSchema);
|
||||||
|
}
|
||||||
this._apiEndpointUrl = url;
|
this._apiEndpointUrl = url;
|
||||||
|
this._heartbeatIntervalMs =
|
||||||
|
_.isUndefined(config) || _.isUndefined(config.heartbeatIntervalMs)
|
||||||
|
? DEFAULT_HEARTBEAT_INTERVAL_MS
|
||||||
|
: config.heartbeatIntervalMs;
|
||||||
this._client = new WebSocket.client();
|
this._client = new WebSocket.client();
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -63,7 +77,7 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
connection.on(WebsocketConnectionEventType.Error, wsError => {
|
connection.on(WebsocketConnectionEventType.Error, wsError => {
|
||||||
handler.onError(this, subscriptionOpts, wsError);
|
handler.onError(this, subscriptionOpts, wsError);
|
||||||
});
|
});
|
||||||
connection.on(WebsocketConnectionEventType.Close, () => {
|
connection.on(WebsocketConnectionEventType.Close, (code: number, desc: string) => {
|
||||||
handler.onClose(this, subscriptionOpts);
|
handler.onClose(this, subscriptionOpts);
|
||||||
});
|
});
|
||||||
connection.on(WebsocketConnectionEventType.Message, message => {
|
connection.on(WebsocketConnectionEventType.Message, message => {
|
||||||
@ -80,6 +94,9 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
if (!_.isUndefined(this._connectionIfExists)) {
|
if (!_.isUndefined(this._connectionIfExists)) {
|
||||||
this._connectionIfExists.close();
|
this._connectionIfExists.close();
|
||||||
}
|
}
|
||||||
|
if (!_.isUndefined(this._heartbeatTimerIfExists)) {
|
||||||
|
clearInterval(this._heartbeatTimerIfExists);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) {
|
private _getConnection(callback: (error?: Error, connection?: WebSocket.connection) => void) {
|
||||||
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
|
if (!_.isUndefined(this._connectionIfExists) && this._connectionIfExists.connected) {
|
||||||
@ -87,6 +104,11 @@ export class WebSocketOrderbookChannel implements OrderbookChannel {
|
|||||||
} else {
|
} else {
|
||||||
this._client.on(WebsocketClientEventType.Connect, connection => {
|
this._client.on(WebsocketClientEventType.Connect, connection => {
|
||||||
this._connectionIfExists = connection;
|
this._connectionIfExists = connection;
|
||||||
|
if (this._heartbeatIntervalMs !== 0) {
|
||||||
|
this._heartbeatTimerIfExists = setInterval(() => {
|
||||||
|
connection.ping('');
|
||||||
|
}, this._heartbeatIntervalMs);
|
||||||
|
}
|
||||||
callback(undefined, this._connectionIfExists);
|
callback(undefined, this._connectionIfExists);
|
||||||
});
|
});
|
||||||
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
|
this._client.on(WebsocketClientEventType.ConnectFailed, error => {
|
||||||
|
@ -63,6 +63,7 @@ const docsInfoConfig: DocsInfoConfig = {
|
|||||||
'TokenPairsRequest',
|
'TokenPairsRequest',
|
||||||
'TokenPairsRequestOpts',
|
'TokenPairsRequestOpts',
|
||||||
'TokenTradeInfo',
|
'TokenTradeInfo',
|
||||||
|
'WebSocketOrderbookChannelConfig',
|
||||||
'Order',
|
'Order',
|
||||||
'SignedOrder',
|
'SignedOrder',
|
||||||
'ECSignature',
|
'ECSignature',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user