查找与锁定和更新调度相关的一个或两个节点模块

Looking for one or two Node modules related to locking and update scheduling

本文关键字:一个 两个 模块 节点 锁定 调度 更新 查找      更新时间:2023-09-26

有些人会认为这太琐碎了,不适合寻找模块,也不适合将其归入leftPad类别,但npm中有很多东西,我觉得这两个需求都涵盖了,所以我很想看看其他人做了什么。我继承了这个代码库,它有这种长时间的更新功能,只需要几个步骤。它有一个自定义的锁定标志,一半设置为过期,但实际上没有过期代码。不管怎样,最重要的是防止更新在其他事情发生时发生。除了有时我们知道我们肯定需要尽快更新,但不是在当前更新的中间。这东西实际上不太管用。所以我正在寻找一两个模块来做两件事:

  1. 两个不同的长时间运行的函数(用回调调用其他函数)可以使用一个带有过期的锁来确保它们不会踩到对方的

  2. 一个简单的模块/函数,上面写着"现在执行此函数,或者在完成当前运行后再次运行"。

或者,在这种情况下,处理这两种情况的东西可能真的有意义,尽管根据我的描述,它们之间的关系可能并不明显。

过期是指,如果出现我预计不会导致锁在很长一段时间内无法移除的情况,我们不想永远被卡住。

这里有一个例子:

function update() {
  // if we are trading, wait until that is done
  // if currently updating, skip it or schedule another one right
  // after, but only need one more, not a queue of updates
  // make a bunch of callbacks or a promise chain, takes a few seconds
  // in some cases we will find that we need to do one more update
  // immediately after all of this finishes, but not until the end
}
// ...some other places that want to call update
function trade() {
  // trade happens sort of sporadically when the tick event fires
  // if we are updating, wait until we are done
  // make a bunch of callbacks or a promise chain, takes a few seconds
  // at the end we need to call update
  // but it can't  update if it is already updating
}
var Promise = require('bluebird');
// note using a bluebird type of promise
const tradeQueue = [];
var currentlyTrading = false;
var currentlyUpdating = false;
var pendingUpdate = null;
var queuedUpdatePromiseDetails = null;
// returns a promise that returns void, the promise will return
// when either the currently executing update finishes, or a fresh one
// does
function update() {
  var test = Math.floor(Math.random() * 1000);
  console.log(test, 'update call');
  if (!pendingUpdate) {
    pendingUpdate = new Promise(function (resolve, reject) {
      queuedUpdatePromiseDetails = { resolve: resolve, reject: reject, test: test };
      if (currentlyTrading) {
        console.log(test, 'setting update to pending');
      } else {
        // perform update, in callback call resolve() if no err, otherwise reject(err)
        console.log(test, 'running update');
        currentlyUpdating = true;
        setTimeout(resolve, 100);
      }
    }).finally(function () {
      currentlyUpdating = false;
      console.log(test, 'update call complete');
      pendingUpdate = null;
      queuedUpdatePromiseDetails = null;
      runPendingTradeOrUpdate();
    });
  } else {
    console.log(test, 'returning existing update promise', queuedUpdatePromiseDetails.test);
  }
  return pendingUpdate;
}
// returns a promise that completes when this
// new trade finishes
function trade(param) {
  var test = Math.floor(Math.random() * 1000);
  console.log(test, 'trade call');
  return new Promise(function (resolve, reject) {
    if (currentlyTrading || currentlyUpdating) {
      console.log(test, 'queued trade')
      var newTrade = { param: param, resolve: resolve, reject: reject, test: test };
      tradeQueue.push(newTrade);
    } else {
      currentlyTrading = true;
      console.log(test, 'beginning trade run');
      // perform trade, in callback call resolve() if no error, otherwise reject(err)
      setTimeout(resolve, 100);
    }
  }).finally(function () {
    console.log(test, 'trade call complete');
    // note that this bit is run for every single trade
    currentlyTrading = false;
    runPendingTradeOrUpdate();
  });
}
// dequeue next trade and run it
function runPendingTradeOrUpdate() {
  if (queuedUpdatePromiseDetails && !currentlyUpdating && !currentlyTrading) {
    // perform update, in callback call resolve() if no err, otherwise reject(err)
    console.log(queuedUpdatePromiseDetails.test, 'running pending update');
    currentlyUpdating = true;
    setTimeout(queuedUpdatePromiseDetails.resolve, 100);
  } else {
    if (tradeQueue.length > 0 && !currentlyTrading) {
      var nextTrade = tradeQueue.shift();
      console.log(nextTrade.test, 'calling queued trade');
      trade(nextTrade.param).then(nextTrade.resolve).catch(nextTrade.reject);
    }
  }
}

var runRandomly = function () {
  setTimeout(function () {
    update();
  }, Math.floor(Math.random() * 300))
  setTimeout(function () {
    trade(null);
  }, Math.floor(Math.random() * 300))
  setTimeout(function () {
    runRandomly();
  }, Math.floor(Math.random() * 300))
}
runRandomly();

好的,非常感谢你们的帮助。

这就是我决定要做的:我现在或再次创建了一个非常简单的模块,并使用现有的带有maxPending功能的锁,而不是过期时间。

我使用这两个模块的方式与自述文件中的示例完全相同。