我有一个作为API运行的快速服务器,我有一个中间件加载:
app.js
const lastActivity = require('./middleware/lastActivity');
app.use(lastActivity);`
中间件/ lastActivity.js
module.exports = function(req, res, next) {
if (req.user && isDifferentDay(req.user.last_activity) {
User.findById(req.user.id, (err, user) => {
user.last_activity = Date.now();
user.save((err) => {
// also do another async call to an external service, then
return next();
}
});
}
});
因此它检查用户保存的last_activity日期是否与今天不同,如果是,则更新用户(我只关心日期,而不是特定的时间戳)。它还对外部服务进行API调用以管理电子邮件营销活动。
但问题是我的网络应用程序同时在页面加载时请求两个资源。这意味着isDifferentDay
对它们都返回true,并且用户模型更新两次,更重要的是我对外部服务进行两次API调用,这是对速率的限制。
一个明显的解决方案是一次只在我的客户端上做一个请求,但我并不想限制自己。我想要的是一种快速锁定'每秒只运行一次中间件?或者其他一些我无法看到的解决方案。
以快速/节点方式处理此问题的最佳方法是什么?
谢谢。
答案 0 :(得分:1)
这个问题是典型的竞争条件
由于您每天只关心用户last_activity
一次,而不是使用findById
,您可以为数据库请求添加额外的过滤器并一次更新。
E.g。
var query = {
_id: req.user.id,
last_activity: req.user.last_activity
};
User.findOneAndUpdate(query, { last_activity: Date.now() }, (err, user) => {
if (!user)
return; // user was changed between requests, do nothing
// ... the rest of your code
});
这样,只有在您的操作之间保持last_activity
不变的情况下,您才会更新用户。