简体   繁体   English

Express:每秒运行一次中间件

[英]Express: run middleware once per second

I have an express server that is running as an API, and I have a middleware loaded as such: 我有一个运行为API的快速服务器,并且已加载了这样的中间件:

app.js app.js

const lastActivity = require('./middleware/lastActivity');
app.use(lastActivity);`

middleware/lastActivity.js middleware / 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();
            }
        });
    }
});

So it checks whether the last_activity date saved on the user is a different day than today, and if so updates the user (I only care about the date, not the specific timestamp). 因此,它将检查保存在用户上的last_activity日期是否与今天不同,并更新用户(我只关心日期,而不关心特定的时间戳)。 It also does an API call to an external service to manage email marketing campaigns. 它还对外部服务进行API调用,以管理电子邮件营销活动。

The problem however is that my web app requests two resources on page load at the same time. 但是问题是我的Web应用程序同时请求页面加载时的两个资源。 This means the isDifferentDay returns true for both of them, and the user model updates twice and more importantly I do two API calls to the external service which is rate limited. 这意味着isDifferentDay返回true,并且用户模型更新两次,更重要的是,我对速率受限的外部服务进行了两次API调用。

One obvious solution is to only do one request on my client at a time, but I don't really want to limit myself to that. 一个明显的解决方案是一次只对我的客户发出一个请求,但是我真的不希望局限于此。 What I want is a sort of express 'lock' which will only run the middleware once per second? 我想要的是一种快速的“锁定”,每秒只能运行一次中间件? Or some other solution that I can't see. 或其他我看不到的解决方案。

What is the best way to handle this in a express/node manner? 以快速/节点方式处理此问题的最佳方法是什么?

Thank you. 谢谢。

This problem is a typical race condition. 此问题是典型的比赛情况。
Since you only care about user's last_activity once per day, instead of using findById you can add an additional filter to DB request AND update it in one go. 由于您每天只关心用户的last_activity ,因此无需使用findById您可以向数据库请求中添加其他过滤器并一次性更新。 Eg 例如

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
});

That way, you'll only update the user if it's last_activity was left unchanged between your actions. 这样,只有在last_activity操作之间的last_activity保持不变的情况下,您才更新用户。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM