Skip to content

Instantly share code, notes, and snippets.

@arzmir
Last active July 5, 2019 10:53
Show Gist options
  • Save arzmir/573cd7e0951528bc8905fe3cbac1a83f to your computer and use it in GitHub Desktop.
Save arzmir/573cd7e0951528bc8905fe3cbac1a83f to your computer and use it in GitHub Desktop.
Problems with Electron, wait-on package, app.ready, event queue
const waitOn = require('wait-on');
const Poller = require('./electron/Poller');
console.time(':');
const waitonCaller = () => {
return new Promise((resolve, reject) => {
try {
waitOn(
{
resources: ['http://localhost:8999/health'],
delay: 500,
interval: 250,
timeout: 2000,
reverse: true,
log: true,
verbose: true,
},
() => resolve('yay')
);
} catch (err) {
reject(err);
}
});
};
const pollerCaller = async () => {
const opts = {
expectingResponse: false,
startupDelay: 500,
pollingInterval: 250,
timesToPoll: 6,
};
const result = await new Poller('http://localhost:8999/health', opts).execute();
return result;
};
(async () => {
console.timeLog(':', 'Pre waitOn');
await waitonCaller();
// await pollerCaller();
console.timeLog(':', 'Post waitOn');
})();
process.on('beforeExit', () => {
console.timeLog(':', 'Elapsed time.');
});
const axios = require('axios');
const defaultOptions = {
axiosTimeout: 900,
chosenLogger: console.log,
expectingResponse: true,
pollingInterval: 1000,
startUpDelay: 1000,
timesToPoll: 5,
silent: false,
};
class Poller {
constructor(url, suppliedOptions = {}) {
const options = { ...defaultOptions, ...suppliedOptions };
this.url = url;
this.promises = [];
this.timeouts = [];
Object.entries(options).forEach(([key, value]) => {
if (Poller.MIN_VALUES[key]) {
this[key] = Math.min(Math.max(Poller.MIN_VALUES[key], value), Poller.MAX_VALUES[key]);
} else {
this[key] = value;
}
});
this.source = axios.CancelToken.source();
this.axiosClient = axios.create({
timeout: this.axiosTimeout,
baseURL: this.url,
headers: { 'Access-Control-Allow-Origin': '*' },
cancelToken: this.source.token,
});
}
cancelRemainingRequests(current) {
this.source.cancel();
this.timeouts.forEach((timeout, idx) => {
if (idx !== current) {
clearTimeout(timeout);
delete this.timeouts[idx];
}
});
this.promises.forEach((_, idx) => {
if (idx !== current) {
this.promises[idx].reject();
delete this.promises[idx];
}
});
}
caller(resolve, reject, i) {
const time = Math.floor(new Date() - this.startTime);
if (!this.silent) this.chosenLogger(`Executing ${i}. call..`, `[${time} ms]`);
return this.axiosClient
.get()
.then(() => {
this.logForPoll(true, this.expectingResponse, i);
if (this.expectingResponse === true) {
this.cancelRemainingRequests(i);
resolve({
success: true,
message: `Resource responded on poll #${i}`,
elapsedTime: `${Math.floor(new Date() - this.startTime)}ms`,
});
} else if (i === this.timesToPoll) {
reject({
success: false,
message: `All ${i} polls completed without success.`,
elapsedTime: `${Math.floor(new Date() - this.startTime)}ms`,
});
}
})
.catch(error => {
if (axios.isCancel(error) === false) {
this.logForPoll(false, this.expectingResponse, i);
if (this.expectingResponse === false) {
this.cancelRemainingRequests(i);
resolve({
success: true,
message: `Resource stopped responding on poll #${i}`,
elapsedTime: `${Math.floor(new Date() - this.startTime)}ms`,
});
} else if (i === this.timesToPoll) {
reject({
success: false,
message: `All ${i} polls completed without success.`,
elapsedTime: `${Math.floor(new Date() - this.startTime)}ms`,
});
}
}
});
}
logForPoll(gotResponse, expectingResponse, i) {
const time = Math.floor(new Date() - this.startTime);
if (!this.silent) {
if (expectingResponse) {
if (gotResponse) {
this.chosenLogger(`Received response as expected on poll #${i}. Resolving poller...`, `[${time} ms]`);
} else {
this.chosenLogger(`Didn't receive response yet on poll #${i}. Continueing polling...`, `[${time} ms]`);
}
} else {
// eslint-disable-next-line no-lonely-if
if (gotResponse) {
this.chosenLogger(`Still received response on poll #${i}. Continueing polling...`, `[${time} ms]`);
} else {
this.chosenLogger(`Received error as expected for poll #${i}. Resolving poller...`, `[${time} ms]`);
}
}
}
}
execute() {
this.startTime = new Date();
if (!this.silent) this.chosenLogger(`Checking ${this.url} expecting ${this.expectingResponse ? 'a' : 'no'} response.`);
for (let i = 1; i < this.timesToPoll + 1; i += 1) {
this.promises.push(
// eslint-disable-next-line no-loop-func
new Promise((resolve, reject) => {
const timeout = this.startUpDelay + this.pollingInterval * i;
this.timeouts.push(setTimeout(async () => this.caller(resolve, reject, i), timeout));
})
);
}
return Promise.race(this.promises)
.then(result => Promise.resolve(result))
.catch(result => Promise.resolve(result));
}
}
Poller.MIN_VALUES = {
axiosTimeout: 250,
pollingInterval: 100,
startUpDelay: 100,
timesToPoll: 1,
};
Poller.MAX_VALUES = {
axiosTimeout: 30000,
pollingInterval: 10000,
startUpDelay: 30000,
timesToPoll: 25,
};
module.exports = Poller;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment