with laravel Echo via the PresenceChannel you can achieve that
Getting list of users currently online
I'm trying to figure out the right way to get the list of users currently online on the site. My app uses Social login (through Socialite).
I'm thinking of following approaches -
-
Keep a check on 'last activity' of the user. Every time use clicks on a link on the site, refresh their online status in database (or cache).
-
Track session data. I've no clue how to go about this.
-
Some magical wizardry with web-sockets, maybe?
Please let me know.
@vapenation - I think you are suggesting the option #3. I'll have to look into it. I'm guessing that the site will need to maintain a connection with the user browsing the site.
I'm not sure how practical it will be to have a web-socket connection with every logged-in user. I'm looking at having ~500 - 1000 users logged in simultaneously.
I think this would best be done in middleware. Just update a timestamp for last_active for the user and query users on that field to get who is active. It would be pretty simple.
I'd also cache the results of who is active, maybe with a resolution of 5-10 minutes. You probably don't want that to be realtime as it could put a strain on the server when you have a lot.
Next to websockets (which I wouldn't use if this is all you'd be using it for), I think this would be most accurate.
could be a good use case for a redis store
each access prune old records (eg>20 minutes) then add the user of the current request with their name and a timestamp
pruning could be done by a cron job
Thank you everyone for your quick responses. I think the following would be a nice solution -
- Write a middleware say 'OnlineStatusUpdater' that runs for every request.
- The middleware updates Redis key for the user's online status and adds say about 10 minutes to the expiry of the key.
- That way, I can check if the user is really active at present, with a buffer of 10 minutes.
Accuracy isn't really important because user may be inactive for 10 minutes - say reading a long article on the site.
Update - I decided to go with the middleware approach as suggested by @Snapey . Now I can get the status of any specific user with -
public function isOnline() {
return Cache::get('user_online-' . $this->id);
}
The question however is, how do I go about showing a list of users online? How to retrieve that information from the cache?
easiest way would be to use cache tags: https://laravel.com/docs/5.6/cache#cache-tags
create a tag for 'user_online' or something.
Update: I'm working in this problem again and my latest approach is this -
$user_session_expires_at = Cache::store('redis')->remember('online_user_' . auth()->id(), 60, function() {
return now()->addMinutes(20);
});
The problem now, is how do I go about retrieving the list of all users who are online? Life would be simpler if Redis allowed retrieving records by cache_tags; but it can't unless I tell it the specific key.
Can someone help?
You can scan the redis store but this might be slow as you have to keep calling redis until it runs out of answers.
@Cronix idea of a column on the users table might be performant enough.
Set a last_access column on the users table on every GET request (one DB transaction) then count the number of users with non-null last_access columns. You can cache this figure for a few minutes.
Then, a background job, every 5 minutes, set the last_access field to null for all users whose last_access is not null AND is more than 20 minutes old.
I've approached this from the point of view of counting only. Not sure how practical it would be to list all on-line users since you say "I'm looking at having ~500 - 1000 users logged in simultaneously." If you do want to list them, then scanning the redis store might be an option.
Please or to participate in this conversation.