message: fix processing state in work pool persisting across sessions
diff: @@ -10,6 +10,8 @@ export class WorkPoolService {
  cacheLength = 25;
  workCache = [];
  + currentlyProcessingHashes = {};
  +
  constructor(private pow: PowService, private notifications: NotificationService, private util: UtilService) { }
  sleep(ms) {
  @@ -48,49 +50,36 @@ export class WorkPoolService {
  // Get work for a hash. Uses the cache, or the current setting for generating it.
  public async getWork(hash, multiplier = 1) {
  - let cached = this.workCache.find(p => p.hash === hash);
  - const tempWork = '1';
  -
  - // if work is requested while work is already being processed for this hash
  - if (cached && cached.work === tempWork) {
  - // wait for current pow to finish or fail
  - while (cached && cached.work === tempWork) {
  + while ( this.currentlyProcessingHashes[hash] === true ) {
  await this.sleep(100);
  - cached = this.workCache.find(p => p.hash === hash);
  }
  +
  + const cached = this.workCache.find(p => p.hash === hash);
  +
  + try {
  if (cached && cached.work &&
  this.util.nano.validateWork(hash, this.util.nano.difficultyFromMultiplier(multiplier, baseThreshold), cached.work)) {
  - console.log('Using pre-processed work: ' + cached.work);
  - return cached.work;
  - }
  - // if the work was invalid and removed from cache, also invalidate the response
  - console.log('Invalid pre-processed work');
  - return null;
  - } else if (cached && cached.work &&
  - this.util.nano.validateWork(hash, this.util.nano.difficultyFromMultiplier(multiplier, baseThreshold), cached.work)) {
  console.log('Using cached work: ' + cached.work);
  return cached.work;
  }
  + } catch(err) {
  + console.log('Error validating cached work. ' + err);
  + }
  - // add temp work to prevent duplicate hashes in the cache due to asynchronous calls during "await"
  - let work = tempWork;
  - this.workCache.push({ hash, work });
  + this.currentlyProcessingHashes[hash] = true;
  +
  + const work = await this.pow.getPow(hash, multiplier);
  - work = await this.pow.getPow(hash, multiplier);
  if (!work) {
  this.notifications.sendWarning(`Failed to retrieve work for ${hash}. Try a different PoW method.`);
  - // remove temp work (will also break the while loop above for parallel threads)
  - const x = this.workCache.findIndex(p => p.hash === hash && p.work === tempWork);
  - if (x !== -1) this.workCache.splice(x, 1);
  + delete this.currentlyProcessingHashes[hash];
  return null;
  }
  console.log('Work found: ' + work);
  - this.workCache.push({ hash, work }); // add the real work
  - // remove temp work (important to remove after push to avoid possible race condition)
  - const index = this.workCache.findIndex(p => p.hash === hash && p.work === tempWork);
  - if (index !== -1) this.workCache.splice(index, 1);
  + this.workCache.push({ hash, work });
  + delete this.currentlyProcessingHashes[hash];
  if (this.workCache.length >= this.cacheLength) this.workCache.shift(); // Prune if we are at max length
  this.saveWorkCache();
  