how can i avoid race conditions in node.js when i'm manipulating the session via socket.io?

我的梦境 提交于 2019-12-10 18:07:33

问题


i'm using this authorization function in my socket.io setup:

io.set('authorization', function (data, accept) {
    if (!data.headers.cookie) {
        return accept('Session cookie required.', false);
    }
    data.cookie = require("cookie").parse(data.headers.cookie);
    data.cookie = require("connect").utils.parseSignedCookies(data.cookie,"yeah whatever");
    data.sessionID = data.cookie['connect.sid'];
    sessionStore.get(data.sessionID, function(err, session){
        if (err) {
            return accept('Error in session store.', false);
        } else if (!session) {
            return accept('Session not found.', false);
        }
        // success! we're authenticated with a known session.info.
        return accept(null, true);
    });
});

then i manipulate the session variables like this:

var addAchievementToUser = function(achievement, sessionID) {
    sessionStore.get(sessionID, function(err, session) {
            //stuff happens here such as
            session.info.username = "whatever";
            sessionStore.set(sessionID, session, function () {
            });
        }
    });
};

this works fine and does what i want but sometimes it produces some evil race conditions.

so, how can i rewrite this so that it does not create race conditions? i've looked into the connect middleware to see if it is possible to manipulate only a single key / value pair instead of the whole session object. but it seems that this is not possible since the session needs to be a string:

MemoryStore.prototype.set = function(sid, sess, fn){
    var self = this;
    process.nextTick(function(){
        self.sessions[sid] = JSON.stringify(sess);
        fn && fn();
  });
};

any ideas?


回答1:


ok so I started using redis middleware which didn't really help me with the problem. anyway, i basically only edit the session via socket.io (and once when the client first connects), so i figured it'd be the "best" to create a session array which contains all active sessions like this:

io.set('authorization', function (data, accept) {
    if (!data.headers.cookie) {
        return accept('Session cookie required.', false);
    }
    data.cookie = require("cookie").parse(data.headers.cookie);
    data.cookie = require("connect").utils.parseSignedCookies(data.cookie, "rawr");
    data.sessionID = data.cookie['connect.sid'];
    sessionStore.get(data.sessionID, function(err, session){
        if (err) {
            return accept('Error in session store.', false);
        } else if (!session) {
            return accept('Session not found.', false);
        }
        // success! we're authenticated with a known session.info.
        if (!sessions[data.sessionID]) {
            sessions[data.sessionID] = session;
        }

        return accept(null, true);
    });
});

so i never need to use the get session method to edit my session data (only the set method). the good thing is that this way it even works when the same client connects with multiple sockets.



来源:https://stackoverflow.com/questions/11165319/how-can-i-avoid-race-conditions-in-node-js-when-im-manipulating-the-session-via

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!