Add connected() to API interface (#2580)

* Add connected() to API interface

* Slight doc update

* Align ApiRx

* isConnected() usage

* Updates

* Retrieve isConnected for API via observable

* Remove (now) useless Rx test
This commit is contained in:
Jaco Greeff
2020-09-04 17:57:02 +02:00
committed by GitHub
parent 4f4833da74
commit 00bc441f0e
17 changed files with 125 additions and 72 deletions
+1 -1
View File
@@ -31,7 +31,7 @@ describe('Http', (): void => {
});
it('always returns isConnected true', (): void => {
expect(http.isConnected()).toEqual(true);
expect(http.isConnected).toEqual(true);
});
it('does not (yet) support subscribe', (): Promise<number | void> => {
+9 -2
View File
@@ -67,10 +67,17 @@ export default class HttpProvider implements ProviderInterface {
throw new Error('Unimplemented');
}
/**
* @description Manually connect from the connection
*/
public async connect (): Promise<void> {
// noop
}
/**
* @description Manually disconnect from the connection
*/
public disconnect (): void {
public async disconnect (): Promise<void> {
// noop
}
@@ -78,7 +85,7 @@ export default class HttpProvider implements ProviderInterface {
* @summary Whether the node is connected or not.
* @return {boolean} true if connected
*/
public isConnected (): boolean {
public get isConnected (): boolean {
return true;
}
+6 -2
View File
@@ -98,11 +98,15 @@ export default class Mock implements ProviderInterface {
throw new Error('Unimplemented');
}
public disconnect (): void {
public async connect (): Promise<void> {
// noop
}
public isConnected (): boolean {
public async disconnect (): Promise<void> {
// noop
}
public get isConnected (): boolean {
return true;
}
+4 -2
View File
@@ -44,9 +44,11 @@ export type ProviderInterfaceEmitCb = (value?: any) => any;
export interface ProviderInterface {
readonly hasSubscriptions: boolean;
readonly isConnected: boolean;
clone (): ProviderInterface;
disconnect (): void;
isConnected (): boolean;
connect (): Promise<void>;
disconnect (): Promise<void>;
on (type: ProviderInterfaceEmitted, sub: ProviderInterfaceEmitCb): () => void;
send (method: string, params: any[]): Promise<any>;
subscribe (type: string, method: string, params: any[], cb: ProviderInterfaceCallback): Promise<number | string>;
+32 -26
View File
@@ -30,10 +30,6 @@ interface WsStateSubscription extends SubscriptionHandler {
params: any[];
}
interface WSProviderInterface extends ProviderInterface {
connect (): void;
}
const ALIASSES: { [index: string]: string } = {
chain_finalisedHead: 'chain_finalizedHead',
chain_subscribeFinalisedHeads: 'chain_subscribeFinalizedHeads',
@@ -62,7 +58,7 @@ const l = logger('api-ws');
*
* @see [[HttpProvider]]
*/
export default class WsProvider implements WSProviderInterface {
export default class WsProvider implements ProviderInterface {
readonly #coder: Coder;
readonly #endpoints: string[];
@@ -123,6 +119,14 @@ export default class WsProvider implements WSProviderInterface {
return true;
}
/**
* @summary Whether the node is connected or not.
* @return {boolean} true if connected
*/
public get isConnected (): boolean {
return this.#isConnected;
}
/**
* @description Returns a clone of the object
*/
@@ -152,31 +156,34 @@ export default class WsProvider implements WSProviderInterface {
this.#websocket.onopen = this.#onSocketOpen;
} catch (error) {
l.error(error);
this.#emit('error', error);
throw error;
}
}
/**
* @description Manually disconnect from the connection, clearing autoconnect logic
*/
public disconnect (): void {
if (isNull(this.#websocket)) {
throw new Error('Cannot disconnect on a non-open websocket');
// eslint-disable-next-line @typescript-eslint/require-await
public async disconnect (): Promise<void> {
try {
assert(!isNull(this.#websocket), 'Cannot disconnect on a non-connected websocket');
// switch off autoConnect, we are in manual mode now
this.#autoConnectMs = 0;
// 1000 - Normal closure; the connection successfully completed
this.#websocket.close(1000);
this.#websocket = null;
} catch (error) {
l.error(error);
this.#emit('error', error);
throw error;
}
// switch off autoConnect, we are in manual mode now
this.#autoConnectMs = 0;
// 1000 - Normal closure; the connection successfully completed
this.#websocket.close(1000);
this.#websocket = null;
}
/**
* @summary Whether the node is connected or not.
* @return {boolean} true if connected
*/
public isConnected (): boolean {
return this.#isConnected;
}
/**
@@ -220,7 +227,7 @@ export default class WsProvider implements WSProviderInterface {
subscription
};
if (this.isConnected() && !isNull(this.#websocket)) {
if (this.isConnected && !isNull(this.#websocket)) {
this.#websocket.send(json);
} else {
this.#queued[id] = json;
@@ -297,8 +304,7 @@ export default class WsProvider implements WSProviderInterface {
if (this.#autoConnectMs > 0) {
setTimeout((): void => {
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.connect();
this.connect().catch(() => { /* noop */ });
}, this.#autoConnectMs);
}
}
+8 -8
View File
@@ -30,26 +30,26 @@ describe('onConnect', (): void => {
it('Does not connect when autoConnect is false', (): void => {
const provider: WsProvider = new WsProvider(TEST_WS_URL, 0);
expect(provider.isConnected()).toBe(false);
expect(provider.isConnected).toBe(false);
});
it('Does connect when autoConnect is true', async () => {
const provider: WsProvider = new WsProvider(TEST_WS_URL, 1);
await sleepMs(100); // Hack to give the provider time to connect
expect(provider.isConnected()).toBe(true);
expect(provider.isConnected).toBe(true);
});
it('Creates a new WebSocket instance by calling the connect() method', async () => {
const provider: WsProvider = new WsProvider(TEST_WS_URL, false);
expect(provider.isConnected()).toBe(false);
expect(provider.isConnected).toBe(false);
expect(mocks[0].server.clients().length).toBe(0);
await provider.connect();
await sleepMs(100); // Hack to give the provider time to connect
expect(provider.isConnected()).toBe(true);
expect(provider.isConnected).toBe(true);
expect(mocks[0].server.clients().length).toBe(1);
});
@@ -59,7 +59,7 @@ describe('onConnect', (): void => {
await provider.connect();
await sleepMs(100); // Hack to give the provider time to connect
expect(provider.isConnected()).toBe(true);
expect(provider.isConnected).toBe(true);
});
it('Connects to the second endpoint when the first is unreachable', async () => {
@@ -71,7 +71,7 @@ describe('onConnect', (): void => {
await sleepMs(100); // Hack to give the provider time to connect
expect(provider.isConnected()).toBe(true);
expect(provider.isConnected).toBe(true);
});
it('Connects to the second endpoint when the first is dropped', async () => {
@@ -92,7 +92,7 @@ describe('onConnect', (): void => {
// Check that second server is connected
expect(mocks[1].server.clients().length).toBe(1);
expect(provider.isConnected()).toBe(true);
expect(provider.isConnected).toBe(true);
});
it('Round-robin of endpoints on WsProvider', async () => {
@@ -124,7 +124,7 @@ describe('onConnect', (): void => {
// Check that first server is connected and the next one isn't
expect(mocks[index].server.clients().length).toBe(1);
expect(mockNext[index].server.clients().length).toBe(0);
expect(provider.isConnected()).toBe(true);
expect(provider.isConnected).toBe(true);
// Close connection from first server
mocks[index].server.clients()[0].close();
+1 -1
View File
@@ -25,7 +25,7 @@ describe('Ws', (): void => {
it('returns the connected state', (): void => {
expect(
createWs([]).isConnected()
createWs([]).isConnected
).toEqual(false);
});