Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

Fix Secure API hangs #3927

Merged
merged 11 commits into from
Dec 21, 2016
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
"react-hot-loader": "3.0.0-beta.6",
"react-intl-aggregate-webpack-plugin": "0.0.1",
"rucksack-css": "0.9.1",
"script-ext-html-webpack-plugin": "1.3.4",
"serviceworker-webpack-plugin": "0.1.7",
"sinon": "1.17.6",
"sinon-as-promised": "4.0.2",
Expand All @@ -125,7 +126,7 @@
"stylelint": "7.6.0",
"stylelint-config-standard": "15.0.0",
"url-loader": "0.5.7",
"webpack": "2.1.0-beta.27",
"webpack": "2.2.0-rc.1",
"webpack-dev-middleware": "1.8.4",
"webpack-error-notification": "0.1.6",
"webpack-hot-middleware": "2.13.2",
Expand Down
61 changes: 49 additions & 12 deletions js/src/api/transport/ws/ws.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import TransportError from '../error';

/* global WebSocket */
export default class Ws extends JsonRpcBase {
constructor (url, token) {
constructor (url, token, connect = true) {
super();

this._url = url;
Expand All @@ -32,23 +32,34 @@ export default class Ws extends JsonRpcBase {
this._connecting = false;
this._connected = false;
this._lastError = null;
this._autoConnect = true;
this._autoConnect = false;
this._retries = 0;
this._reconnectTimeoutId = null;

this._connect();
this._connectPromise = null;
this._connectPromiseFunctions = {};

if (connect) {
this.connect();
}
}

updateToken (token) {
updateToken (token, connect = true) {
this._token = token;
this._autoConnect = true;
// this._autoConnect = true;

this._connect();
if (connect) {
this.connect();
}
}

_connect () {
connect () {
if (this._connected) {
return Promise.resolve();
}

if (this._connecting) {
return;
return this._connectPromise || Promise.resolve();
}

if (this._reconnectTimeoutId) {
Expand Down Expand Up @@ -104,10 +115,17 @@ export default class Ws extends JsonRpcBase {

window._parityWS = this;
}

this._connectPromise = new Promise((resolve, reject) => {
this._connectPromiseFunctions = { resolve, reject };
});

return this._connectPromise;
}

_onOpen = (event) => {
console.log('ws:onOpen', event);
console.log('ws:onOpen');

this._connected = true;
this._connecting = false;
this._autoConnect = true;
Expand All @@ -116,6 +134,11 @@ export default class Ws extends JsonRpcBase {
Object.keys(this._messages)
.filter((id) => this._messages[id].queued)
.forEach(this._send);

this._connectPromiseFunctions.resolve();

this._connectPromise = null;
this._connectPromiseFunctions = {};
}

_onClose = (event) => {
Expand All @@ -135,24 +158,38 @@ export default class Ws extends JsonRpcBase {
console.log('ws:onClose', `trying again in ${time}...`);

this._reconnectTimeoutId = setTimeout(() => {
this._connect();
this.connect();
}, timeout);

return;
}

console.log('ws:onClose', event);
if (this._connectPromise) {
this._connectPromiseFunctions.reject(event);

this._connectPromise = null;
this._connectPromiseFunctions = {};
}

console.log('ws:onClose');
}

_onError = (event) => {
// Only print error if the WS is connected
// ie. don't print if error == closed
window.setTimeout(() => {
if (this._connected) {
console.error('ws:onError', event);
console.error('ws:onError');

event.timestamp = Date.now();
this._lastError = event;

if (this._connectPromise) {
this._connectPromiseFunctions.reject(event);

this._connectPromise = null;
this._connectPromiseFunctions = {};
}
}
}, 50);
}
Expand Down
7 changes: 1 addition & 6 deletions js/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,7 @@ if (process.env.NODE_ENV === 'development') {
}

const AUTH_HASH = '#/auth?';
const parityUrl = process.env.PARITY_URL ||
(
process.env.NODE_ENV === 'production'
? window.location.host
: '127.0.0.1:8180'
);
const parityUrl = process.env.PARITY_URL || window.location.host;

let token = null;
if (window.location.hash && window.location.hash.indexOf(AUTH_HASH) === 0) {
Expand Down
55 changes: 0 additions & 55 deletions js/src/redux/providers/status.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,18 @@ export default class Status {
this._api = api;
this._store = store;

this._pingable = false;
this._apiStatus = {};
this._status = {};
this._longStatus = {};
this._minerSettings = {};

this._pollPingTimeoutId = null;
this._longStatusTimeoutId = null;

this._timestamp = Date.now();
}

start () {
this._subscribeBlockNumber();
this._pollPing();
this._pollStatus();
this._pollLongStatus();
this._pollLogs();
Expand Down Expand Up @@ -65,50 +62,6 @@ export default class Status {
});
}

/**
* Pinging should be smart. It should only
* be used when the UI is connecting or the
* Node is deconnected.
*
* @see src/views/Connection/connection.js
*/
_shouldPing = () => {
const { isConnected } = this._apiStatus;
return !isConnected;
}

_stopPollPing = () => {
if (!this._pollPingTimeoutId) {
return;
}

clearTimeout(this._pollPingTimeoutId);
this._pollPingTimeoutId = null;
}

_pollPing = () => {
// Already pinging, don't try again
if (this._pollPingTimeoutId) {
return;
}

const dispatch = (pingable, timeout = 1000) => {
if (pingable !== this._pingable) {
this._pingable = pingable;
this._store.dispatch(statusCollection({ isPingable: pingable }));
}

this._pollPingTimeoutId = setTimeout(() => {
this._stopPollPing();
this._pollPing();
}, timeout);
};

fetch('/', { method: 'HEAD' })
.then((response) => dispatch(!!response.ok))
.catch(() => dispatch(false));
}

_pollTraceMode = () => {
return this._api.trace.block()
.then(blockTraces => {
Expand Down Expand Up @@ -137,21 +90,13 @@ export default class Status {

if (gotConnected) {
this._pollLongStatus();
this._store.dispatch(statusCollection({ isPingable: true }));
}

if (!isEqual(apiStatus, this._apiStatus)) {
this._store.dispatch(statusCollection(apiStatus));
this._apiStatus = apiStatus;
}

// Ping if necessary, otherwise stop pinging
if (this._shouldPing()) {
this._pollPing();
} else {
this._stopPollPing();
}

if (!isConnected) {
return nextTimeout(250);
}
Expand Down
1 change: 0 additions & 1 deletion js/src/redux/providers/statusReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const initialState = {
syncing: true,
isConnected: false,
isConnecting: false,
isPingable: false,
isTest: undefined,
refreshStatus: false,
traceMode: undefined
Expand Down
Loading