Merge pull request #104 from BeaudanBrown/pow-refactor
Refactor PoW calculation to use webworkers Fixes #100pull/107/head
commit
76cdf61ef9
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,124 @@
|
||||
/* global Worker, window, setTimeout */
|
||||
|
||||
const WORKER_TIMEOUT = 60 * 1000; // one minute
|
||||
|
||||
class TimedOutError extends Error {
|
||||
constructor(message) {
|
||||
super(message);
|
||||
this.name = this.constructor.name;
|
||||
if (typeof Error.captureStackTrace === 'function') {
|
||||
Error.captureStackTrace(this, this.constructor);
|
||||
} else {
|
||||
this.stack = (new Error(message)).stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class WorkerInterface {
|
||||
constructor(path) {
|
||||
this._utilWorker = new Worker(path);
|
||||
this._jobs = Object.create(null);
|
||||
this._DEBUG = false;
|
||||
this._jobCounter = 0;
|
||||
|
||||
this._utilWorker.onmessage = e => {
|
||||
const [jobId, errorForDisplay, result] = e.data;
|
||||
|
||||
const job = this._getJob(jobId);
|
||||
if (!job) {
|
||||
throw new Error(
|
||||
`Received worker reply to job ${jobId}, but did not have it in our registry!`
|
||||
);
|
||||
}
|
||||
|
||||
const { resolve, reject, fnName } = job;
|
||||
|
||||
if (errorForDisplay) {
|
||||
return reject(
|
||||
new Error(
|
||||
`Error received from worker job ${jobId} (${fnName}): ${errorForDisplay}`
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return resolve(result);
|
||||
};
|
||||
}
|
||||
|
||||
_makeJob (fnName) {
|
||||
this._jobCounter += 1;
|
||||
const id = this._jobCounter;
|
||||
|
||||
if (this._DEBUG) {
|
||||
window.log.info(`Worker job ${id} (${fnName}) started`);
|
||||
}
|
||||
this._jobs[id] = {
|
||||
fnName,
|
||||
start: Date.now(),
|
||||
};
|
||||
|
||||
return id;
|
||||
};
|
||||
|
||||
_updateJob(id, data) {
|
||||
const { resolve, reject } = data;
|
||||
const { fnName, start } = this._jobs[id];
|
||||
|
||||
this._jobs[id] = {
|
||||
...this._jobs[id],
|
||||
...data,
|
||||
resolve: value => {
|
||||
this._removeJob(id);
|
||||
const end = Date.now();
|
||||
window.log.info(
|
||||
`Worker job ${id} (${fnName}) succeeded in ${end - start}ms`
|
||||
);
|
||||
return resolve(value);
|
||||
},
|
||||
reject: error => {
|
||||
this._removeJob(id);
|
||||
const end = Date.now();
|
||||
window.log.info(
|
||||
`Worker job ${id} (${fnName}) failed in ${end - start}ms`
|
||||
);
|
||||
return reject(error);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
_removeJob(id) {
|
||||
if (this._DEBUG) {
|
||||
this._jobs[id].complete = true;
|
||||
} else {
|
||||
delete this._jobs[id];
|
||||
}
|
||||
}
|
||||
|
||||
_getJob(id) {
|
||||
return this._jobs[id];
|
||||
};
|
||||
|
||||
callWorker(fnName, ...args) {
|
||||
const jobId = this._makeJob(fnName);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this._utilWorker.postMessage([jobId, fnName, ...args]);
|
||||
|
||||
this._updateJob(jobId, {
|
||||
resolve,
|
||||
reject,
|
||||
args: this._DEBUG ? args : null,
|
||||
});
|
||||
|
||||
setTimeout(
|
||||
() => reject(new TimedOutError(`Worker job ${jobId} (${fnName}) timed out`)),
|
||||
WORKER_TIMEOUT
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
WorkerInterface,
|
||||
TimedOutError,
|
||||
};
|
Loading…
Reference in New Issue