0

I am building an application using node.js and socket.io. I would like to create a table of users who are actively browsing the site at any given moment, which will update dynamically.

I am setting a cookie to give each browser a unique ID, and have a mysql database of all users (whether online or not); however, I'm not sure how best to use these two pieces of information to determine who is, and who isn't, actively browsing right now.

The simplest way would seem to be to store the cookie & socket IDs in an array, but I have read that global variables (which presumably this would have to be) are generally bad, and to be avoided.

Alternatively I could create a new database table, where IDs are inserted and deleted when a socket connects/disconnects; but I'm not sure whether this would be overkill.

Is one of these methods any better than the other, or is there a way of tracking this information which I haven't thought of yet?

1 Answer 1

3

You can keep track of active users in memory without it being a global variable. It can simply be a module level variable. This is one of the advantages of the nodejs module system.

The reasons to put it in a database instead of memory are:

  1. You have multiple servers so you need a centralized place to put the data
  2. You want the data stored persistently so if the server is restarted (normally or abnormally) you will have the recent data

The reasons for not putting it directly in a database:

  1. It's a significant load of new database operations since you have to update the data on every single incoming request.
  2. You can sometimes get the persistence without directly using a database by logging the access to a log file and then running chron jobs that parse the logs and do bulk addition of data to the database. This has a downside in that it's not as easy to query live data (since the most recent data is sitting in databases and hasn't been parsed yet).

For an in-memory store, you could do something like this:

// middleware that keeps track of user access let userAccessMap = new Map(); app.use((req, res, next) => { // get userId from the cookie (substitute your own cookie logic here) let id = id: req.cookie.userID; let lastAccess = Date.now(); // if you want to keep track of more than just lastAccess, // you can store an object of data here instead of just the lastAccess time // To update it, you would get the previous object, update some properties // in it, and then set it back in the userAccessMap userAccessMap.set(id, lastAccess); next(); }); // routinely clean up the userAccessMap to remove old access times // so it doesn't just grow forever const cleanupFrequency = 30 * 60 * 1000; // run cleanup every 30 minutes const cleanupTarget = 24 * 60 * 60 * 1000; // clean out users who haven't been here in the last day setInterval(() => { let now = Date.now(); for (let [id, lastAccess] of userAccessMap.entries()) { if (now - lastAccess > cleanupTarget) { // delete users who haven't been here in a long time userAccessMap.delete(id); } } }, cleanupFrequncy); // Then, create some sort of adminstrative interface (probably with some sort of access protection) // that gives you access to the user access info // This might even be available in a separate web server on a separate port that isn't open to the general publoic app.get("/userAccessData", (req, res) => { // perhaps convert this to a human readable user name by looking up the user id // also may want to sort the data by recentAccess res.json(Array.from(userAccessMap)); }); 
Sign up to request clarification or add additional context in comments.

1 Comment

thanks for the answer! I have a question, what is a reasonable size for a variable like this? and how do you measure the performance? using the process info, like heap size..?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.